diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index f034e7c57a7..02e777e3aa7 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -3655,6 +3655,46 @@ ], "url": "/FileAPI/url/url_xmlhttprequest_img.html" }, + { + "path": "compat/webkit-text-fill-color-property-001a.html", + "references": [ + [ + "/compat/webkit-text-fill-color-property-001-ref.html", + "==" + ] + ], + "url": "/compat/webkit-text-fill-color-property-001a.html" + }, + { + "path": "compat/webkit-text-fill-color-property-001b.html", + "references": [ + [ + "/compat/webkit-text-fill-color-property-001-ref.html", + "==" + ] + ], + "url": "/compat/webkit-text-fill-color-property-001b.html" + }, + { + "path": "compat/webkit-text-fill-color-property-001c.html", + "references": [ + [ + "/compat/webkit-text-fill-color-property-001-ref.html", + "==" + ] + ], + "url": "/compat/webkit-text-fill-color-property-001c.html" + }, + { + "path": "compat/webkit-text-fill-color-property-001d.html", + "references": [ + [ + "/compat/webkit-text-fill-color-property-001-ref.html", + "==" + ] + ], + "url": "/compat/webkit-text-fill-color-property-001d.html" + }, { "path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html", "references": [ @@ -4975,6 +5015,16 @@ ], "url": "/html/rendering/non-replaced-elements/the-fieldset-element-0/min-width-not-important.html" }, + { + "path": "html/rendering/non-replaced-elements/the-hr-element-0/align.html", + "references": [ + [ + "/html/rendering/non-replaced-elements/the-hr-element-0/align-ref.html", + "==" + ] + ], + "url": "/html/rendering/non-replaced-elements/the-hr-element-0/align.html" + }, { "path": "html/rendering/non-replaced-elements/the-hr-element-0/color.html", "references": [ @@ -5305,6 +5355,16 @@ ], "url": "/html/semantics/grouping-content/the-pre-element/pre-newline-bidi.html" }, + { + "path": "html/semantics/links/linktypes/alternate-css.html", + "references": [ + [ + "/html/semantics/links/linktypes/alternate-css-ref.html", + "==" + ] + ], + "url": "/html/semantics/links/linktypes/alternate-css.html" + }, { "path": "html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html", "references": [ @@ -5565,26 +5625,6 @@ ], "url": "/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html" }, - { - "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html" - }, { "path": "shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html", "references": [ @@ -5605,16 +5645,6 @@ ], "url": "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html" }, - { - "path": "shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html" - }, { "path": "shadow-dom/untriaged/shadow-trees/shadow-root-001.html", "references": [ @@ -13941,6 +13971,10 @@ "path": "custom-elements/registering-custom-elements/unresolved-elements-interface-svg-element.html", "url": "/custom-elements/registering-custom-elements/unresolved-elements-interface-svg-element.html" }, + { + "path": "dom/collections/HTMLCollection-as-proto-length-get-throws.html", + "url": "/dom/collections/HTMLCollection-as-proto-length-get-throws.html" + }, { "path": "dom/collections/HTMLCollection-empty-name.html", "url": "/dom/collections/HTMLCollection-empty-name.html" @@ -14405,6 +14439,14 @@ "path": "dom/nodes/Element-getElementsByTagNameNS.html", "url": "/dom/nodes/Element-getElementsByTagNameNS.html" }, + { + "path": "dom/nodes/Element-insertAdjacentElement.html", + "url": "/dom/nodes/Element-insertAdjacentElement.html" + }, + { + "path": "dom/nodes/Element-insertAdjacentText.html", + "url": "/dom/nodes/Element-insertAdjacentText.html" + }, { "path": "dom/nodes/Element-lastElementChild-svg.svg", "url": "/dom/nodes/Element-lastElementChild-svg.svg" @@ -14765,6 +14807,10 @@ "path": "dom/nodes/prepend-on-Document.html", "url": "/dom/nodes/prepend-on-Document.html" }, + { + "path": "dom/nodes/remove-unscopable.html", + "url": "/dom/nodes/remove-unscopable.html" + }, { "path": "dom/nodes/rootNode.html", "url": "/dom/nodes/rootNode.html" @@ -19289,6 +19335,10 @@ "path": "html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml", "url": "/html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml" }, + { + "path": "html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html", + "url": "/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html" + }, { "path": "html/semantics/scripting-1/the-script-element/script-onload-string.html", "url": "/html/semantics/scripting-1/the-script-element/script-onload-string.html" @@ -20017,6 +20067,10 @@ "path": "js/builtins/Object.prototype.seal.html", "url": "/js/builtins/Object.prototype.seal.html" }, + { + "path": "js/builtins/Promise-incumbent-global.sub.html", + "url": "/js/builtins/Promise-incumbent-global.sub.html" + }, { "path": "js/builtins/Promise-subclassing.html", "url": "/js/builtins/Promise-subclassing.html" @@ -27665,10 +27719,6 @@ "path": "selection/Document-open.html", "url": "/selection/Document-open.html" }, - { - "path": "selection/collapse.html", - "url": "/selection/collapse.html" - }, { "path": "selection/collapseToStartEnd.html", "url": "/selection/collapseToStartEnd.html" @@ -27677,10 +27727,6 @@ "path": "selection/deleteFromDocument.html", "url": "/selection/deleteFromDocument.html" }, - { - "path": "selection/extend.html", - "url": "/selection/extend.html" - }, { "path": "selection/getRangeAt.html", "url": "/selection/getRangeAt.html" @@ -27725,6 +27771,366 @@ "path": "service-workers/cache-storage/serviceworker/credentials.html", "url": "/service-workers/cache-storage/serviceworker/credentials.html" }, + { + "path": "service-workers/service-worker/ServiceWorkerGlobalScope/close.https.html", + "url": "/service-workers/service-worker/ServiceWorkerGlobalScope/close.https.html" + }, + { + "path": "service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html", + "url": "/service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html" + }, + { + "path": "service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html", + "url": "/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html" + }, + { + "path": "service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html", + "url": "/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html" + }, + { + "path": "service-workers/service-worker/activate-event-after-install-state-change.https.html", + "url": "/service-workers/service-worker/activate-event-after-install-state-change.https.html" + }, + { + "path": "service-workers/service-worker/activation-after-registration.https.html", + "url": "/service-workers/service-worker/activation-after-registration.https.html" + }, + { + "path": "service-workers/service-worker/active.https.html", + "url": "/service-workers/service-worker/active.https.html" + }, + { + "path": "service-workers/service-worker/appcache-ordering-main.https.html", + "url": "/service-workers/service-worker/appcache-ordering-main.https.html" + }, + { + "path": "service-workers/service-worker/claim-not-using-registration.https.html", + "url": "/service-workers/service-worker/claim-not-using-registration.https.html" + }, + { + "path": "service-workers/service-worker/claim-using-registration.https.html", + "url": "/service-workers/service-worker/claim-using-registration.https.html" + }, + { + "path": "service-workers/service-worker/clients-get-cross-origin.https.html", + "url": "/service-workers/service-worker/clients-get-cross-origin.https.html" + }, + { + "path": "service-workers/service-worker/clients-get.https.html", + "url": "/service-workers/service-worker/clients-get.https.html" + }, + { + "path": "service-workers/service-worker/clients-matchall-client-types.https.html", + "url": "/service-workers/service-worker/clients-matchall-client-types.https.html" + }, + { + "path": "service-workers/service-worker/clients-matchall-include-uncontrolled.https.html", + "url": "/service-workers/service-worker/clients-matchall-include-uncontrolled.https.html" + }, + { + "path": "service-workers/service-worker/clients-matchall.https.html", + "url": "/service-workers/service-worker/clients-matchall.https.html" + }, + { + "path": "service-workers/service-worker/controller-on-load.https.html", + "url": "/service-workers/service-worker/controller-on-load.https.html" + }, + { + "path": "service-workers/service-worker/controller-on-reload.https.html", + "url": "/service-workers/service-worker/controller-on-reload.https.html" + }, + { + "path": "service-workers/service-worker/extendable-event-async-waituntil.https.html", + "url": "/service-workers/service-worker/extendable-event-async-waituntil.https.html" + }, + { + "path": "service-workers/service-worker/extendable-event-waituntil.https.html", + "url": "/service-workers/service-worker/extendable-event-waituntil.https.html" + }, + { + "path": "service-workers/service-worker/fetch-canvas-tainting-cache.https.html", + "url": "/service-workers/service-worker/fetch-canvas-tainting-cache.https.html" + }, + { + "path": "service-workers/service-worker/fetch-canvas-tainting.https.html", + "url": "/service-workers/service-worker/fetch-canvas-tainting.https.html" + }, + { + "path": "service-workers/service-worker/fetch-cors-xhr.https.html", + "url": "/service-workers/service-worker/fetch-cors-xhr.https.html" + }, + { + "path": "service-workers/service-worker/fetch-csp.https.html", + "url": "/service-workers/service-worker/fetch-csp.https.html" + }, + { + "path": "service-workers/service-worker/fetch-event-after-navigation-within-page.https.html", + "url": "/service-workers/service-worker/fetch-event-after-navigation-within-page.https.html" + }, + { + "path": "service-workers/service-worker/fetch-event-async-respond-with.https.html", + "url": "/service-workers/service-worker/fetch-event-async-respond-with.https.html" + }, + { + "path": "service-workers/service-worker/fetch-event-network-error.https.html", + "url": "/service-workers/service-worker/fetch-event-network-error.https.html" + }, + { + "path": "service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html", + "url": "/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html" + }, + { + "path": "service-workers/service-worker/fetch-event.https.html", + "url": "/service-workers/service-worker/fetch-event.https.html" + }, + { + "path": "service-workers/service-worker/fetch-header-visibility.https.html", + "url": "/service-workers/service-worker/fetch-header-visibility.https.html" + }, + { + "path": "service-workers/service-worker/fetch-request-css-base-url.https.html", + "url": "/service-workers/service-worker/fetch-request-css-base-url.https.html" + }, + { + "path": "service-workers/service-worker/fetch-request-css-images.https.html", + "url": "/service-workers/service-worker/fetch-request-css-images.https.html" + }, + { + "path": "service-workers/service-worker/fetch-request-fallback.https.html", + "url": "/service-workers/service-worker/fetch-request-fallback.https.html" + }, + { + "path": "service-workers/service-worker/fetch-request-no-freshness-headers.https.html", + "url": "/service-workers/service-worker/fetch-request-no-freshness-headers.https.html" + }, + { + "path": "service-workers/service-worker/fetch-request-resources.https.html", + "url": "/service-workers/service-worker/fetch-request-resources.https.html" + }, + { + "path": "service-workers/service-worker/fetch-request-xhr.https.html", + "url": "/service-workers/service-worker/fetch-request-xhr.https.html" + }, + { + "path": "service-workers/service-worker/fetch-response-xhr.https.html", + "url": "/service-workers/service-worker/fetch-response-xhr.https.html" + }, + { + "path": "service-workers/service-worker/getregistration.https.html", + "url": "/service-workers/service-worker/getregistration.https.html" + }, + { + "path": "service-workers/service-worker/getregistrations.https.html", + "url": "/service-workers/service-worker/getregistrations.https.html" + }, + { + "path": "service-workers/service-worker/indexeddb.https.html", + "url": "/service-workers/service-worker/indexeddb.https.html" + }, + { + "path": "service-workers/service-worker/install-event-type.https.html", + "url": "/service-workers/service-worker/install-event-type.https.html" + }, + { + "path": "service-workers/service-worker/installing.https.html", + "url": "/service-workers/service-worker/installing.https.html" + }, + { + "path": "service-workers/service-worker/interfaces.https.html", + "url": "/service-workers/service-worker/interfaces.https.html" + }, + { + "path": "service-workers/service-worker/invalid-blobtype.https.html", + "url": "/service-workers/service-worker/invalid-blobtype.https.html" + }, + { + "path": "service-workers/service-worker/invalid-header.https.html", + "url": "/service-workers/service-worker/invalid-header.https.html" + }, + { + "path": "service-workers/service-worker/multiple-register.https.html", + "url": "/service-workers/service-worker/multiple-register.https.html" + }, + { + "path": "service-workers/service-worker/multiple-update.https.html", + "url": "/service-workers/service-worker/multiple-update.https.html" + }, + { + "path": "service-workers/service-worker/navigation-redirect.https.html", + "url": "/service-workers/service-worker/navigation-redirect.https.html" + }, + { + "path": "service-workers/service-worker/onactivate-script-error.https.html", + "url": "/service-workers/service-worker/onactivate-script-error.https.html" + }, + { + "path": "service-workers/service-worker/oninstall-script-error.https.html", + "url": "/service-workers/service-worker/oninstall-script-error.https.html" + }, + { + "path": "service-workers/service-worker/performance-timeline.https.html", + "url": "/service-workers/service-worker/performance-timeline.https.html" + }, + { + "path": "service-workers/service-worker/postmessage-msgport-to-client.https.html", + "url": "/service-workers/service-worker/postmessage-msgport-to-client.https.html" + }, + { + "path": "service-workers/service-worker/postmessage-to-client.https.html", + "url": "/service-workers/service-worker/postmessage-to-client.https.html" + }, + { + "path": "service-workers/service-worker/postmessage.https.html", + "url": "/service-workers/service-worker/postmessage.https.html" + }, + { + "path": "service-workers/service-worker/ready.https.html", + "url": "/service-workers/service-worker/ready.https.html" + }, + { + "path": "service-workers/service-worker/referer.https.html", + "url": "/service-workers/service-worker/referer.https.html" + }, + { + "path": "service-workers/service-worker/register-default-scope.https.html", + "url": "/service-workers/service-worker/register-default-scope.https.html" + }, + { + "path": "service-workers/service-worker/register-same-scope-different-script-url.https.html", + "url": "/service-workers/service-worker/register-same-scope-different-script-url.https.html" + }, + { + "path": "service-workers/service-worker/register-wait-forever-in-install-worker.https.html", + "url": "/service-workers/service-worker/register-wait-forever-in-install-worker.https.html" + }, + { + "path": "service-workers/service-worker/registration-end-to-end.https.html", + "url": "/service-workers/service-worker/registration-end-to-end.https.html" + }, + { + "path": "service-workers/service-worker/registration-events.https.html", + "url": "/service-workers/service-worker/registration-events.https.html" + }, + { + "path": "service-workers/service-worker/registration-iframe.https.html", + "url": "/service-workers/service-worker/registration-iframe.https.html" + }, + { + "path": "service-workers/service-worker/registration-service-worker-attributes.https.html", + "url": "/service-workers/service-worker/registration-service-worker-attributes.https.html" + }, + { + "path": "service-workers/service-worker/registration.https.html", + "url": "/service-workers/service-worker/registration.https.html" + }, + { + "path": "service-workers/service-worker/rejections.https.html", + "url": "/service-workers/service-worker/rejections.https.html" + }, + { + "path": "service-workers/service-worker/request-end-to-end.https.html", + "url": "/service-workers/service-worker/request-end-to-end.https.html" + }, + { + "path": "service-workers/service-worker/resource-timing.https.html", + "url": "/service-workers/service-worker/resource-timing.https.html" + }, + { + "path": "service-workers/service-worker/service-worker-csp-connect.https.html", + "url": "/service-workers/service-worker/service-worker-csp-connect.https.html" + }, + { + "path": "service-workers/service-worker/service-worker-csp-default.https.html", + "url": "/service-workers/service-worker/service-worker-csp-default.https.html" + }, + { + "path": "service-workers/service-worker/service-worker-csp-script.https.html", + "url": "/service-workers/service-worker/service-worker-csp-script.https.html" + }, + { + "path": "service-workers/service-worker/serviceworkerobject-scripturl.https.html", + "url": "/service-workers/service-worker/serviceworkerobject-scripturl.https.html" + }, + { + "path": "service-workers/service-worker/shared-worker-controlled.https.html", + "url": "/service-workers/service-worker/shared-worker-controlled.https.html" + }, + { + "path": "service-workers/service-worker/skip-waiting-installed.https.html", + "url": "/service-workers/service-worker/skip-waiting-installed.https.html" + }, + { + "path": "service-workers/service-worker/skip-waiting-using-registration.https.html", + "url": "/service-workers/service-worker/skip-waiting-using-registration.https.html" + }, + { + "path": "service-workers/service-worker/skip-waiting-without-client.https.html", + "url": "/service-workers/service-worker/skip-waiting-without-client.https.html" + }, + { + "path": "service-workers/service-worker/skip-waiting-without-using-registration.https.html", + "url": "/service-workers/service-worker/skip-waiting-without-using-registration.https.html" + }, + { + "path": "service-workers/service-worker/skip-waiting.https.html", + "url": "/service-workers/service-worker/skip-waiting.https.html" + }, + { + "path": "service-workers/service-worker/state.https.html", + "url": "/service-workers/service-worker/state.https.html" + }, + { + "path": "service-workers/service-worker/synced-state.https.html", + "url": "/service-workers/service-worker/synced-state.https.html" + }, + { + "path": "service-workers/service-worker/uncontrolled-page.https.html", + "url": "/service-workers/service-worker/uncontrolled-page.https.html" + }, + { + "path": "service-workers/service-worker/unregister-controller.https.html", + "url": "/service-workers/service-worker/unregister-controller.https.html" + }, + { + "path": "service-workers/service-worker/unregister-then-register-new-script.https.html", + "url": "/service-workers/service-worker/unregister-then-register-new-script.https.html" + }, + { + "path": "service-workers/service-worker/unregister-then-register.https.html", + "url": "/service-workers/service-worker/unregister-then-register.https.html" + }, + { + "path": "service-workers/service-worker/unregister.https.html", + "url": "/service-workers/service-worker/unregister.https.html" + }, + { + "path": "service-workers/service-worker/update-after-navigation-fetch-event.https.html", + "url": "/service-workers/service-worker/update-after-navigation-fetch-event.https.html" + }, + { + "path": "service-workers/service-worker/update-after-oneday.https.html", + "url": "/service-workers/service-worker/update-after-oneday.https.html" + }, + { + "path": "service-workers/service-worker/update.https.html", + "url": "/service-workers/service-worker/update.https.html" + }, + { + "path": "service-workers/service-worker/waiting.https.html", + "url": "/service-workers/service-worker/waiting.https.html" + }, + { + "path": "service-workers/service-worker/websocket.https.html", + "url": "/service-workers/service-worker/websocket.https.html" + }, + { + "path": "service-workers/service-worker/worker-interception.https.html", + "url": "/service-workers/service-worker/worker-interception.https.html" + }, + { + "path": "service-workers/service-worker/xhr.https.html", + "url": "/service-workers/service-worker/xhr.https.html" + }, { "path": "shadow-dom/Element-interface-attachShadow.html", "url": "/shadow-dom/Element-interface-attachShadow.html" @@ -27741,26 +28147,10 @@ "path": "shadow-dom/styles/shadow-cascade-order.html", "url": "/shadow-dom/styles/shadow-cascade-order.html" }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html" - }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html" - }, { "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html", "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html" }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html" - }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html" - }, { "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html", "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html" @@ -27769,18 +28159,10 @@ "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html", "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html" }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html" - }, { "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html", "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html" }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-002.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-002.html" - }, { "path": "shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html", "url": "/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html" @@ -27809,10 +28191,6 @@ "path": "shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html", "url": "/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html" }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html" - }, { "path": "shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html", "url": "/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html" @@ -27833,38 +28211,6 @@ "path": "shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html", "url": "/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html" }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-001.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-001.html" - }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-002.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-002.html" - }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-003.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-003.html" - }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-005.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-005.html" - }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-006.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-006.html" - }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-001.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-001.html" - }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-002.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-002.html" - }, - { - "path": "shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-004.html", - "url": "/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-004.html" - }, { "path": "shadow-dom/untriaged/events/event-dispatch/test-001.html", "url": "/shadow-dom/untriaged/events/event-dispatch/test-001.html" @@ -27881,10 +28227,6 @@ "path": "shadow-dom/untriaged/events/event-retargeting/test-001.html", "url": "/shadow-dom/untriaged/events/event-retargeting/test-001.html" }, - { - "path": "shadow-dom/untriaged/events/event-retargeting/test-002.html", - "url": "/shadow-dom/untriaged/events/event-retargeting/test-002.html" - }, { "path": "shadow-dom/untriaged/events/event-retargeting/test-003.html", "url": "/shadow-dom/untriaged/events/event-retargeting/test-003.html" @@ -27993,70 +28335,10 @@ "path": "shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html", "url": "/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html" }, - { - "path": "shadow-dom/untriaged/shadow-trees/composition/test-001.html", - "url": "/shadow-dom/untriaged/shadow-trees/composition/test-001.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-001.html", - "url": "/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-001.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-002.html", - "url": "/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-002.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/custom-pseudo-elements/test-001.html", - "url": "/shadow-dom/untriaged/shadow-trees/custom-pseudo-elements/test-001.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-003.html", - "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-003.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-003.html", - "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-003.html" - }, { "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html", "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html" }, - { - "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-005.html", - "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-005.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/nested-shadow-trees/test-001.html", - "url": "/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/test-001.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/rendering-shadow-trees/test-001.html", - "url": "/shadow-dom/untriaged/shadow-trees/rendering-shadow-trees/test-001.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/reprojection/test-001.html", - "url": "/shadow-dom/untriaged/shadow-trees/reprojection/test-001.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-001.html", - "url": "/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-001.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-002.html", - "url": "/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-002.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-003.html", - "url": "/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-003.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-004.html", - "url": "/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-004.html" - }, - { - "path": "shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-005.html", - "url": "/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-005.html" - }, { "path": "shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html", "url": "/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html" @@ -28117,14 +28399,6 @@ "path": "shadow-dom/untriaged/styles/css-variables/test-001.html", "url": "/shadow-dom/untriaged/styles/css-variables/test-001.html" }, - { - "path": "shadow-dom/untriaged/styles/deep-combinator/deep-combinator-001.html", - "url": "/shadow-dom/untriaged/styles/deep-combinator/deep-combinator-001.html" - }, - { - "path": "shadow-dom/untriaged/styles/shadow-pseudoelement/shadow-pseudoelement-001.html", - "url": "/shadow-dom/untriaged/styles/shadow-pseudoelement/shadow-pseudoelement-001.html" - }, { "path": "shadow-dom/untriaged/styles/test-001.html", "url": "/shadow-dom/untriaged/styles/test-001.html" @@ -28137,18 +28411,10 @@ "path": "shadow-dom/untriaged/styles/test-005.html", "url": "/shadow-dom/untriaged/styles/test-005.html" }, - { - "path": "shadow-dom/untriaged/styles/test-007.html", - "url": "/shadow-dom/untriaged/styles/test-007.html" - }, { "path": "shadow-dom/untriaged/styles/test-008.html", "url": "/shadow-dom/untriaged/styles/test-008.html" }, - { - "path": "shadow-dom/untriaged/styles/test-009.html", - "url": "/shadow-dom/untriaged/styles/test-009.html" - }, { "path": "shadow-dom/untriaged/styles/test-010.html", "url": "/shadow-dom/untriaged/styles/test-010.html" @@ -28409,6 +28675,14 @@ "path": "web-animations/animatable/animate.html", "url": "/web-animations/animatable/animate.html" }, + { + "path": "web-animations/animation-effect-timing/delay.html", + "url": "/web-animations/animation-effect-timing/delay.html" + }, + { + "path": "web-animations/animation-effect-timing/direction.html", + "url": "/web-animations/animation-effect-timing/direction.html" + }, { "path": "web-animations/animation-effect-timing/duration.html", "url": "/web-animations/animation-effect-timing/duration.html" @@ -28430,36 +28704,8 @@ "url": "/web-animations/animation-effect-timing/iterationStart.html" }, { - "path": "web-animations/animation-node/animation-node-after.html", - "url": "/web-animations/animation-node/animation-node-after.html" - }, - { - "path": "web-animations/animation-node/animation-node-before.html", - "url": "/web-animations/animation-node/animation-node-before.html" - }, - { - "path": "web-animations/animation-node/animation-node-next-sibling.html", - "url": "/web-animations/animation-node/animation-node-next-sibling.html" - }, - { - "path": "web-animations/animation-node/animation-node-parent.html", - "url": "/web-animations/animation-node/animation-node-parent.html" - }, - { - "path": "web-animations/animation-node/animation-node-previous-sibling.html", - "url": "/web-animations/animation-node/animation-node-previous-sibling.html" - }, - { - "path": "web-animations/animation-node/animation-node-remove.html", - "url": "/web-animations/animation-node/animation-node-remove.html" - }, - { - "path": "web-animations/animation-node/animation-node-replace.html", - "url": "/web-animations/animation-node/animation-node-replace.html" - }, - { - "path": "web-animations/animation-node/idlharness.html", - "url": "/web-animations/animation-node/idlharness.html" + "path": "web-animations/animation-effect-timing/iterations.html", + "url": "/web-animations/animation-effect-timing/iterations.html" }, { "path": "web-animations/animation-timeline/document-timeline.html", @@ -28469,10 +28715,30 @@ "path": "web-animations/animation-timeline/idlharness.html", "url": "/web-animations/animation-timeline/idlharness.html" }, + { + "path": "web-animations/animation/cancel.html", + "url": "/web-animations/animation/cancel.html" + }, { "path": "web-animations/animation/constructor.html", "url": "/web-animations/animation/constructor.html" }, + { + "path": "web-animations/animation/finish.html", + "url": "/web-animations/animation/finish.html" + }, + { + "path": "web-animations/animation/play.html", + "url": "/web-animations/animation/play.html" + }, + { + "path": "web-animations/animation/playState.html", + "url": "/web-animations/animation/playState.html" + }, + { + "path": "web-animations/animation/playbackRate.html", + "url": "/web-animations/animation/playbackRate.html" + }, { "path": "web-animations/keyframe-effect/constructor.html", "url": "/web-animations/keyframe-effect/constructor.html" @@ -34513,6 +34779,16 @@ "timeout": "long", "url": "/selection/addRange.html" }, + { + "path": "selection/collapse.html", + "timeout": "long", + "url": "/selection/collapse.html" + }, + { + "path": "selection/extend.html", + "timeout": "long", + "url": "/selection/extend.html" + }, { "path": "service-workers/cache-storage/common.https.html", "timeout": "long", @@ -34643,6 +34919,41 @@ "timeout": "long", "url": "/service-workers/cache-storage/worker/cache-storage.https.html" }, + { + "path": "service-workers/service-worker/fetch-event-redirect.https.html", + "timeout": "long", + "url": "/service-workers/service-worker/fetch-event-redirect.https.html" + }, + { + "path": "service-workers/service-worker/fetch-frame-resource.https.html", + "timeout": "long", + "url": "/service-workers/service-worker/fetch-frame-resource.https.html" + }, + { + "path": "service-workers/service-worker/fetch-mixed-content-to-inscope.https.html", + "timeout": "long", + "url": "/service-workers/service-worker/fetch-mixed-content-to-inscope.https.html" + }, + { + "path": "service-workers/service-worker/fetch-mixed-content-to-outscope.https.html", + "timeout": "long", + "url": "/service-workers/service-worker/fetch-mixed-content-to-outscope.https.html" + }, + { + "path": "service-workers/service-worker/fetch-request-redirect.https.html", + "timeout": "long", + "url": "/service-workers/service-worker/fetch-request-redirect.https.html" + }, + { + "path": "service-workers/service-worker/fetch-waits-for-activate.https.html", + "timeout": "long", + "url": "/service-workers/service-worker/fetch-waits-for-activate.https.html" + }, + { + "path": "service-workers/service-worker/register-closed-window.https.html", + "timeout": "long", + "url": "/service-workers/service-worker/register-closed-window.https.html" + }, { "path": "websockets/binary/002.html", "timeout": "long", @@ -34748,5468 +35059,8 @@ }, "local_changes": { "deleted": [], - "items": { - "reftest": { - "2dcontext/building-paths/canvas_complexshapes_arcto_001.htm": [ - { - "path": "2dcontext/building-paths/canvas_complexshapes_arcto_001.htm", - "references": [ - [ - "/2dcontext/building-paths/canvas_complexshapes_arcto_001-ref.htm", - "==" - ] - ], - "url": "/2dcontext/building-paths/canvas_complexshapes_arcto_001.htm" - } - ], - "2dcontext/building-paths/canvas_complexshapes_beziercurveto_001.htm": [ - { - "path": "2dcontext/building-paths/canvas_complexshapes_beziercurveto_001.htm", - "references": [ - [ - "/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001-ref.htm", - "==" - ] - ], - "url": "/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001.htm" - } - ], - "2dcontext/compositing/canvas_compositing_globalcompositeoperation_001.htm": [ - { - "path": "2dcontext/compositing/canvas_compositing_globalcompositeoperation_001.htm", - "references": [ - [ - "/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001-ref.htm", - "==" - ] - ], - "url": "/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001.htm" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_1.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_1.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_1_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_1.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_10.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_10.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_10_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_10.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_11.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_11.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_11_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_11.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_12.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_12.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_12_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_12.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_2.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_2.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_2_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_2.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_3.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_3.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_3_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_3.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_4.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_4.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_4_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_4.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_5.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_5.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_5_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_5.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_6.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_6.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_6_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_6.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_7.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_7.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_7_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_7.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_8.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_8.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_8_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_8.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_9.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_9.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_9_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_9.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_1.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_1.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_1_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_1.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_10.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_10.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_10_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_10.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_12.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_12.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_12_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_12.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_13.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_13.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_13_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_13.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_2.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_2.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_2_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_2.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_3.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_3.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_3_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_3.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_4.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_4.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_4_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_4.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_5.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_5.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_5_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_5.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_6.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_6.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_6_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_6.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_7.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_7.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_7_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_7.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_8.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_8.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_8_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_8.html" - } - ], - "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_9.html": [ - { - "path": "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_9.html", - "references": [ - [ - "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_9_ref.html", - "==" - ] - ], - "url": "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_9.html" - } - ], - "2dcontext/line-styles/canvas_linestyles_linecap_001.htm": [ - { - "path": "2dcontext/line-styles/canvas_linestyles_linecap_001.htm", - "references": [ - [ - "/2dcontext/line-styles/canvas_linestyles_linecap_001-ref.htm", - "==" - ] - ], - "url": "/2dcontext/line-styles/canvas_linestyles_linecap_001.htm" - } - ], - "2dcontext/line-styles/lineto_a.html": [ - { - "path": "2dcontext/line-styles/lineto_a.html", - "references": [ - [ - "/2dcontext/line-styles/lineto_ref.html", - "==" - ] - ], - "url": "/2dcontext/line-styles/lineto_a.html" - } - ], - "2dcontext/shadows/canvas_shadows_002.htm": [ - { - "path": "2dcontext/shadows/canvas_shadows_002.htm", - "references": [ - [ - "/2dcontext/shadows/canvas_shadows_002-ref.htm", - "==" - ] - ], - "url": "/2dcontext/shadows/canvas_shadows_002.htm" - } - ], - "2dcontext/the-canvas-state/canvas_state_restore_001.htm": [ - { - "path": "2dcontext/the-canvas-state/canvas_state_restore_001.htm", - "references": [ - [ - "/2dcontext/the-canvas-state/canvas_state_restore_001-ref.htm", - "==" - ] - ], - "url": "/2dcontext/the-canvas-state/canvas_state_restore_001.htm" - } - ], - "2dcontext/transformations/canvas_transformations_reset_001.html": [ - { - "path": "2dcontext/transformations/canvas_transformations_reset_001.html", - "references": [ - [ - "/2dcontext/transformations/canvas_transformations_reset_001-ref.html", - "==" - ] - ], - "url": "/2dcontext/transformations/canvas_transformations_reset_001.html" - } - ], - "2dcontext/transformations/canvas_transformations_scale_001.htm": [ - { - "path": "2dcontext/transformations/canvas_transformations_scale_001.htm", - "references": [ - [ - "/2dcontext/transformations/canvas_transformations_scale_001-ref.htm", - "==" - ] - ], - "url": "/2dcontext/transformations/canvas_transformations_scale_001.htm" - } - ], - "2dcontext/transformations/transform_a.html": [ - { - "path": "2dcontext/transformations/transform_a.html", - "references": [ - [ - "/2dcontext/transformations/transform_ref.html", - "==" - ] - ], - "url": "/2dcontext/transformations/transform_a.html" - } - ], - "FileAPI/url/url_xmlhttprequest_img.html": [ - { - "path": "FileAPI/url/url_xmlhttprequest_img.html", - "references": [ - [ - "/FileAPI/url/url_xmlhttprequest_img-ref.html", - "==" - ] - ], - "url": "/FileAPI/url/url_xmlhttprequest_img.html" - } - ], - "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html": [ - { - "path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html", - "references": [ - [ - "/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag-ref.html", - "==" - ] - ], - "url": "/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html" - } - ], - "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag.html": [ - { - "path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag.html", - "references": [ - [ - "/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag-ref.html", - "==" - ] - ], - "url": "/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag.html" - } - ], - "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension.html": [ - { - "path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension.html", - "references": [ - [ - "/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension-ref.html", - "==" - ] - ], - "url": "/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension.html" - } - ], - "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension.html": [ - { - "path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension.html", - "references": [ - [ - "/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension-ref.html", - "==" - ] - ], - "url": "/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-EN-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-EN-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-EN-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-EN-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-EN-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-EN-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-EN-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-EN-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-N-EN-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-N-EN-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-N-EN-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-N-EN-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-N-EN-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-N-EN-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-N-EN-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-N-EN-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-N-EN.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-N-EN.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-N-EN.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-N-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-N-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-N-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-N-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-N-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-N-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-N-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-N-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-bdi-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-bdi-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-bdi-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-bdi-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-bdi-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-bdi-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-bdi-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-bdi-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-dir-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-dir-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-dir-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-dir-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-dir-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-dir-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-dir-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-dir-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-script-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-script-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-script-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-script-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-script-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-script-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-script-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-script-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-style-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-style-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-style-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-style-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-style-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-style-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-style-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-style-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-textarea-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-textarea-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-textarea-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-textarea-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-contained-textarea-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-contained-textarea-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-contained-textarea-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-contained-textarea-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-EN-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-EN-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-EN-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-EN-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-EN-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-EN-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-EN-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-EN-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-N-EN-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-N-EN-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-N-EN-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-N-EN-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-N-EN-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-N-EN-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-N-EN-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-N-EN-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-N-EN.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-N-EN.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-N-EN-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-N-EN.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-N-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-N-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-N-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-N-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-N-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-N-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-N-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-N-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-script-EN-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-script-EN-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-script-EN-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-script-EN-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-script-EN-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-script-EN-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-script-EN-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-script-EN-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-script-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-script-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-script-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-script-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-script-N-EN.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-script-N-EN.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-script-N-EN.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-script-N-L.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-script-N-L.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-script-N-L-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-script-N-L.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-script-N-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-script-N-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-script-N-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-script-N-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-input-script-R.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-input-script-R.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-input-script-R-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-input-script-R.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-isolate.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-isolate.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-isolate-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-isolate.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-pre-N-EN.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-pre-N-EN.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-pre-N-EN-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-pre-N-EN.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-pre-mixed.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-pre-mixed.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-pre-mixed-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-pre-mixed.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-textarea-N-EN.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-textarea-N-EN.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-textarea-N-EN-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-textarea-N-EN.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-textarea-mixed.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-textarea-mixed.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-textarea-mixed-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-textarea-mixed.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs.html" - } - ], - "html/dom/elements/global-attributes/dir_auto-textarea-script-mixed.html": [ - { - "path": "html/dom/elements/global-attributes/dir_auto-textarea-script-mixed.html", - "references": [ - [ - "/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed.html" - } - ], - "html/dom/elements/global-attributes/lang-xmllang-01.html": [ - { - "path": "html/dom/elements/global-attributes/lang-xmllang-01.html", - "references": [ - [ - "/html/dom/elements/global-attributes/lang-xmllang-01-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/lang-xmllang-01.html" - } - ], - "html/dom/elements/global-attributes/lang-xyzzy.html": [ - { - "path": "html/dom/elements/global-attributes/lang-xyzzy.html", - "references": [ - [ - "/html/dom/elements/global-attributes/lang-xyzzy-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/lang-xyzzy.html" - } - ], - "html/dom/elements/global-attributes/style-01.html": [ - { - "path": "html/dom/elements/global-attributes/style-01.html", - "references": [ - [ - "/html/dom/elements/global-attributes/style-01-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/global-attributes/style-01.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-001a.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-001a.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-001-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-001a.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-001b.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-001b.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-001-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-001b.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-001c.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-001c.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-001-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-001c.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002a.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002a.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-002a-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002a.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002b.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002b.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-002b-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002b.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002c.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002c.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-002c-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002c.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-003a.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-003a.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-003-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-003a.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-003b.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-003b.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-003-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-003b.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-003c.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-003c.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-003-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-003c.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-004a.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-004a.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-004-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-004a.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-004b.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-004b.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-004-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-004b.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-004c.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-004c.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-004-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-004c.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-005a.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-005a.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-005-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-005a.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-005b.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-005b.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-005-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-005b.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-005c.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-005c.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-005-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-005c.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006a.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006a.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-006-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006a.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006b.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006b.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-006-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006b.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006c.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006c.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-006c-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006c.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-007a.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-007a.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-007-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-007a.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-007b.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-007b.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-007-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-007b.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-007c.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-007c.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-007-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-007c.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-008a.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-008a.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-008-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-008a.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-008b.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-008b.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-008-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-008b.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-008c.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-008c.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-008-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-008c.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009a.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009a.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-009-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009a.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009b.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009b.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-009b-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009b.html" - } - ], - "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009c.html": [ - { - "path": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009c.html", - "references": [ - [ - "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-009b-ref.html", - "==" - ] - ], - "url": "/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009c.html" - } - ], - "html/editing/the-hidden-attribute/hidden-2.svg": [ - { - "path": "html/editing/the-hidden-attribute/hidden-2.svg", - "references": [ - [ - "/html/editing/the-hidden-attribute/hidden-2-ref.svg", - "==" - ] - ], - "url": "/html/editing/the-hidden-attribute/hidden-2.svg" - } - ], - "html/rendering/bindings/the-input-element-as-a-text-entry-widget/unrecognized-type-should-fallback-as-text-type.html": [ - { - "path": "html/rendering/bindings/the-input-element-as-a-text-entry-widget/unrecognized-type-should-fallback-as-text-type.html", - "references": [ - [ - "/html/rendering/bindings/the-input-element-as-a-text-entry-widget/unrecognized-type-should-fallback-as-text-type-ref.html", - "==" - ] - ], - "url": "/html/rendering/bindings/the-input-element-as-a-text-entry-widget/unrecognized-type-should-fallback-as-text-type.html" - } - ], - "html/rendering/bindings/the-select-element-0/option-label.html": [ - { - "path": "html/rendering/bindings/the-select-element-0/option-label.html", - "references": [ - [ - "/html/rendering/bindings/the-select-element-0/option-label-ref.html", - "==" - ] - ], - "url": "/html/rendering/bindings/the-select-element-0/option-label.html" - } - ], - "html/rendering/bindings/the-textarea-element-0/cols-default.html": [ - { - "path": "html/rendering/bindings/the-textarea-element-0/cols-default.html", - "references": [ - [ - "/html/rendering/bindings/the-textarea-element-0/textarea-ref.html", - "==" - ] - ], - "url": "/html/rendering/bindings/the-textarea-element-0/cols-default.html" - } - ], - "html/rendering/bindings/the-textarea-element-0/cols-zero.html": [ - { - "path": "html/rendering/bindings/the-textarea-element-0/cols-zero.html", - "references": [ - [ - "/html/rendering/bindings/the-textarea-element-0/textarea-ref.html", - "==" - ] - ], - "url": "/html/rendering/bindings/the-textarea-element-0/cols-zero.html" - } - ], - "html/rendering/bindings/the-textarea-element-0/rows-default.html": [ - { - "path": "html/rendering/bindings/the-textarea-element-0/rows-default.html", - "references": [ - [ - "/html/rendering/bindings/the-textarea-element-0/textarea-ref.html", - "==" - ] - ], - "url": "/html/rendering/bindings/the-textarea-element-0/rows-default.html" - } - ], - "html/rendering/bindings/the-textarea-element-0/rows-zero.html": [ - { - "path": "html/rendering/bindings/the-textarea-element-0/rows-zero.html", - "references": [ - [ - "/html/rendering/bindings/the-textarea-element-0/textarea-ref.html", - "==" - ] - ], - "url": "/html/rendering/bindings/the-textarea-element-0/rows-zero.html" - } - ], - "html/rendering/non-replaced-elements/flow-content-0/figure.html": [ - { - "path": "html/rendering/non-replaced-elements/flow-content-0/figure.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/flow-content-0/figure-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/flow-content-0/figure.html" - } - ], - "html/rendering/non-replaced-elements/lists/li-type-supported-xhtml.xhtml": [ - { - "path": "html/rendering/non-replaced-elements/lists/li-type-supported-xhtml.xhtml", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/li-type-supported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/li-type-supported-xhtml.xhtml" - } - ], - "html/rendering/non-replaced-elements/lists/li-type-supported.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/li-type-supported.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/li-type-supported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/li-type-supported.html" - } - ], - "html/rendering/non-replaced-elements/lists/li-type-unsupported-lower-alpha.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/li-type-unsupported-lower-alpha.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/li-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/li-type-unsupported-lower-alpha.html" - } - ], - "html/rendering/non-replaced-elements/lists/li-type-unsupported-lower-roman.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/li-type-unsupported-lower-roman.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/li-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/li-type-unsupported-lower-roman.html" - } - ], - "html/rendering/non-replaced-elements/lists/li-type-unsupported-upper-alpha.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/li-type-unsupported-upper-alpha.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/li-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/li-type-unsupported-upper-alpha.html" - } - ], - "html/rendering/non-replaced-elements/lists/li-type-unsupported-upper-roman.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/li-type-unsupported-upper-roman.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/li-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/li-type-unsupported-upper-roman.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-supported-xhtml.xhtml": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-supported-xhtml.xhtml", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-supported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-supported-xhtml.xhtml" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-supported.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-supported.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-supported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-supported.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-circle.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-circle.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-circle.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-disc.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-disc.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-disc.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-invalid.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-invalid.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-invalid.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-lower-alpha.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-lower-alpha.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-lower-alpha.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-lower-roman.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-lower-roman.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-lower-roman.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-none.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-none.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-none.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-round.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-round.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-round.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-square.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-square.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-square.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-upper-alpha.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-upper-alpha.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-upper-alpha.html" - } - ], - "html/rendering/non-replaced-elements/lists/ol-type-unsupported-upper-roman.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ol-type-unsupported-upper-roman.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ol-type-unsupported-upper-roman.html" - } - ], - "html/rendering/non-replaced-elements/lists/ul-type-supported-xhtml.xhtml": [ - { - "path": "html/rendering/non-replaced-elements/lists/ul-type-supported-xhtml.xhtml", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ul-type-supported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ul-type-supported-xhtml.xhtml" - } - ], - "html/rendering/non-replaced-elements/lists/ul-type-supported.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ul-type-supported.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ul-type-supported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ul-type-supported.html" - } - ], - "html/rendering/non-replaced-elements/lists/ul-type-unsupported-decimal.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ul-type-unsupported-decimal.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-decimal.html" - } - ], - "html/rendering/non-replaced-elements/lists/ul-type-unsupported-invalid.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ul-type-unsupported-invalid.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-invalid.html" - } - ], - "html/rendering/non-replaced-elements/lists/ul-type-unsupported-lower-alpha.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ul-type-unsupported-lower-alpha.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-lower-alpha.html" - } - ], - "html/rendering/non-replaced-elements/lists/ul-type-unsupported-lower-roman.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ul-type-unsupported-lower-roman.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-lower-roman.html" - } - ], - "html/rendering/non-replaced-elements/lists/ul-type-unsupported-upper-alpha.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ul-type-unsupported-upper-alpha.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-upper-alpha.html" - } - ], - "html/rendering/non-replaced-elements/lists/ul-type-unsupported-upper-roman.html": [ - { - "path": "html/rendering/non-replaced-elements/lists/ul-type-unsupported-upper-roman.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/lists/ul-type-unsupported-upper-roman.html" - } - ], - "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-a.html": [ - { - "path": "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-a.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-a.html" - } - ], - "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-q.html": [ - { - "path": "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-q.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-q.html" - } - ], - "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-s.html": [ - { - "path": "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-s.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-s.html" - } - ], - "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-x.xhtml": [ - { - "path": "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-x.xhtml", - "references": [ - [ - "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/001-x.xhtml" - } - ], - "html/rendering/non-replaced-elements/tables/table-border-1.html": [ - { - "path": "html/rendering/non-replaced-elements/tables/table-border-1.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/tables/table-border-1-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/tables/table-border-1.html" - } - ], - "html/rendering/non-replaced-elements/tables/table-border-2.html": [ - { - "path": "html/rendering/non-replaced-elements/tables/table-border-2.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/tables/table-border-2-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/tables/table-border-2.html" - } - ], - "html/rendering/non-replaced-elements/tables/table-cell-width-s.html": [ - { - "path": "html/rendering/non-replaced-elements/tables/table-cell-width-s.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/tables/table-cell-width-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/tables/table-cell-width-s.html" - } - ], - "html/rendering/non-replaced-elements/tables/table-cell-width.html": [ - { - "path": "html/rendering/non-replaced-elements/tables/table-cell-width.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/tables/table-cell-width-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/tables/table-cell-width.html" - } - ], - "html/rendering/non-replaced-elements/tables/table-layout.html": [ - { - "path": "html/rendering/non-replaced-elements/tables/table-layout.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/tables/table-layout-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/tables/table-layout.html" - } - ], - "html/rendering/non-replaced-elements/tables/table-width-150percent.html": [ - { - "path": "html/rendering/non-replaced-elements/tables/table-width-150percent.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/tables/table-width-150percent-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/tables/table-width-150percent.html" - } - ], - "html/rendering/non-replaced-elements/tables/table-width-s.html": [ - { - "path": "html/rendering/non-replaced-elements/tables/table-width-s.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/tables/table-width-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/tables/table-width-s.html" - } - ], - "html/rendering/non-replaced-elements/tables/table-width.html": [ - { - "path": "html/rendering/non-replaced-elements/tables/table-width.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/tables/table-width-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/tables/table-width.html" - } - ], - "html/rendering/non-replaced-elements/the-fieldset-element-0/min-width-not-important.html": [ - { - "path": "html/rendering/non-replaced-elements/the-fieldset-element-0/min-width-not-important.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/the-fieldset-element-0/ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/the-fieldset-element-0/min-width-not-important.html" - } - ], - "html/rendering/non-replaced-elements/the-hr-element-0/align.html": [ - { - "path": "html/rendering/non-replaced-elements/the-hr-element-0/align.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/the-hr-element-0/align-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/the-hr-element-0/align.html" - } - ], - "html/rendering/non-replaced-elements/the-hr-element-0/color.html": [ - { - "path": "html/rendering/non-replaced-elements/the-hr-element-0/color.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/the-hr-element-0/color-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/the-hr-element-0/color.html" - } - ], - "html/rendering/non-replaced-elements/the-hr-element-0/width.html": [ - { - "path": "html/rendering/non-replaced-elements/the-hr-element-0/width.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/the-hr-element-0/width-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/the-hr-element-0/width.html" - } - ], - "html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml": [ - { - "path": "html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml", - "references": [ - [ - "/html/rendering/non-replaced-elements/the-page/body_text_00ffff-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml" - } - ], - "html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim.html": [ - { - "path": "html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim.html", - "references": [ - [ - "/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim-ref.html", - "==" - ] - ], - "url": "/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim.html" - } - ], - "html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml": [ - { - "path": "html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml", - "references": [ - [ - "/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border-ref.xhtml", - "==" - ] - ], - "url": "/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml" - } - ], - "html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml": [ - { - "path": "html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml", - "references": [ - [ - "/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml", - "==" - ] - ], - "url": "/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml" - } - ], - "html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml": [ - { - "path": "html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml", - "references": [ - [ - "/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml", - "==" - ] - ], - "url": "/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml" - } - ], - "html/rendering/replaced-elements/images/space.html": [ - { - "path": "html/rendering/replaced-elements/images/space.html", - "references": [ - [ - "/html/rendering/replaced-elements/images/space-ref.html", - "==" - ] - ], - "url": "/html/rendering/replaced-elements/images/space.html" - } - ], - "html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml": [ - { - "path": "html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml", - "references": [ - [ - "/html/semantics/document-metadata/the-style-element/html_style_in_comment-ref.html", - "==" - ] - ], - "url": "/html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml" - } - ], - "html/semantics/embedded-content/the-audio-element/audio_001.htm": [ - { - "path": "html/semantics/embedded-content/the-audio-element/audio_001.htm", - "references": [ - [ - "/html/semantics/embedded-content/the-audio-element/audio_content-ref.htm", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-audio-element/audio_001.htm" - } - ], - "html/semantics/embedded-content/the-audio-element/audio_002.htm": [ - { - "path": "html/semantics/embedded-content/the-audio-element/audio_002.htm", - "references": [ - [ - "/html/semantics/embedded-content/the-audio-element/audio_content-ref.htm", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-audio-element/audio_002.htm" - } - ], - "html/semantics/embedded-content/the-embed-element/embed-represent-nothing-01.html": [ - { - "path": "html/semantics/embedded-content/the-embed-element/embed-represent-nothing-01.html", - "references": [ - [ - "/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-ref.html", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-01.html" - } - ], - "html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html": [ - { - "path": "html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html", - "references": [ - [ - "/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-ref.html", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html" - } - ], - "html/semantics/embedded-content/the-embed-element/embed-represent-nothing-03.html": [ - { - "path": "html/semantics/embedded-content/the-embed-element/embed-represent-nothing-03.html", - "references": [ - [ - "/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-ref.html", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-03.html" - } - ], - "html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html": [ - { - "path": "html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html", - "references": [ - [ - "/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-ref.html", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html" - } - ], - "html/semantics/embedded-content/the-video-element/video_content_image.htm": [ - { - "path": "html/semantics/embedded-content/the-video-element/video_content_image.htm", - "references": [ - [ - "/html/semantics/embedded-content/the-video-element/video_content-ref.htm", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-video-element/video_content_image.htm" - } - ], - "html/semantics/embedded-content/the-video-element/video_content_text.htm": [ - { - "path": "html/semantics/embedded-content/the-video-element/video_content_text.htm", - "references": [ - [ - "/html/semantics/embedded-content/the-video-element/video_content-ref.htm", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-video-element/video_content_text.htm" - } - ], - "html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm": [ - { - "path": "html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm", - "references": [ - [ - "/html/semantics/embedded-content/the-video-element/video_dynamic_poster-ref.htm", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm" - } - ], - "html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm": [ - { - "path": "html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm", - "references": [ - [ - "/html/semantics/embedded-content/the-video-element/video_dynamic_poster-ref.htm", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm" - } - ], - "html/semantics/embedded-content/the-video-element/video_initially_paused.html": [ - { - "path": "html/semantics/embedded-content/the-video-element/video_initially_paused.html", - "references": [ - [ - "/html/semantics/embedded-content/the-video-element/video_initially_paused-ref.html", - "==" - ] - ], - "url": "/html/semantics/embedded-content/the-video-element/video_initially_paused.html" - } - ], - "html/semantics/forms/the-input-element/image01.html": [ - { - "path": "html/semantics/forms/the-input-element/image01.html", - "references": [ - [ - "/html/semantics/forms/the-input-element/image01-ref.html", - "==" - ] - ], - "url": "/html/semantics/forms/the-input-element/image01.html" - } - ], - "html/semantics/forms/the-textarea-element/textarea-newline-bidi.html": [ - { - "path": "html/semantics/forms/the-textarea-element/textarea-newline-bidi.html", - "references": [ - [ - "/html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html", - "==" - ] - ], - "url": "/html/semantics/forms/the-textarea-element/textarea-newline-bidi.html" - } - ], - "html/semantics/grouping-content/the-li-element/grouping-li-reftest-002.html": [ - { - "path": "html/semantics/grouping-content/the-li-element/grouping-li-reftest-002.html", - "references": [ - [ - "/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002-ref.html", - "==" - ] - ], - "url": "/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002.html" - } - ], - "html/semantics/grouping-content/the-ol-element/reversed-2.html": [ - { - "path": "html/semantics/grouping-content/the-ol-element/reversed-2.html", - "references": [ - [ - "/html/semantics/grouping-content/the-ol-element/reversed-2-ref.html", - "==" - ] - ], - "url": "/html/semantics/grouping-content/the-ol-element/reversed-2.html" - } - ], - "html/semantics/grouping-content/the-pre-element/pre-newline-bidi.html": [ - { - "path": "html/semantics/grouping-content/the-pre-element/pre-newline-bidi.html", - "references": [ - [ - "/html/semantics/grouping-content/the-pre-element/pre-newline-bidi-ref.html", - "==" - ] - ], - "url": "/html/semantics/grouping-content/the-pre-element/pre-newline-bidi.html" - } - ], - "html/semantics/links/linktypes/alternate-css.html": [ - { - "path": "html/semantics/links/linktypes/alternate-css.html", - "references": [ - [ - "/html/semantics/links/linktypes/alternate-css-ref.html", - "==" - ] - ], - "url": "/html/semantics/links/linktypes/alternate-css.html" - } - ], - "html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html": [ - { - "path": "html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html", - "references": [ - [ - "/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html", - "==" - ] - ], - "url": "/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html" - } - ], - "html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html": [ - { - "path": "html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html", - "references": [ - [ - "/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html", - "==" - ] - ], - "url": "/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html" - } - ], - "html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html": [ - { - "path": "html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html", - "references": [ - [ - "/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html", - "==" - ] - ], - "url": "/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped.html" - } - ], - "html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container.html" - } - ], - "html/semantics/text-level-semantics/the-bdo-element/bdo-child.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdo-element/bdo-child.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdo-element/bidi-001-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdo-element/bdo-child.html" - } - ], - "html/semantics/text-level-semantics/the-bdo-element/bdo-ltr.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdo-element/bdo-ltr.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdo-element/bidi-001-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdo-element/bdo-ltr.html" - } - ], - "html/semantics/text-level-semantics/the-bdo-element/bdo-override.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdo-element/bdo-override.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdo-element/bidi-001-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdo-element/bdo-override.html" - } - ], - "html/semantics/text-level-semantics/the-bdo-element/bidi-001.html": [ - { - "path": "html/semantics/text-level-semantics/the-bdo-element/bidi-001.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-bdo-element/bidi-001-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-bdo-element/bidi-001.html" - } - ], - "html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors.html": [ - { - "path": "html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors.html" - } - ], - "html/semantics/text-level-semantics/the-br-element/br-bidi.html": [ - { - "path": "html/semantics/text-level-semantics/the-br-element/br-bidi.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-br-element/br-bidi-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-br-element/br-bidi.html" - } - ], - "html/semantics/text-level-semantics/the-wbr-element/wbr-element.html": [ - { - "path": "html/semantics/text-level-semantics/the-wbr-element/wbr-element.html", - "references": [ - [ - "/html/semantics/text-level-semantics/the-wbr-element/wbr-element-ref.html", - "==" - ] - ], - "url": "/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html" - } - ], - "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html" - } - ], - "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html" - } - ], - "shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html" - } - ], - "shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html" - } - ], - "shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html" - } - ], - "shadow-dom/untriaged/shadow-trees/shadow-root-001.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/shadow-root-001.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/shadow-root-001-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/shadow-root-001.html" - } - ], - "shadow-dom/untriaged/shadow-trees/shadow-root-002.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/shadow-root-002.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/shadow-root-002-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/shadow-root-002.html" - } - ], - "shadow-dom/untriaged/shadow-trees/text-decoration-001.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/text-decoration-001.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/text-decoration-001-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/text-decoration-001.html" - } - ], - "shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html": [ - { - "path": "shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html", - "references": [ - [ - "/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/2_tracks.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/2_tracks.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/2_tracks-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/2_tracks.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/3_tracks.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/3_tracks.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/3_tracks-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/3_tracks.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_end.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_end.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_end-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_end.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_end_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_end_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_middle.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_middle.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_middle-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_middle.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_middle_position_50.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_middle_position_50.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_start.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_start.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_start-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_start.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/align_start_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/align_start_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/basic.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/basic.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/basic-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/basic.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/cue_too_long.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/cue_too_long.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/cue_too_long-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/cue_too_long.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/evil/media_height_19.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/evil/media_height_19.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/evil/single_quote.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/evil/single_quote.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/evil/single_quote-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/evil/single_quote.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/evil/size_90.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/evil/size_90.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/evil/size_90-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/evil/size_90.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/evil/size_99.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/evil/size_99.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/evil/size_99-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/evil/size_99.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/line_0_is_top.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/line_0_is_top.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/line_0_is_top-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/line_0_is_top.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/line_50_percent.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/line_50_percent.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/line_50_percent-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/line_50_percent.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/media_with_controls.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/media_with_controls.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/media_with_controls-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/media_with_controls.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/navigate_cue_position.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/navigate_cue_position.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/repaint.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/repaint.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/repaint-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/repaint.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/size_50.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/size_50.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/size_50-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/size_50.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/too_many_cues.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/too_many_cues.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/too_many_cues-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/too_many_cues.html" - } - ], - "webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html": [ - { - "path": "webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html", - "references": [ - [ - "/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped-ref.html", - "==" - ] - ], - "url": "/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html" - } - ] - }, - "testharness": { - "html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html": [ - { - "path": "html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html", - "url": "/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html" - } - ] - } - }, - "reftest_nodes": { - "html/rendering/non-replaced-elements/the-hr-element-0/align.html": [ - { - "path": "html/rendering/non-replaced-elements/the-hr-element-0/align.html", - "references": [ - [ - "/html/rendering/non-replaced-elements/the-hr-element-0/align-ref.html", - "==" - ] - ], - "url": "/html/rendering/non-replaced-elements/the-hr-element-0/align.html" - } - ], - "html/semantics/links/linktypes/alternate-css-ref.html": [ - { - "path": "html/semantics/links/linktypes/alternate-css-ref.html", - "references": [ - [ - "/html/semantics/links/linktypes/alternate-css-ref.html", - "==" - ] - ], - "url": "/html/semantics/links/linktypes/alternate-css-ref.html" - } - ], - "html/semantics/links/linktypes/alternate-css.html": [ - { - "path": "html/semantics/links/linktypes/alternate-css.html", - "references": [ - [ - "/html/semantics/links/linktypes/alternate-css-ref.html", - "==" - ] - ], - "url": "/html/semantics/links/linktypes/alternate-css.html" - } - ] - } + "items": {}, + "reftest_nodes": {} }, "reftest_nodes": { "2dcontext/building-paths/canvas_complexshapes_arcto_001.htm": [ @@ -40656,6 +35507,54 @@ "url": "/FileAPI/url/url_xmlhttprequest_img.html" } ], + "compat/webkit-text-fill-color-property-001a.html": [ + { + "path": "compat/webkit-text-fill-color-property-001a.html", + "references": [ + [ + "/compat/webkit-text-fill-color-property-001-ref.html", + "==" + ] + ], + "url": "/compat/webkit-text-fill-color-property-001a.html" + } + ], + "compat/webkit-text-fill-color-property-001b.html": [ + { + "path": "compat/webkit-text-fill-color-property-001b.html", + "references": [ + [ + "/compat/webkit-text-fill-color-property-001-ref.html", + "==" + ] + ], + "url": "/compat/webkit-text-fill-color-property-001b.html" + } + ], + "compat/webkit-text-fill-color-property-001c.html": [ + { + "path": "compat/webkit-text-fill-color-property-001c.html", + "references": [ + [ + "/compat/webkit-text-fill-color-property-001-ref.html", + "==" + ] + ], + "url": "/compat/webkit-text-fill-color-property-001c.html" + } + ], + "compat/webkit-text-fill-color-property-001d.html": [ + { + "path": "compat/webkit-text-fill-color-property-001d.html", + "references": [ + [ + "/compat/webkit-text-fill-color-property-001-ref.html", + "==" + ] + ], + "url": "/compat/webkit-text-fill-color-property-001d.html" + } + ], "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html": [ { "path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html", @@ -42780,6 +37679,18 @@ "url": "/html/rendering/non-replaced-elements/the-fieldset-element-0/min-width-not-important.html" } ], + "html/rendering/non-replaced-elements/the-hr-element-0/align.html": [ + { + "path": "html/rendering/non-replaced-elements/the-hr-element-0/align.html", + "references": [ + [ + "/html/rendering/non-replaced-elements/the-hr-element-0/align-ref.html", + "==" + ] + ], + "url": "/html/rendering/non-replaced-elements/the-hr-element-0/align.html" + } + ], "html/rendering/non-replaced-elements/the-hr-element-0/color.html": [ { "path": "html/rendering/non-replaced-elements/the-hr-element-0/color.html", @@ -43284,6 +38195,30 @@ "url": "/html/semantics/grouping-content/the-pre-element/pre-newline-bidi.html" } ], + "html/semantics/links/linktypes/alternate-css-ref.html": [ + { + "path": "html/semantics/links/linktypes/alternate-css-ref.html", + "references": [ + [ + "/html/semantics/links/linktypes/alternate-css-ref.html", + "==" + ] + ], + "url": "/html/semantics/links/linktypes/alternate-css-ref.html" + } + ], + "html/semantics/links/linktypes/alternate-css.html": [ + { + "path": "html/semantics/links/linktypes/alternate-css.html", + "references": [ + [ + "/html/semantics/links/linktypes/alternate-css-ref.html", + "==" + ] + ], + "url": "/html/semantics/links/linktypes/alternate-css.html" + } + ], "html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html": [ { "path": "html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html", @@ -43596,30 +38531,6 @@ "url": "/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html" } ], - "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html" - } - ], - "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html" - } - ], "shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html": [ { "path": "shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html", @@ -43644,18 +38555,6 @@ "url": "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html" } ], - "shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html": [ - { - "path": "shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html", - "references": [ - [ - "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002-ref.html", - "==" - ] - ], - "url": "/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html" - } - ], "shadow-dom/untriaged/shadow-trees/shadow-root-001.html": [ { "path": "shadow-dom/untriaged/shadow-trees/shadow-root-001.html", @@ -46357,7 +41256,7 @@ } ] }, - "rev": "15ad8eaadd91425cc9331b2e658d4c2796ae5ad8", + "rev": "d011702f368b88b3bae86e7a8fd2ddd22e18b33c", "url_base": "/", "version": 3 } diff --git a/tests/wpt/metadata/XMLHttpRequest/setrequestheader-bogus-value.htm.ini b/tests/wpt/metadata/XMLHttpRequest/setrequestheader-bogus-value.htm.ini deleted file mode 100644 index d04386464d1..00000000000 --- a/tests/wpt/metadata/XMLHttpRequest/setrequestheader-bogus-value.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[setrequestheader-bogus-value.htm] - type: testharness - [XMLHttpRequest: setRequestHeader() value argument checks 4] - expected: FAIL - diff --git a/tests/wpt/metadata/dom/collections/HTMLCollection-as-proto-length-get-throws.html.ini b/tests/wpt/metadata/dom/collections/HTMLCollection-as-proto-length-get-throws.html.ini new file mode 100644 index 00000000000..0e56cb9f2f3 --- /dev/null +++ b/tests/wpt/metadata/dom/collections/HTMLCollection-as-proto-length-get-throws.html.ini @@ -0,0 +1,5 @@ +[HTMLCollection-as-proto-length-get-throws.html] + type: testharness + [HTMLcollection as a prototype should not allow getting .length on the base object] + expected: FAIL + diff --git a/tests/wpt/metadata/dom/interfaces.html.ini b/tests/wpt/metadata/dom/interfaces.html.ini index 0c273da2dfb..4cdad8a3627 100644 --- a/tests/wpt/metadata/dom/interfaces.html.ini +++ b/tests/wpt/metadata/dom/interfaces.html.ini @@ -207,3 +207,9 @@ [Node interface: document.createComment("abc") must inherit property "rootNode" with the proper type (16)] expected: FAIL + [Element interface: element must inherit property "query" with the proper type (36)] + expected: FAIL + + [Element interface: element must inherit property "queryAll" with the proper type (37)] + expected: FAIL + diff --git a/tests/wpt/metadata/dom/nodes/Document-getElementsByTagName.html.ini b/tests/wpt/metadata/dom/nodes/Document-getElementsByTagName.html.ini index 849409e0fe6..3abe2d9b08f 100644 --- a/tests/wpt/metadata/dom/nodes/Document-getElementsByTagName.html.ini +++ b/tests/wpt/metadata/dom/nodes/Document-getElementsByTagName.html.ini @@ -3,3 +3,9 @@ [Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)] expected: FAIL + [Element in non-HTML namespace, prefix, lowercase name] + expected: FAIL + + [Element in non-HTML namespace, prefix, uppercase name] + expected: FAIL + diff --git a/tests/wpt/metadata/dom/nodes/Element-classlist.html.ini b/tests/wpt/metadata/dom/nodes/Element-classlist.html.ini new file mode 100644 index 00000000000..3f1125fd479 --- /dev/null +++ b/tests/wpt/metadata/dom/nodes/Element-classlist.html.ini @@ -0,0 +1,8 @@ +[Element-classlist.html] + type: testharness + [.contains(empty_string) must return false] + expected: FAIL + + [.contains(string_with_spaces) must return false] + expected: FAIL + diff --git a/tests/wpt/metadata/dom/nodes/Element-getElementsByTagName.html.ini b/tests/wpt/metadata/dom/nodes/Element-getElementsByTagName.html.ini index 5cda7ac70ed..55701c6264d 100644 --- a/tests/wpt/metadata/dom/nodes/Element-getElementsByTagName.html.ini +++ b/tests/wpt/metadata/dom/nodes/Element-getElementsByTagName.html.ini @@ -3,3 +3,9 @@ [Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)] expected: FAIL + [Element in non-HTML namespace, prefix, lowercase name] + expected: FAIL + + [Element in non-HTML namespace, prefix, uppercase name] + expected: FAIL + diff --git a/tests/wpt/metadata/dom/nodes/case.html.ini b/tests/wpt/metadata/dom/nodes/case.html.ini new file mode 100644 index 00000000000..e7dd2689077 --- /dev/null +++ b/tests/wpt/metadata/dom/nodes/case.html.ini @@ -0,0 +1,17 @@ +[case.html] + type: testharness + [getElementsByTagName a:abc] + expected: FAIL + + [getElementsByTagName a:Abc] + expected: FAIL + + [getElementsByTagName a:ABC] + expected: FAIL + + [getElementsByTagName a:ä] + expected: FAIL + + [getElementsByTagName a:Ä] + expected: FAIL + diff --git a/tests/wpt/metadata/dom/nodes/remove-unscopable.html.ini b/tests/wpt/metadata/dom/nodes/remove-unscopable.html.ini new file mode 100644 index 00000000000..bd66b155deb --- /dev/null +++ b/tests/wpt/metadata/dom/nodes/remove-unscopable.html.ini @@ -0,0 +1,5 @@ +[remove-unscopable.html] + type: testharness + [remove() should be unscopable] + expected: FAIL + diff --git a/tests/wpt/metadata/encoding/api-basics.html.ini b/tests/wpt/metadata/encoding/api-basics.html.ini index eb82a3047c9..df28ac82e8a 100644 --- a/tests/wpt/metadata/encoding/api-basics.html.ini +++ b/tests/wpt/metadata/encoding/api-basics.html.ini @@ -12,3 +12,12 @@ [Encode/decode round trip: utf-16] expected: FAIL + [Decode sample: utf-16le] + expected: FAIL + + [Decode sample: utf-16be] + expected: FAIL + + [Decode sample: utf-16] + expected: FAIL + diff --git a/tests/wpt/metadata/encoding/textdecoder-streaming.html.ini b/tests/wpt/metadata/encoding/textdecoder-streaming.html.ini index 401997d8036..72333e5be3a 100644 --- a/tests/wpt/metadata/encoding/textdecoder-streaming.html.ini +++ b/tests/wpt/metadata/encoding/textdecoder-streaming.html.ini @@ -18,3 +18,30 @@ [Streaming decode: utf-16be, 5 byte window] expected: FAIL + [Streaming decode: utf-8, 1 byte window] + expected: FAIL + + [Streaming decode: utf-8, 2 byte window] + expected: FAIL + + [Streaming decode: utf-8, 3 byte window] + expected: FAIL + + [Streaming decode: utf-8, 4 byte window] + expected: FAIL + + [Streaming decode: utf-8, 5 byte window] + expected: FAIL + + [Streaming decode: utf-16le, 2 byte window] + expected: FAIL + + [Streaming decode: utf-16le, 4 byte window] + expected: FAIL + + [Streaming decode: utf-16be, 2 byte window] + expected: FAIL + + [Streaming decode: utf-16be, 4 byte window] + expected: FAIL + diff --git a/tests/wpt/metadata/encoding/textencoder-constructor-non-utf.html.ini b/tests/wpt/metadata/encoding/textencoder-constructor-non-utf.html.ini new file mode 100644 index 00000000000..1e475829d28 --- /dev/null +++ b/tests/wpt/metadata/encoding/textencoder-constructor-non-utf.html.ini @@ -0,0 +1,119 @@ +[textencoder-constructor-non-utf.html] + type: testharness + [Encoding argument not considered for encode: ibm866] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-2] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-3] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-4] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-5] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-6] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-7] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-8] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-8-i] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-10] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-13] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-14] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-15] + expected: FAIL + + [Encoding argument not considered for encode: iso-8859-16] + expected: FAIL + + [Encoding argument not considered for encode: koi8-r] + expected: FAIL + + [Encoding argument not considered for encode: koi8-u] + expected: FAIL + + [Encoding argument not considered for encode: macintosh] + expected: FAIL + + [Encoding argument not considered for encode: windows-874] + expected: FAIL + + [Encoding argument not considered for encode: windows-1250] + expected: FAIL + + [Encoding argument not considered for encode: windows-1251] + expected: FAIL + + [Encoding argument not considered for encode: windows-1252] + expected: FAIL + + [Encoding argument not considered for encode: windows-1253] + expected: FAIL + + [Encoding argument not considered for encode: windows-1254] + expected: FAIL + + [Encoding argument not considered for encode: windows-1255] + expected: FAIL + + [Encoding argument not considered for encode: windows-1256] + expected: FAIL + + [Encoding argument not considered for encode: windows-1257] + expected: FAIL + + [Encoding argument not considered for encode: windows-1258] + expected: FAIL + + [Encoding argument not considered for encode: x-mac-cyrillic] + expected: FAIL + + [Encoding argument not considered for encode: gbk] + expected: FAIL + + [Encoding argument not considered for encode: gb18030] + expected: FAIL + + [Encoding argument not considered for encode: big5] + expected: FAIL + + [Encoding argument not considered for encode: euc-jp] + expected: FAIL + + [Encoding argument not considered for encode: iso-2022-jp] + expected: FAIL + + [Encoding argument not considered for encode: shift_jis] + expected: FAIL + + [Encoding argument not considered for encode: euc-kr] + expected: FAIL + + [Encoding argument not considered for encode: replacement] + expected: FAIL + + [Encoding argument not considered for encode: utf-16be] + expected: FAIL + + [Encoding argument not considered for encode: utf-16le] + expected: FAIL + + [Encoding argument not considered for encode: x-user-defined] + expected: FAIL + diff --git a/tests/wpt/metadata/mozilla-sync b/tests/wpt/metadata/mozilla-sync index a5890f0d625..042374c3deb 100644 --- a/tests/wpt/metadata/mozilla-sync +++ b/tests/wpt/metadata/mozilla-sync @@ -1 +1 @@ -0397e2a24d3e5c988b089ef100002397f4cabdfa \ No newline at end of file +f9608022caf7f223dfdfe960c31fb5fe7eb0d1f1 \ No newline at end of file diff --git a/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini b/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini index 3054ff5b380..1733d692fa9 100644 --- a/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini +++ b/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini @@ -792,3 +792,9 @@ [Parsing: against ] expected: FAIL + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + diff --git a/tests/wpt/metadata/url/a-element.html.ini b/tests/wpt/metadata/url/a-element.html.ini index b4f11adcb34..f4a3706ae28 100644 --- a/tests/wpt/metadata/url/a-element.html.ini +++ b/tests/wpt/metadata/url/a-element.html.ini @@ -792,3 +792,9 @@ [Parsing: against ] expected: FAIL + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + diff --git a/tests/wpt/metadata/url/url-constructor.html.ini b/tests/wpt/metadata/url/url-constructor.html.ini index e9f116005c1..04058f5ebbd 100644 --- a/tests/wpt/metadata/url/url-constructor.html.ini +++ b/tests/wpt/metadata/url/url-constructor.html.ini @@ -198,3 +198,15 @@ [Parsing: against ] expected: FAIL + [URL.searchParams updating, clearing] + expected: FAIL + + [URL.searchParams and URL.search setters, update propagation] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-value.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-value.htm index 3d23e164bc0..c3aa076c971 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-value.htm +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-value.htm @@ -12,16 +12,20 @@ + + diff --git a/tests/wpt/web-platform-tests/dom/interfaces.html b/tests/wpt/web-platform-tests/dom/interfaces.html index 0efb52fd497..45dd97e2f50 100644 --- a/tests/wpt/web-platform-tests/dom/interfaces.html +++ b/tests/wpt/web-platform-tests/dom/interfaces.html @@ -310,6 +310,9 @@ interface Element : Node { HTMLCollection getElementsByTagName(DOMString localName); HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); HTMLCollection getElementsByClassName(DOMString classNames); + + Element? insertAdjacentElement(DOMString where, Element element); // historical + void insertAdjacentText(DOMString where, DOMString data); // historical }; interface NamedNodeMap { diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js b/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js index cc2b73646ef..3d206062d3a 100644 --- a/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js +++ b/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js @@ -127,17 +127,19 @@ function test_getElementsByTagName(context, element) { test(function() { var t = element.appendChild(document.createElementNS("test", "te:st")) this.add_cleanup(function() {element.removeChild(t)}) - assert_array_equals(context.getElementsByTagName("st"), [t]) + assert_array_equals(context.getElementsByTagName("st"), []) assert_array_equals(context.getElementsByTagName("ST"), []) + assert_array_equals(context.getElementsByTagName("te:st"), [t]) + assert_array_equals(context.getElementsByTagName("te:ST"), []) }, "Element in non-HTML namespace, prefix, lowercase name") test(function() { var t = element.appendChild(document.createElementNS("test", "te:ST")) this.add_cleanup(function() {element.removeChild(t)}) - assert_array_equals(context.getElementsByTagName("ST"), [t]) assert_array_equals(context.getElementsByTagName("st"), []) + assert_array_equals(context.getElementsByTagName("ST"), []) assert_array_equals(context.getElementsByTagName("te:st"), []) - assert_array_equals(context.getElementsByTagName("te:ST"), []) + assert_array_equals(context.getElementsByTagName("te:ST"), [t]) }, "Element in non-HTML namespace, prefix, uppercase name") test(function() { diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml index e3aae85704d..2ae90748c2f 100644 --- a/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml +++ b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml @@ -37,17 +37,19 @@ test(function() { test(function() { var t = document.body.appendChild(document.createElementNS("test", "te:st")) this.add_cleanup(function() {document.body.removeChild(t)}) - assert_array_equals(document.getElementsByTagName("st"), [t]) + assert_array_equals(document.getElementsByTagName("st"), []) assert_array_equals(document.getElementsByTagName("ST"), []) + assert_array_equals(document.getElementsByTagName("te:st"), [t]) + assert_array_equals(document.getElementsByTagName("te:ST"), []) }, "Element in non-HTML namespace, prefix, lowercase name") test(function() { var t = document.body.appendChild(document.createElementNS("test", "te:ST")) this.add_cleanup(function() {document.body.removeChild(t)}) - assert_array_equals(document.getElementsByTagName("ST"), [t]) + assert_array_equals(document.getElementsByTagName("ST"), []) assert_array_equals(document.getElementsByTagName("st"), []) assert_array_equals(document.getElementsByTagName("te:st"), []) - assert_array_equals(document.getElementsByTagName("te:ST"), []) + assert_array_equals(document.getElementsByTagName("te:ST"), [t]) }, "Element in non-HTML namespace, prefix, uppercase name") test(function() { diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-classlist.html b/tests/wpt/web-platform-tests/dom/nodes/Element-classlist.html index cad3669da11..d3d6deb040c 100644 --- a/tests/wpt/web-platform-tests/dom/nodes/Element-classlist.html +++ b/tests/wpt/web-platform-tests/dom/nodes/Element-classlist.html @@ -66,8 +66,8 @@ test(function () { assert_equals( elem.classList.toString(), ' ', 'explicit' ); }, 'classList should contain initial markup whitespace'); test(function () { - assert_throws( 'SYNTAX_ERR', function () { elem.classList.contains(''); } ); -}, '.contains(empty_string) must throw a SYNTAX_ERR'); + assert_false( elem.classList.contains('') ); +}, '.contains(empty_string) must return false'); test(function () { assert_throws( 'SYNTAX_ERR', function () { elem.classList.add(''); } ); }, '.add(empty_string) must throw a SYNTAX_ERR'); @@ -85,8 +85,8 @@ test(function () { assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', ''); } ); }, '.replace with empty_string must throw a SYNTAX_ERR'); test(function () { - assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.contains('a b'); } ); -}, '.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR'); + assert_false( elem.classList.contains('a b') ); +}, '.contains(string_with_spaces) must return false'); test(function () { assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.add('a b'); } ); }, '.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR'); diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-insertAdjacentElement.html b/tests/wpt/web-platform-tests/dom/nodes/Element-insertAdjacentElement.html new file mode 100644 index 00000000000..d03e56680d4 --- /dev/null +++ b/tests/wpt/web-platform-tests/dom/nodes/Element-insertAdjacentElement.html @@ -0,0 +1,91 @@ + + + + + + +
+
+
+ + + + + diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-insertAdjacentText.html b/tests/wpt/web-platform-tests/dom/nodes/Element-insertAdjacentText.html new file mode 100644 index 00000000000..0fafabb519a --- /dev/null +++ b/tests/wpt/web-platform-tests/dom/nodes/Element-insertAdjacentText.html @@ -0,0 +1,76 @@ + + + + + + +
+
+
+ + diff --git a/tests/wpt/web-platform-tests/dom/nodes/case.js b/tests/wpt/web-platform-tests/dom/nodes/case.js index fb28b9514a3..8c2da4a44af 100644 --- a/tests/wpt/web-platform-tests/dom/nodes/case.js +++ b/tests/wpt/web-platform-tests/dom/nodes/case.js @@ -73,6 +73,13 @@ function ascii_lowercase(input) { }); } +function get_qualified_name(el) { + if (el.prefix) { + return el.prefix + ":" + el.localName; + } + return el.localName; +} + function test_create_element(name) { var node = document.createElement(name); assert_equals(node.localName, expected_case(name)); @@ -133,9 +140,9 @@ function test_get_elements_tag_name(elements_to_create, search_string) { var expected = Array.prototype.filter.call(container.childNodes, function(node) { if (is_html && node.namespaceURI === "http://www.w3.org/1999/xhtml") { - return node.localName === expected_case(search_string); + return get_qualified_name(node) === expected_case(search_string); } else { - return node.localName === search_string; + return get_qualified_name(node) === search_string; } }); document.documentElement.appendChild(container); diff --git a/tests/wpt/web-platform-tests/dom/nodes/remove-unscopable.html b/tests/wpt/web-platform-tests/dom/nodes/remove-unscopable.html new file mode 100644 index 00000000000..120ae813205 --- /dev/null +++ b/tests/wpt/web-platform-tests/dom/nodes/remove-unscopable.html @@ -0,0 +1,18 @@ + + + + + +
+ diff --git a/tests/wpt/web-platform-tests/encoding/api-basics.html b/tests/wpt/web-platform-tests/encoding/api-basics.html index 084575655c9..83670ce7dc3 100644 --- a/tests/wpt/web-platform-tests/encoding/api-basics.html +++ b/tests/wpt/web-platform-tests/encoding/api-basics.html @@ -15,13 +15,11 @@ test(function() { }, 'Default inputs'); -function testEncodeDecodeSample(encoding, string, bytes) { +function testDecodeSample(encoding, string, bytes) { test(function() { - var encoded = new TextEncoder(encoding).encode(string); - assert_array_equals([].slice.call(encoded), bytes); assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes)), string); assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes).buffer), string); - }, 'Encode/decode round trip: ' + encoding); + }, 'Decode sample: ' + encoding); } // z (ASCII U+007A), cent (Latin-1 U+00A2), CJK water (BMP U+6C34), @@ -29,25 +27,29 @@ function testEncodeDecodeSample(encoding, string, bytes) { // byte-swapped BOM (non-character U+FFFE) var sample = 'z\xA2\u6C34\uD834\uDD1E\uF8FF\uDBFF\uDFFD\uFFFE'; -testEncodeDecodeSample( - 'utf-8', - sample, - [0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xEF, 0xA3, 0xBF, 0xF4, 0x8F, 0xBF, 0xBD, 0xEF, 0xBF, 0xBE] -); +test(function() { + var encoding = 'utf-8'; + var string = sample; + var bytes = [0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xEF, 0xA3, 0xBF, 0xF4, 0x8F, 0xBF, 0xBD, 0xEF, 0xBF, 0xBE]; + var encoded = new TextEncoder().encode(string); + assert_array_equals([].slice.call(encoded), bytes); + assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes)), string); + assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes).buffer), string); +}, 'Encode/decode round trip: utf-8'); -testEncodeDecodeSample( +testDecodeSample( 'utf-16le', sample, [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF] ); -testEncodeDecodeSample( +testDecodeSample( 'utf-16be', sample, [0x00, 0x7A, 0x00, 0xA2, 0x6C, 0x34, 0xD8, 0x34, 0xDD, 0x1E, 0xF8, 0xFF, 0xDB, 0xFF, 0xDF, 0xFD, 0xFF, 0xFE] ); -testEncodeDecodeSample( +testDecodeSample( 'utf-16', sample, [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF] diff --git a/tests/wpt/web-platform-tests/encoding/api-invalid-label.html b/tests/wpt/web-platform-tests/encoding/api-invalid-label.html index ff037173a11..f15c184aa89 100644 --- a/tests/wpt/web-platform-tests/encoding/api-invalid-label.html +++ b/tests/wpt/web-platform-tests/encoding/api-invalid-label.html @@ -23,10 +23,6 @@ setup(function() { }); tests.forEach(function(input) { - test(function() { - assert_throws(new RangeError(), function() { new TextEncoder(input); }); - }, 'Invalid label ' + format_value(input) + ' should be rejected by TextEncoder.'); - test(function() { assert_throws(new RangeError(), function() { new TextDecoder(input); }); }, 'Invalid label ' + format_value(input) + ' should be rejected by TextDecoder.'); diff --git a/tests/wpt/web-platform-tests/encoding/api-replacement-encodings.html b/tests/wpt/web-platform-tests/encoding/api-replacement-encodings.html index ef0cdb88ec0..2dffd72e7b4 100644 --- a/tests/wpt/web-platform-tests/encoding/api-replacement-encodings.html +++ b/tests/wpt/web-platform-tests/encoding/api-replacement-encodings.html @@ -6,7 +6,6 @@ diff --git a/tests/wpt/web-platform-tests/js/builtins/Promise-incumbent-global-subsubframe.sub.html b/tests/wpt/web-platform-tests/js/builtins/Promise-incumbent-global-subsubframe.sub.html new file mode 100644 index 00000000000..9edd9d278ab --- /dev/null +++ b/tests/wpt/web-platform-tests/js/builtins/Promise-incumbent-global-subsubframe.sub.html @@ -0,0 +1,13 @@ + + diff --git a/tests/wpt/web-platform-tests/js/builtins/Promise-incumbent-global.sub.html b/tests/wpt/web-platform-tests/js/builtins/Promise-incumbent-global.sub.html new file mode 100644 index 00000000000..6ae0a9fe5e8 --- /dev/null +++ b/tests/wpt/web-platform-tests/js/builtins/Promise-incumbent-global.sub.html @@ -0,0 +1,20 @@ + + + + + + + diff --git a/tests/wpt/web-platform-tests/lint.whitelist b/tests/wpt/web-platform-tests/lint.whitelist index 8828f8b3a4e..2ab4b9d8513 100644 --- a/tests/wpt/web-platform-tests/lint.whitelist +++ b/tests/wpt/web-platform-tests/lint.whitelist @@ -105,6 +105,9 @@ W3C-TEST.ORG:subresource-integrity/refresh-header.js.headers # semi-legitimate use of 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 # Lint doesn't know about sub.svg I guess PARSE-FAILED:content-security-policy/svg/including.sub.svg diff --git a/tests/wpt/web-platform-tests/selection/collapse.html b/tests/wpt/web-platform-tests/selection/collapse.html index f1268f9f391..530158a05bb 100644 --- a/tests/wpt/web-platform-tests/selection/collapse.html +++ b/tests/wpt/web-platform-tests/selection/collapse.html @@ -1,5 +1,6 @@ Selection.collapse() tests +
diff --git a/tests/wpt/web-platform-tests/selection/extend.html b/tests/wpt/web-platform-tests/selection/extend.html index bc8fe2cf3d0..e00f8c401a9 100644 --- a/tests/wpt/web-platform-tests/selection/extend.html +++ b/tests/wpt/web-platform-tests/selection/extend.html @@ -1,6 +1,7 @@ Selection extend() tests + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/close.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/close.https.html new file mode 100644 index 00000000000..3e3cc8b2b08 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/close.https.html @@ -0,0 +1,11 @@ + +ServiceWorkerGlobalScope: close operation + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html new file mode 100644 index 00000000000..f0dad6a7b28 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html @@ -0,0 +1,37 @@ + +ServiceWorkerGlobalScope: registration + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/close-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/close-worker.js new file mode 100644 index 00000000000..a1342b187b3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/close-worker.js @@ -0,0 +1,8 @@ +importScripts('../../resources/interfaces.js'); +importScripts('../../resources/worker-testharness.js'); + +test(function() { + assert_throws({name: 'InvalidAccessError'}, function() { + self.close(); + }); +}, 'ServiceWorkerGlobalScope close operation'); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-worker.js new file mode 100644 index 00000000000..c98acbcfb06 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-worker.js @@ -0,0 +1,132 @@ +importScripts('../../resources/test-helpers.sub.js'); +importScripts('../../resources/worker-testharness.js'); + +var events_seen = []; + +assert_equals( + self.registration.scope, + normalizeURL('scope/registration-attribute'), + 'On worker script evaluation, registration attribute should be set'); +assert_equals( + self.registration.installing, + null, + 'On worker script evaluation, installing worker should be null'); +assert_equals( + self.registration.waiting, + null, + 'On worker script evaluation, waiting worker should be null'); +assert_equals( + self.registration.active, + null, + 'On worker script evaluation, active worker should be null'); + +self.registration.addEventListener('updatefound', function() { + events_seen.push('updatefound'); + + assert_equals( + self.registration.scope, + normalizeURL('scope/registration-attribute'), + 'On updatefound event, registration attribute should be set'); + assert_equals( + self.registration.installing.scriptURL, + normalizeURL('registration-attribute-worker.js'), + 'On updatefound event, installing worker should be set'); + assert_equals( + self.registration.waiting, + null, + 'On updatefound event, waiting worker should be null'); + assert_equals( + self.registration.active, + null, + 'On updatefound event, active worker should be null'); + + assert_equals( + self.registration.installing.state, + 'installing', + 'On updatefound event, worker should be in the installing state'); + + var worker = self.registration.installing; + self.registration.installing.addEventListener('statechange', function() { + events_seen.push('statechange(' + worker.state + ')'); + }); + }); + +self.addEventListener('install', function(e) { + events_seen.push('install'); + + assert_equals( + self.registration.scope, + normalizeURL('scope/registration-attribute'), + 'On install event, registration attribute should be set'); + assert_equals( + self.registration.installing.scriptURL, + normalizeURL('registration-attribute-worker.js'), + 'On install event, installing worker should be set'); + assert_equals( + self.registration.waiting, + null, + 'On install event, waiting worker should be null'); + assert_equals( + self.registration.active, + null, + 'On install event, active worker should be null'); + + assert_equals( + self.registration.installing.state, + 'installing', + 'On install event, worker should be in the installing state'); + }); + +self.addEventListener('activate', function(e) { + events_seen.push('activate'); + + assert_equals( + self.registration.scope, + normalizeURL('scope/registration-attribute'), + 'On activate event, registration attribute should be set'); + assert_equals( + self.registration.installing, + null, + 'On activate event, installing worker should be null'); + assert_equals( + self.registration.waiting, + null, + 'On activate event, waiting worker should be null'); + assert_equals( + self.registration.active.scriptURL, + normalizeURL('registration-attribute-worker.js'), + 'On activate event, active worker should be set'); + + assert_equals( + self.registration.active.state, + 'activating', + 'On activate event, worker should be in the activating state'); + }); + +self.addEventListener('fetch', function(e) { + events_seen.push('fetch'); + + assert_equals( + self.registration.scope, + normalizeURL('scope/registration-attribute'), + 'On fetch event, registration attribute should be set'); + assert_equals( + self.registration.installing, + null, + 'On fetch event, installing worker should be null'); + assert_equals( + self.registration.waiting, + null, + 'On fetch event, waiting worker should be null'); + assert_equals( + self.registration.active.scriptURL, + normalizeURL('registration-attribute-worker.js'), + 'On fetch event, active worker should be set'); + + assert_equals( + self.registration.active.state, + 'activated', + 'On fetch event, worker should be in the activated state'); + + e.respondWith(new Response(events_seen)); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-controlling-worker.html b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-controlling-worker.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-worker.js new file mode 100644 index 00000000000..6cee5365428 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-worker.js @@ -0,0 +1,23 @@ +function matchQuery(query) { + return self.location.href.indexOf(query) != -1; +} + +if (matchQuery('?evaluation')) + self.registration.unregister(); + +self.addEventListener('install', function(e) { + if (matchQuery('?install')) + self.registration.unregister(); + }); + +self.addEventListener('activate', function(e) { + if (matchQuery('?activate')) + self.registration.unregister(); + }); + +self.addEventListener('message', function(e) { + self.registration.unregister() + .then(function(result) { + e.data.port.postMessage({result: result}); + }); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.js new file mode 100644 index 00000000000..63c4534b7ef --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.js @@ -0,0 +1,25 @@ +importScripts('../../resources/test-helpers.sub.js'); +importScripts('../../resources/worker-testharness.js'); + +var events_seen = []; + +self.registration.addEventListener('updatefound', function() { + events_seen.push('updatefound'); + }); + +self.addEventListener('activate', function(e) { + events_seen.push('activate'); + }); + +self.addEventListener('fetch', function(e) { + events_seen.push('fetch'); + e.respondWith(new Response(events_seen)); + }); + +self.addEventListener('message', function(e) { + events_seen.push('message'); + self.registration.update(); + }); + +// update() during the script evaluation should be ignored. +self.registration.update(); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.py b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.py new file mode 100644 index 00000000000..5158bf25170 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.py @@ -0,0 +1,14 @@ +import os +import time + +def main(request, response): + # update() does not bypass cache so set the max-age to 0 such that update() + # can find a new version in the network. + headers = [('Cache-Control', 'max-age: 0'), + ('Content-Type', 'application/javascript')] + with open(os.path.join(os.path.dirname(__file__), + 'update-worker.js'), 'r') as file: + script = file.read() + # Return a different script for each access. + return headers, '// %s\n%s' % (time.time(), script) + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html new file mode 100644 index 00000000000..31330918807 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html @@ -0,0 +1,127 @@ + +ServiceWorkerGlobalScope: unregister + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html new file mode 100644 index 00000000000..a9285a1c9e2 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html @@ -0,0 +1,45 @@ + +ServiceWorkerGlobalScope: update + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/activate-event-after-install-state-change.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/activate-event-after-install-state-change.https.html new file mode 100644 index 00000000000..57fccf13712 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/activate-event-after-install-state-change.https.html @@ -0,0 +1,32 @@ + +Service Worker: registration events + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/activation-after-registration.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/activation-after-registration.https.html new file mode 100644 index 00000000000..ff0990df6ba --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/activation-after-registration.https.html @@ -0,0 +1,29 @@ + +Service Worker: Activation occurs after registration + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/active.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/active.https.html new file mode 100644 index 00000000000..deee6a50ea0 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/active.https.html @@ -0,0 +1,55 @@ + +ServiceWorker: navigator.serviceWorker.active + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/appcache-ordering-main.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/appcache-ordering-main.https.html new file mode 100644 index 00000000000..609d67e4504 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/appcache-ordering-main.https.html @@ -0,0 +1,91 @@ + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/claim-not-using-registration.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/claim-not-using-registration.https.html new file mode 100644 index 00000000000..e18e061cd3c --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/claim-not-using-registration.https.html @@ -0,0 +1,123 @@ + +Service Worker: claim client not using registration + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/claim-using-registration.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/claim-using-registration.https.html new file mode 100644 index 00000000000..640b0be3e50 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/claim-using-registration.https.html @@ -0,0 +1,100 @@ + +Service Worker: claim client using registration + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/clients-get-cross-origin.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-get-cross-origin.https.html new file mode 100644 index 00000000000..3413acbf9d5 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-get-cross-origin.https.html @@ -0,0 +1,42 @@ + +Service Worker: Clients.get across origins + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/clients-get.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-get.https.html new file mode 100644 index 00000000000..af38502dd9f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-get.https.html @@ -0,0 +1,70 @@ + +Service Worker: Clients.get + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/clients-matchall-client-types.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-matchall-client-types.https.html new file mode 100644 index 00000000000..3645e86354d --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-matchall-client-types.https.html @@ -0,0 +1,78 @@ + +Service Worker: Clients.matchAll with various clientTypes + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/clients-matchall-include-uncontrolled.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-matchall-include-uncontrolled.https.html new file mode 100644 index 00000000000..9285aef970f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-matchall-include-uncontrolled.https.html @@ -0,0 +1,93 @@ + +Service Worker: Clients.matchAll with includeUncontrolled + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/clients-matchall.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-matchall.https.html new file mode 100644 index 00000000000..12e3da4e61f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/clients-matchall.https.html @@ -0,0 +1,45 @@ + +Service Worker: Clients.matchAll + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/controller-on-load.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/controller-on-load.https.html new file mode 100644 index 00000000000..ff3b7ce04f4 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/controller-on-load.https.html @@ -0,0 +1,45 @@ + +Service Worker: Controller on load + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/controller-on-reload.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/controller-on-reload.https.html new file mode 100644 index 00000000000..4490c707963 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/controller-on-reload.https.html @@ -0,0 +1,54 @@ + +Service Worker: Controller on reload + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/extendable-event-async-waituntil.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/extendable-event-async-waituntil.https.html new file mode 100644 index 00000000000..c06bf84ab2d --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/extendable-event-async-waituntil.https.html @@ -0,0 +1,30 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/extendable-event-waituntil.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/extendable-event-waituntil.https.html new file mode 100644 index 00000000000..003e703b1f3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/extendable-event-waituntil.https.html @@ -0,0 +1,125 @@ + +ExtendableEvent: waitUntil + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting-cache.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting-cache.https.html new file mode 100644 index 00000000000..fdb64e15d66 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting-cache.https.html @@ -0,0 +1,38 @@ + +Service Worker: canvas tainting of the fetched image using cached responses + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting.https.html new file mode 100644 index 00000000000..bb75473926f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting.https.html @@ -0,0 +1,38 @@ + +Service Worker: canvas tainting of the fetched image + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-cors-xhr.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-cors-xhr.https.html new file mode 100644 index 00000000000..3b1f1d6bc32 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-cors-xhr.https.html @@ -0,0 +1,38 @@ + +Service Worker: CORS XHR of fetch() + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-csp.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-csp.https.html new file mode 100644 index 00000000000..bdb56c213af --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-csp.https.html @@ -0,0 +1,32 @@ + +Service Worker: CSP control of fetch() + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-after-navigation-within-page.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-after-navigation-within-page.https.html new file mode 100644 index 00000000000..dce1f794fab --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-after-navigation-within-page.https.html @@ -0,0 +1,65 @@ + +ServiceWorker: navigator.serviceWorker.waiting + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-async-respond-with.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-async-respond-with.https.html new file mode 100644 index 00000000000..912e709ca38 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-async-respond-with.https.html @@ -0,0 +1,34 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-network-error.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-network-error.https.html new file mode 100644 index 00000000000..f6a3d0776e5 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-network-error.https.html @@ -0,0 +1,42 @@ + +Service Worker: Fetch event network error + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-redirect.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-redirect.https.html new file mode 100644 index 00000000000..556d04413fa --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-redirect.https.html @@ -0,0 +1,997 @@ + +Service Worker: Fetch Event Redirect Handling + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html new file mode 100644 index 00000000000..5d3346e7b28 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html @@ -0,0 +1,35 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event.https.html new file mode 100644 index 00000000000..9869f3b2799 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event.https.html @@ -0,0 +1,466 @@ + + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-frame-resource.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-frame-resource.https.html new file mode 100644 index 00000000000..cc1dac472bc --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-frame-resource.https.html @@ -0,0 +1,221 @@ + +Service Worker: Fetch for the frame loading. + + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-header-visibility.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-header-visibility.https.html new file mode 100644 index 00000000000..36bf16f3279 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-header-visibility.https.html @@ -0,0 +1,52 @@ + +Service Worker: Visibility of headers during fetch. + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-mixed-content-to-inscope.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-mixed-content-to-inscope.https.html new file mode 100644 index 00000000000..fb9fa9b7b71 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-mixed-content-to-inscope.https.html @@ -0,0 +1,27 @@ + +Service Worker: Mixed content of fetch() + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-mixed-content-to-outscope.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-mixed-content-to-outscope.https.html new file mode 100644 index 00000000000..cee89ce167d --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-mixed-content-to-outscope.https.html @@ -0,0 +1,27 @@ + +Service Worker: Mixed content of fetch() + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-css-base-url.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-css-base-url.https.html new file mode 100644 index 00000000000..0405ed70905 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-css-base-url.https.html @@ -0,0 +1,56 @@ + +Service Worker: CSS's base URL must be the request URL even when fetched from other URL + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-css-images.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-css-images.https.html new file mode 100644 index 00000000000..cbce7f19d71 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-css-images.https.html @@ -0,0 +1,99 @@ + +Service Worker: FetchEvent for css image + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-fallback.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-fallback.https.html new file mode 100644 index 00000000000..8290e21dd3e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-fallback.https.html @@ -0,0 +1,113 @@ + +Service Worker: the fallback behavior of FetchEvent + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-no-freshness-headers.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-no-freshness-headers.https.html new file mode 100644 index 00000000000..829b0cf2594 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-no-freshness-headers.https.html @@ -0,0 +1,53 @@ + +Service Worker: the headers of FetchEvent shouldn't contain freshness headers + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html new file mode 100644 index 00000000000..fa937f2e189 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html @@ -0,0 +1,176 @@ + +Service Worker: FetchEvent for resources + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-resources.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-resources.https.html new file mode 100644 index 00000000000..061add6f167 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-resources.https.html @@ -0,0 +1,142 @@ + +Service Worker: FetchEvent for resources + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-xhr.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-xhr.https.html new file mode 100644 index 00000000000..1b80985a356 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-xhr.https.html @@ -0,0 +1,33 @@ + +Service Worker: the body of FetchEvent using XMLHttpRequest + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-response-xhr.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-response-xhr.https.html new file mode 100644 index 00000000000..8b66c605178 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-response-xhr.https.html @@ -0,0 +1,37 @@ + +Service Worker: the response of FetchEvent using XMLHttpRequest + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-waits-for-activate.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-waits-for-activate.https.html new file mode 100644 index 00000000000..304680c97e6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-waits-for-activate.https.html @@ -0,0 +1,63 @@ + +Service Worker: Fetch Event Waits for Activate Event + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/getregistration.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/getregistration.https.html new file mode 100644 index 00000000000..c86fda50d52 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/getregistration.https.html @@ -0,0 +1,87 @@ + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/getregistrations.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/getregistrations.https.html new file mode 100644 index 00000000000..86e8e1c283e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/getregistrations.https.html @@ -0,0 +1,159 @@ + +Service Worker: getRegistrations() + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/indexeddb.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/indexeddb.https.html new file mode 100644 index 00000000000..4de2bc43e17 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/indexeddb.https.html @@ -0,0 +1,35 @@ + +Service Worker: Indexed DB + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/install-event-type.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/install-event-type.https.html new file mode 100644 index 00000000000..7e74af85c3a --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/install-event-type.https.html @@ -0,0 +1,30 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/installing.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/installing.https.html new file mode 100644 index 00000000000..57d87811192 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/installing.https.html @@ -0,0 +1,37 @@ + +ServiceWorker: navigator.serviceWorker.installing + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/interfaces.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/interfaces.https.html new file mode 100644 index 00000000000..403a005344e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/interfaces.https.html @@ -0,0 +1,56 @@ + +Service Worker: Interfaces + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/invalid-blobtype.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/invalid-blobtype.https.html new file mode 100644 index 00000000000..f1f2d1bdc61 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/invalid-blobtype.https.html @@ -0,0 +1,30 @@ + +Service Worker: respondWith with header value containing a null byte + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/invalid-header.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/invalid-header.https.html new file mode 100644 index 00000000000..79469526493 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/invalid-header.https.html @@ -0,0 +1,30 @@ + +Service Worker: respondWith with header value containing a null byte + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/multiple-register.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/multiple-register.https.html new file mode 100644 index 00000000000..1089cffda91 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/multiple-register.https.html @@ -0,0 +1,116 @@ + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/multiple-update.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/multiple-update.https.html new file mode 100644 index 00000000000..84aac9583b9 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/multiple-update.https.html @@ -0,0 +1,92 @@ + + +Service Worker: Trigger multiple updates + + + + 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 new file mode 100644 index 00000000000..7b606cf0c3c --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/navigation-redirect.https.html @@ -0,0 +1,449 @@ + +Service Worker: Navigation redirection + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/onactivate-script-error.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/onactivate-script-error.https.html new file mode 100644 index 00000000000..23a7f2c8686 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/onactivate-script-error.https.html @@ -0,0 +1,75 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/oninstall-script-error.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/oninstall-script-error.https.html new file mode 100644 index 00000000000..a9ca19cab7f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/oninstall-script-error.https.html @@ -0,0 +1,67 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/performance-timeline.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/performance-timeline.https.html new file mode 100644 index 00000000000..182076baa98 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/performance-timeline.https.html @@ -0,0 +1,11 @@ + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-msgport-to-client.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-msgport-to-client.https.html new file mode 100644 index 00000000000..38b4f56e784 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-msgport-to-client.https.html @@ -0,0 +1,51 @@ + +Service Worker: postMessage to Client + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client.https.html new file mode 100644 index 00000000000..a031ee2edf3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client.https.html @@ -0,0 +1,49 @@ + +Service Worker: postMessage to Client + + + + + 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 new file mode 100644 index 00000000000..a6f66517910 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage.https.html @@ -0,0 +1,60 @@ + +Service Worker: postMessage + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/ready.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/ready.https.html new file mode 100644 index 00000000000..ee6a97ca8fc --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/ready.https.html @@ -0,0 +1,172 @@ + +Service Worker: navigator.serviceWorker.ready + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/referer.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/referer.https.html new file mode 100644 index 00000000000..9b3565329ec --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/referer.https.html @@ -0,0 +1,30 @@ + +Service Worker: check referer of fetch() + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/register-closed-window.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/register-closed-window.https.html new file mode 100644 index 00000000000..22135671625 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/register-closed-window.https.html @@ -0,0 +1,35 @@ + +Service Worker: Register() on Closed Window + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/register-default-scope.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/register-default-scope.https.html new file mode 100644 index 00000000000..dc136d4e8dd --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/register-default-scope.https.html @@ -0,0 +1,66 @@ + +register() and scope + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/register-same-scope-different-script-url.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/register-same-scope-different-script-url.https.html new file mode 100644 index 00000000000..445be740951 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/register-same-scope-different-script-url.https.html @@ -0,0 +1,240 @@ + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/register-wait-forever-in-install-worker.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/register-wait-forever-in-install-worker.https.html new file mode 100644 index 00000000000..348daccccdc --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/register-wait-forever-in-install-worker.https.html @@ -0,0 +1,30 @@ + +Service Worker: Register wait-forever-in-install-worker + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/registration-end-to-end.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-end-to-end.https.html new file mode 100644 index 00000000000..e92b6502f09 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-end-to-end.https.html @@ -0,0 +1,96 @@ + +Service Worker: registration end-to-end + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/registration-events.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-events.https.html new file mode 100644 index 00000000000..972ce7410b9 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-events.https.html @@ -0,0 +1,37 @@ + +Service Worker: registration events + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/registration-iframe.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-iframe.https.html new file mode 100644 index 00000000000..fb60afe8497 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-iframe.https.html @@ -0,0 +1,108 @@ + + +Service Worker: Registration for iframe + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/registration-service-worker-attributes.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-service-worker-attributes.https.html new file mode 100644 index 00000000000..a0dea5428db --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-service-worker-attributes.https.html @@ -0,0 +1,70 @@ + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/registration.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/registration.https.html new file mode 100644 index 00000000000..ae9f85fb27c --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/registration.https.html @@ -0,0 +1,368 @@ + +Service Worker: Registration + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/rejections.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/rejections.https.html new file mode 100644 index 00000000000..8002ad9a81b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/rejections.https.html @@ -0,0 +1,21 @@ + +Service Worker: Rejection Types + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/request-end-to-end.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/request-end-to-end.https.html new file mode 100644 index 00000000000..c9c3b30464b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/request-end-to-end.https.html @@ -0,0 +1,61 @@ + +Service Worker: Request end-to-end + + + + 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 new file mode 100644 index 00000000000..f33c41d715e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resource-timing.https.html @@ -0,0 +1,58 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/404.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/404.py new file mode 100644 index 00000000000..235a3d4ff0e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/404.py @@ -0,0 +1,5 @@ +# iframe does not fire onload event if the response's content-type is not +# text/plain or text/html so this script exists if you want to test a 404 load +# in an iframe. +def main(req, res): + return 404, [('Content-Type', 'text/plain')], "Page not found" diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.install.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.install.html new file mode 100644 index 00000000000..428ad92c782 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.install.html @@ -0,0 +1,26 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.is-appcached.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.is-appcached.html new file mode 100644 index 00000000000..485ab177197 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.is-appcached.html @@ -0,0 +1,13 @@ + + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.is-appcached.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.is-appcached.js new file mode 100644 index 00000000000..a562b6f1c3c --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.is-appcached.js @@ -0,0 +1 @@ +var is_appcached = true; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.manifest b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.manifest new file mode 100644 index 00000000000..0deed0e91a8 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.manifest @@ -0,0 +1,7 @@ +CACHE MANIFEST + +appcache-ordering.is-appcached.html + +FALLBACK: +appcache-ordering.is-appcached404.js appcache-ordering.is-appcached.js + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/blank.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/blank.html new file mode 100644 index 00000000000..a3c3a4689a6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/blank.html @@ -0,0 +1,2 @@ + +Empty doc diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/claim-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/claim-worker.js new file mode 100644 index 00000000000..317feb1a02d --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/claim-worker.js @@ -0,0 +1,14 @@ +self.addEventListener('message', function(event) { + self.clients.claim() + .then(function(result) { + if (result !== undefined) { + event.data.port.postMessage( + 'FAIL: claim() should be resolved with undefined'); + return; + } + event.data.port.postMessage('PASS'); + }) + .catch(function(error) { + event.data.port.postMessage('FAIL: exception: ' + error.name); + }); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-frame.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-frame.html new file mode 100644 index 00000000000..27143d4b99b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-frame.html @@ -0,0 +1,12 @@ + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-other-origin.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-other-origin.html new file mode 100644 index 00000000000..cbd3dcc6f3b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-other-origin.html @@ -0,0 +1,64 @@ + + + + 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 new file mode 100644 index 00000000000..9ac2c226458 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-worker.js @@ -0,0 +1,53 @@ +self.onfetch = function(e) { + if (e.request.url.indexOf("clients-get-frame.html") >= 0) { + if (e.clientId === null) { + e.respondWith(fetch(e.request)); + } else { + e.respondWith(Response.error()); + } + return; + } + e.respondWith(new Response(e.clientId)); +}; + +self.onmessage = function(e) { + var port = e.data.port; + if (e.data.message == 'get_client_ids') { + var clientIds = e.data.clientIds; + var message = []; + + Promise.all( + clientIds.map(function(clientId) { + return self.clients.get(clientId); + }).concat(self.clients.get("invalid-id")) + ).then(function(clients) { + clients.forEach(function(client) { + if (client instanceof Client) { + message.push([client.visibilityState, + client.focused, + client.url, + client.frameType]); + } else { + message.push(client); + } + }); + port.postMessage(message); + }); + } else if (e.data.message == 'get_other_client_id') { + var clientId = e.data.clientId; + var message; + + self.clients.get(clientId) + .then(function(client) { + if (client instanceof Client) { + message = [client.visibilityState, + client.focused, + client.url, + client.frameType]; + } else { + message = client; + } + port.postMessage(message); + }); + } +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-matchall-client-types-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-matchall-client-types-iframe.html new file mode 100644 index 00000000000..51b4dca0314 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-matchall-client-types-iframe.html @@ -0,0 +1,8 @@ + +Empty doc + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-matchall-client-types-shared-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-matchall-client-types-shared-worker.js new file mode 100644 index 00000000000..1ae72fb8944 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-matchall-client-types-shared-worker.js @@ -0,0 +1,4 @@ +onconnect = function(e) { + var port = e.ports[0]; + port.postMessage('started'); +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-matchall-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-matchall-worker.js new file mode 100644 index 00000000000..f0ae90d8142 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-matchall-worker.js @@ -0,0 +1,24 @@ +self.onmessage = function(e) { + var port = e.data.port; + var options = e.data.options; + + self.clients.matchAll(options).then(function(clients) { + var message = []; + clients.forEach(function(client) { + var frame_type = client.frameType; + if (client.url.indexOf('clients-matchall-include-uncontrolled.https.html') > -1 && + client.frameType == 'auxiliary') { + // The test tab might be opened using window.open() by the test framework. + // In that case, just pretend it's top-level! + frame_type = 'top-level'; + } + message.push([client.visibilityState, + client.focused, + client.url, + frame_type]); + }); + // Sort by url + message.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; }); + port.postMessage(message); + }); +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy-shared-worker-interceptor.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy-shared-worker-interceptor.js new file mode 100644 index 00000000000..82b24459b4f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy-shared-worker-interceptor.js @@ -0,0 +1,7 @@ +var worker_text = 'onconnect = function(e) { e.ports[0].postMessage("worker loading intercepted by service worker"); };'; + +self.onfetch = function(event) { + if (event.request.url.indexOf('dummy-shared-worker.js') != -1) + event.respondWith(new Response(worker_text)); +}; + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy-worker-interceptor.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy-worker-interceptor.js new file mode 100644 index 00000000000..43244e1d993 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy-worker-interceptor.js @@ -0,0 +1,21 @@ +importScripts('get-host-info.sub.js'); + +var worker_text = 'postMessage("worker loading intercepted by service worker"); '; + +self.onfetch = function(event) { + if (event.request.url.indexOf('synthesized') != -1) { + event.respondWith(new Response(worker_text)); + } else if (event.request.url.indexOf('same-origin') != -1) { + event.respondWith(fetch('dummy-worker-script.py')); + } else if (event.request.url.indexOf('cors') != -1) { + var path = (new URL('dummy-worker-script.py', self.location)).pathname; + var url = get_host_info()['HTTPS_REMOTE_ORIGIN'] + path; + var mode = "no-cors"; + if (event.request.url.indexOf('no-cors') == -1) { + url += '?ACAOrigin=*'; + mode = "cors"; + } + event.respondWith(fetch(url, { mode: mode })); + } +}; + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy-worker-script.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy-worker-script.py new file mode 100644 index 00000000000..6f40b5ed605 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy-worker-script.py @@ -0,0 +1,9 @@ +def main(request, response): + headers = [] + + if "ACAOrigin" in request.GET: + for item in request.GET["ACAOrigin"].split(","): + headers.append(("Access-Control-Allow-Origin", item)) + + return headers, "postMessage('dummy-worker-script loaded');" + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy.html new file mode 100644 index 00000000000..12a179980df --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy.html @@ -0,0 +1,2 @@ + +Hello world diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy.txt b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy.txt new file mode 100644 index 00000000000..802992c4220 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/dummy.txt @@ -0,0 +1 @@ +Hello world diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/empty-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/empty-worker.js new file mode 100644 index 00000000000..49ceb2648a9 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/empty-worker.js @@ -0,0 +1 @@ +// Do nothing. diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/empty.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/empty.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/end-to-end-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/end-to-end-worker.js new file mode 100644 index 00000000000..d45a50556a9 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/end-to-end-worker.js @@ -0,0 +1,7 @@ +onmessage = function(e) { + var message = e.data; + if (typeof message === 'object' && 'port' in message) { + var response = 'Ack for: ' + message.from; + message.port.postMessage(response); + } +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/events-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/events-worker.js new file mode 100644 index 00000000000..80a2188677b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/events-worker.js @@ -0,0 +1,12 @@ +var eventsSeen = []; + +function handler(event) { eventsSeen.push(event.type); } + +['activate', 'install'].forEach(function(type) { + self.addEventListener(type, handler); + }); + +onmessage = function(e) { + var message = e.data; + message.port.postMessage({events: eventsSeen}); +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/extendable-event-async-waituntil.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/extendable-event-async-waituntil.js new file mode 100644 index 00000000000..d77238d9397 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/extendable-event-async-waituntil.js @@ -0,0 +1,20 @@ +var result = 'FAIL: did not throw.'; + +self.addEventListener('message', function(event) { + event.data.port.postMessage(result); + }); + +self.addEventListener('install', function(event) { + self.installEvent = event; + }); + +self.addEventListener('activate', function(event) { + try { + self.installEvent.waitUntil(new Promise(function(){})); + } catch (error) { + if (error.name == 'InvalidStateError') + result = 'PASS'; + else + result = 'FAIL: unexpected exception: ' + error; + } + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/extendable-event-waituntil.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/extendable-event-waituntil.js new file mode 100644 index 00000000000..48fdf1b99fd --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/extendable-event-waituntil.js @@ -0,0 +1,75 @@ +var pendingPorts = []; +var portResolves = []; + +onmessage = function(e) { + var message = e.data; + if ('port' in message) { + var resolve = self.portResolves.shift(); + if (resolve) + resolve(message.port); + else + self.pendingPorts.push(message.port); + } +}; + +function fulfillPromise() { + return new Promise(function(resolve) { + // Make sure the oninstall/onactivate callback returns first. + Promise.resolve().then(function() { + var port = self.pendingPorts.shift(); + if (port) + resolve(port); + else + self.portResolves.push(resolve); + }); + }).then(function(port) { + port.postMessage('SYNC'); + return new Promise(function(resolve) { + port.onmessage = function(e) { + if (e.data == 'ACK') + resolve(); + }; + }); + }); +} + +function rejectPromise() { + return new Promise(function(resolve, reject) { + // Make sure the oninstall/onactivate callback returns first. + Promise.resolve().then(reject); + }); +} + +function stripScopeName(url) { + return url.split('/').slice(-1)[0]; +} + +oninstall = function(e) { + switch (stripScopeName(self.location.href)) { + case 'install-fulfilled': + e.waitUntil(fulfillPromise()); + break; + case 'install-rejected': + e.waitUntil(rejectPromise()); + break; + case 'install-multiple-fulfilled': + e.waitUntil(fulfillPromise()); + e.waitUntil(fulfillPromise()); + break; + case 'install-reject-precedence': + e.waitUntil(fulfillPromise()); + e.waitUntil(rejectPromise()); + break; + } +}; + +onactivate = function(e) { + switch (stripScopeName(self.location.href)) { + case 'activate-fulfilled': + e.waitUntil(fulfillPromise()); + break; + case 'activate-rejected': + e.waitUntil(rejectPromise()); + break; + } +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fail-on-fetch-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fail-on-fetch-worker.js new file mode 100644 index 00000000000..517f289fbc8 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fail-on-fetch-worker.js @@ -0,0 +1,5 @@ +importScripts('worker-testharness.js'); + +this.addEventListener('fetch', function(event) { + event.respondWith(new Response('ERROR')); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-access-control-login.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-access-control-login.html new file mode 100644 index 00000000000..0ffab1af598 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-access-control-login.html @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-access-control.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-access-control.py new file mode 100644 index 00000000000..862718ad03f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-access-control.py @@ -0,0 +1,69 @@ +import base64 +import json + +def main(request, response): + headers = [] + headers.append(('X-ServiceWorker-ServerHeader', 'SetInTheServer')) + + if "ACAOrigin" in request.GET: + for item in request.GET["ACAOrigin"].split(","): + headers.append(("Access-Control-Allow-Origin", item)) + + for suffix in ["Headers", "Methods", "Credentials"]: + query = "ACA%s" % suffix + header = "Access-Control-Allow-%s" % suffix + if query in request.GET: + headers.append((header, request.GET[query])) + + if "ACEHeaders" in request.GET: + headers.append(("Access-Control-Expose-Headers", request.GET[query])) + + if ("Auth" in request.GET and not request.auth.username) or "AuthFail" in request.GET: + status = 401 + headers.append(('WWW-Authenticate', 'Basic realm="Restricted"')) + body = 'Authentication canceled' + return status, headers, body + + if "PNGIMAGE" in request.GET: + headers.append(("Content-Type", "image/png")) + body = base64.decodestring("iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1B" + "AACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAhSURBVDhPY3wro/KfgQLABKXJBqMG" + "jBoAAqMGDLwBDAwAEsoCTFWunmQAAAAASUVORK5CYII=") + return headers, body + + + username = request.auth.username if request.auth.username else "undefined" + password = request.auth.password if request.auth.username else "undefined" + cookie = request.cookies['cookie'].value if 'cookie' in request.cookies else "undefined" + + files = [] + for key, values in request.POST.iteritems(): + assert len(values) == 1 + value = values[0] + if not hasattr(value, "file"): + continue + data = value.file.read() + files.append({"key": key, + "name": value.file.name, + "type": value.type, + "error": 0, #TODO, + "size": len(data), + "content": data}) + + get_data = {key:request.GET[key] for key,value in request.GET.iteritems()} + post_data = {key:request.POST[key] for key,value in request.POST.iteritems() + if not hasattr(request.POST[key], "file")} + headers_data = {key:request.headers[key] for key,value in request.headers.iteritems()} + + data = {"jsonpResult": "success", + "method": request.method, + "headers": headers_data, + "body": request.body, + "files": files, + "GET": get_data, + "POST": post_data, + "username": username, + "password": password, + "cookie": cookie} + + return headers, "report( %s )" % json.dumps(data) diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-canvas-tainting-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-canvas-tainting-iframe.html new file mode 100644 index 00000000000..0bd6b6f07c3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-canvas-tainting-iframe.html @@ -0,0 +1,277 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-cors-xhr-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-cors-xhr-iframe.html new file mode 100644 index 00000000000..48f618397c5 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-cors-xhr-iframe.html @@ -0,0 +1,210 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-csp-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-csp-iframe.html new file mode 100644 index 00000000000..cf7175bc83d --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-csp-iframe.html @@ -0,0 +1,72 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-csp-iframe.html.sub.headers b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-csp-iframe.html.sub.headers new file mode 100644 index 00000000000..300efe049b5 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-csp-iframe.html.sub.headers @@ -0,0 +1 @@ +Content-Security-Policy: img-src https://{{host}}:{{ports[https][0]}} diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-after-navigation-within-page-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-after-navigation-within-page-iframe.html new file mode 100644 index 00000000000..bf8a6d5ce51 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-after-navigation-within-page-iframe.html @@ -0,0 +1,22 @@ + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-async-respond-with-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-async-respond-with-worker.js new file mode 100644 index 00000000000..7f66d20dfc2 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-async-respond-with-worker.js @@ -0,0 +1,19 @@ +var result; + +self.addEventListener('message', function(event) { + event.data.port.postMessage(result); + }); + +self.addEventListener('fetch', function(event) { + setTimeout(function() { + try { + event.respondWith(new Response()); + result = 'FAIL: did not throw'; + } catch (error) { + if (error.name == 'InvalidStateError') + result = 'PASS'; + else + result = 'FAIL: Unexpected exception: ' + error; + } + }, 0); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-network-error-controllee-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-network-error-controllee-iframe.html new file mode 100644 index 00000000000..a4c9307e745 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-network-error-controllee-iframe.html @@ -0,0 +1,59 @@ + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-network-error-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-network-error-worker.js new file mode 100644 index 00000000000..52d4c8e860b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-network-error-worker.js @@ -0,0 +1,46 @@ +// Test that multiple fetch handlers do not confuse the implementation. +self.addEventListener('fetch', function(event) {}); + +self.addEventListener('fetch', function(event) { + var testcase = new URL(event.request.url).search; + switch (testcase) { + case '?reject': + event.respondWith(Promise.reject()); + break; + case '?prevent-default': + event.preventDefault(); + break; + case '?prevent-default-and-respond-with': + event.preventDefault(); + break; + case '?unused-body': + event.respondWith(new Response('body')); + break; + case '?used-body': + var res = new Response('body'); + res.text(); + event.respondWith(res); + break; + case '?unused-fetched-body': + event.respondWith(fetch('other.html').then(function(res){ + return res; + })); + break; + case '?used-fetched-body': + event.respondWith(fetch('other.html').then(function(res){ + res.text(); + return res; + })); + break; + } + }); + +self.addEventListener('fetch', function(event) {}); + +self.addEventListener('fetch', function(event) { + var testcase = new URL(event.request.url).search; + if (testcase == '?prevent-default-and-respond-with') + event.respondWith(new Response('responding!')); + }); + +self.addEventListener('fetch', function(event) {}); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-redirect-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-redirect-iframe.html new file mode 100644 index 00000000000..499e9677569 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-redirect-iframe.html @@ -0,0 +1,20 @@ + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-stops-propagation-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-stops-propagation-worker.js new file mode 100644 index 00000000000..18da049d69f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-stops-propagation-worker.js @@ -0,0 +1,15 @@ +var result = null; + +self.addEventListener('message', function(event) { + event.data.port.postMessage(result); + }); + +self.addEventListener('fetch', function(event) { + if (!result) + result = 'PASS'; + event.respondWith(new Response()); + }); + +self.addEventListener('fetch', function(event) { + result = 'FAIL: fetch event propagated'; + }); 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 new file mode 100644 index 00000000000..5180c30f7d4 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-test-worker.js @@ -0,0 +1,131 @@ +function handleString(event) { + event.respondWith(new Response('Test string')); +} + +function handleBlob(event) { + event.respondWith(new Response(new Blob(['Test blob']))); +} + +function handleReferrer(event) { + event.respondWith(new Response(new Blob( + ['Referrer: ' + event.request.referrer]))); +} + +function handleReferrerPolicy(event) { + event.respondWith(new Response(new Blob( + ['ReferrerPolicy: ' + event.request.referrerPolicy]))); +} + +function handleReferrerFull(event) { + event.respondWith(new Response(new Blob( + ['Referrer: ' + event.request.referrer + '\n' + + 'ReferrerPolicy: ' + event.request.referrerPolicy]))); +} + +function handleClientId(event) { + var body; + if (event.clientId !== null) { + body = 'Client ID Found: ' + event.clientId; + } else { + body = 'Client ID Not Found'; + } + event.respondWith(new Response(body)); +} + +function handleNullBody(event) { + event.respondWith(new Response()); +} + +function handleFetch(event) { + event.respondWith(fetch('other.html')); +} + +function handleFormPost(event) { + event.respondWith(new Promise(function(resolve) { + event.request.text() + .then(function(result) { + resolve(new Response(event.request.method + ':' + + event.request.headers.get('Content-Type') + ':' + + result)); + }); + })); +} + +function handleMultipleRespondWith(event) { + var logForMultipleRespondWith = ''; + for (var i = 0; i < 3; ++i) { + logForMultipleRespondWith += '(' + i + ')'; + try { + event.respondWith(new Promise(function(resolve) { + setTimeout(function() { + resolve(new Response(logForMultipleRespondWith)); + }, 0); + })); + } catch (e) { + logForMultipleRespondWith += '[' + e.name + ']'; + } + } +} + +var lastResponseForUsedCheck = undefined; + +function handleUsedCheck(event) { + if (!lastResponseForUsedCheck) { + event.respondWith(fetch('other.html').then(function(response) { + lastResponseForUsedCheck = response; + return response; + })); + } else { + event.respondWith(new Response( + 'bodyUsed: ' + lastResponseForUsedCheck.bodyUsed)); + } +} + +function handleFragmentCheck(event) { + var body; + if (event.request.url.indexOf('#') === -1) { + body = 'Fragment Not Found'; + } else { + body = 'Fragment Found'; + } + event.respondWith(new Response(body)); +} + +function handleCache(event) { + event.respondWith(new Response(event.request.cache)); +} + +self.addEventListener('fetch', function(event) { + var url = event.request.url; + var handlers = [ + { pattern: '?string', fn: handleString }, + { pattern: '?blob', fn: handleBlob }, + { pattern: '?referrerFull', fn: handleReferrerFull }, + { pattern: '?referrerPolicy', fn: handleReferrerPolicy }, + { pattern: '?referrer', fn: handleReferrer }, + { pattern: '?clientId', fn: handleClientId }, + { pattern: '?ignore', fn: function() {} }, + { pattern: '?null', fn: handleNullBody }, + { pattern: '?fetch', fn: handleFetch }, + { pattern: '?form-post', fn: handleFormPost }, + { pattern: '?multiple-respond-with', fn: handleMultipleRespondWith }, + { pattern: '?used-check', fn: handleUsedCheck }, + { pattern: '?fragment-check', fn: handleFragmentCheck }, + { pattern: '?cache', fn: handleCache }, + ]; + + 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(new Response(new Blob( + ['Service Worker got an unexpected request: ' + url]))); + } + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-header-visibility-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-header-visibility-iframe.html new file mode 100644 index 00000000000..e0f32f75477 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-header-visibility-iframe.html @@ -0,0 +1,66 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-inscope.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-inscope.html new file mode 100644 index 00000000000..a7db229cecc --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-inscope.html @@ -0,0 +1,71 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-outscope.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-outscope.html new file mode 100644 index 00000000000..cec00cb25e4 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-outscope.html @@ -0,0 +1,80 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-mixed-content-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-mixed-content-iframe.html new file mode 100644 index 00000000000..961fd2ab699 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-mixed-content-iframe.html @@ -0,0 +1,71 @@ + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-iframe.html new file mode 100644 index 00000000000..0edf2e7f965 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-iframe.html @@ -0,0 +1 @@ + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-style.css b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-style.css new file mode 100644 index 00000000000..7643f667adb --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-style.css @@ -0,0 +1 @@ +body { background-image: url("./dummy.png");} diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-worker.js new file mode 100644 index 00000000000..0d9244ec75c --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-worker.js @@ -0,0 +1,27 @@ +importScripts('../resources/get-host-info.sub.js'); +importScripts('test-helpers.sub.js'); + +var port = undefined; + +self.onmessage = function(e) { + var message = e.data; + if ('port' in message) { + port = message.port; + port.postMessage({ready: true}); + } +}; + +self.addEventListener('fetch', function(event) { + var url = event.request.url; + if (url.indexOf('fetch-request-css-base-url-style.css') != -1) { + event.respondWith(fetch( + get_host_info()['HTTPS_REMOTE_ORIGIN'] + base_path() + + 'fetch-request-css-base-url-style.css', + {mode: 'no-cors'})); + } else if (url.indexOf('dummy.png') != -1) { + port.postMessage({ + url: event.request.url, + referrer: event.request.referrer + }); + } + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-fallback-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-fallback-iframe.html new file mode 100644 index 00000000000..f00d24e37a8 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-fallback-iframe.html @@ -0,0 +1,15 @@ + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-fallback-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-fallback-worker.js new file mode 100644 index 00000000000..3b028b24bde --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-fallback-worker.js @@ -0,0 +1,13 @@ +var requests = []; + +self.addEventListener('message', function(event) { + event.data.port.postMessage({requests: requests}); + requests = []; + }); + +self.addEventListener('fetch', function(event) { + requests.push({ + url: event.request.url, + mode: event.request.mode + }); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-no-freshness-headers-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-no-freshness-headers-iframe.html new file mode 100644 index 00000000000..68a1a868760 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-no-freshness-headers-iframe.html @@ -0,0 +1 @@ + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-no-freshness-headers-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-no-freshness-headers-worker.js new file mode 100644 index 00000000000..2bd59d73922 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-no-freshness-headers-worker.js @@ -0,0 +1,18 @@ +var requests = []; + +self.addEventListener('message', function(event) { + event.data.port.postMessage({requests: requests}); + }); + +self.addEventListener('fetch', function(event) { + var url = event.request.url; + var headers = []; + for (var header of event.request.headers) { + headers.push(header); + } + requests.push({ + url: url, + headers: headers + }); + event.respondWith(fetch(event.request)); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html new file mode 100644 index 00000000000..ffd76bfc499 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html @@ -0,0 +1,35 @@ + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-iframe.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-iframe.https.html new file mode 100644 index 00000000000..cadbff45cae --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-iframe.https.html @@ -0,0 +1,51 @@ + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-worker.js new file mode 100644 index 00000000000..9ec1dc62822 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-worker.js @@ -0,0 +1,23 @@ +var requests = []; +var port = undefined; + +self.onmessage = function(e) { + var message = e.data; + if ('port' in message) { + port = message.port; + port.postMessage({ready: true}); + } +}; + +self.addEventListener('fetch', function(event) { + var url = event.request.url; + if (url.indexOf('dummy?test') == -1) { + return; + } + port.postMessage({ + url: url, + mode: event.request.mode, + credentials: event.request.credentials + }); + event.respondWith(Promise.reject()); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-iframe.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-iframe.https.html new file mode 100644 index 00000000000..26c6b734467 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-iframe.https.html @@ -0,0 +1,179 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-worker.js new file mode 100644 index 00000000000..91b3abb14d9 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-worker.js @@ -0,0 +1,22 @@ +self.addEventListener('fetch', function(event) { + var url = event.request.url; + if (url.indexOf('dummy?test') == -1) { + return; + } + event.respondWith(new Promise(function(resolve) { + var headers = []; + for (var header of event.request.headers) { + headers.push(header); + } + event.request.text() + .then(function(result) { + resolve(new Response(JSON.stringify({ + method: event.request.method, + mode: event.request.mode, + credentials: event.request.credentials, + headers: headers, + body: result + }))); + }); + })); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-response-xhr-iframe.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-response-xhr-iframe.https.html new file mode 100644 index 00000000000..3391381e38a --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-response-xhr-iframe.https.html @@ -0,0 +1,35 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-response-xhr-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-response-xhr-worker.js new file mode 100644 index 00000000000..465fbc91baa --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-response-xhr-worker.js @@ -0,0 +1,12 @@ +self.addEventListener('fetch', function(event) { + var url = event.request.url; + if (url.indexOf('dummy?test') == -1) { + return; + } + event.respondWith(new Promise(function(resolve) { + var headers = new Headers; + headers.append('foo', 'foo'); + headers.append('foo', 'bar'); + resolve(new Response('hello world', {'headers': headers})); + })); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-rewrite-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-rewrite-worker.js new file mode 100644 index 00000000000..3929f2cccf1 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-rewrite-worker.js @@ -0,0 +1,118 @@ +function get_query_params(url) { + var search = (new URL(url)).search; + if (!search) { + return {}; + } + var ret = {}; + var params = search.substring(1).split('&'); + params.forEach(function(param) { + var element = param.split('='); + ret[decodeURIComponent(element[0])] = decodeURIComponent(element[1]); + }); + return ret; +} + +function get_request_init(base, params) { + var init = {}; + init['method'] = params['method'] || base['method']; + init['mode'] = params['mode'] || base['mode']; + if (init['mode'] == 'navigate') { + init['mode'] = 'same-origin'; + } + init['credentials'] = params['credentials'] || base['credentials']; + init['redirect'] = params['redirect-mode'] || base['redirect']; + return init; +} + +self.addEventListener('fetch', function(event) { + var params = get_query_params(event.request.url); + var init = get_request_init(event.request, params); + var url = params['url']; + if (params['ignore']) { + return; + } + if (params['throw']) { + throw new Error('boom'); + } + if (params['reject']) { + event.respondWith(new Promise(function(resolve, reject) { + reject(); + })); + return; + } + if (params['resolve-null']) { + event.respondWith(new Promise(function(resolve) { + resolve(null); + })); + return; + } + if (params['generate-png']) { + var binary = atob( + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAA' + + 'RnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAhSURBVDhPY3wro/Kf' + + 'gQLABKXJBqMGjBoAAqMGDLwBDAwAEsoCTFWunmQAAAAASUVORK5CYII='); + var array = new Uint8Array(binary.length); + for(var i = 0; i < binary.length; i++) { + array[i] = binary.charCodeAt(i); + }; + event.respondWith(new Response(new Blob([array], {type: 'image/png'}))); + return; + } + if (params['check-ua-header']) { + var ua = event.request.headers.get('User-Agent'); + if (ua) { + // We have a user agent! + event.respondWith(new Response(new Blob([ua]))); + } else { + // We don't have a user-agent! + event.respondWith(new Response(new Blob(["NO_UA"]))); + } + return; + } + if (params['check-accept-header']) { + var accept = event.request.headers.get('Accept'); + if (accept) { + event.respondWith(new Response(accept)); + } else { + event.respondWith(new Response('NO_ACCEPT')); + } + } + event.respondWith(new Promise(function(resolve, reject) { + var request = event.request; + if (url) { + request = new Request(url, init); + } + fetch(request).then(function(response) { + var expectedType = params['expected_type']; + if (expectedType && response.type !== expectedType) { + // Resolve a JSON object with a failure instead of rejecting + // in order to distinguish this from a NetworkError, which + // may be expected even if the type is correct. + resolve(new Response(JSON.stringify({ + result: 'failure', + detail: 'got ' + response.type + ' Response.type instead of ' + + expectedType + }))); + } + + if (params['cache']) { + var cacheName = "cached-fetches-" + Date.now(); + var cache; + var cachedResponse; + return self.caches.open(cacheName).then(function(opened) { + cache = opened; + return cache.put(request, response); + }).then(function() { + return cache.match(request); + }).then(function(cached) { + cachedResponse = cached; + return self.caches.delete(cacheName); + }).then(function() { + resolve(cachedResponse); + }); + } else { + resolve(response); + } + }, reject) + })); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-waits-for-activate-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-waits-for-activate-worker.js new file mode 100644 index 00000000000..66f3e593619 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-waits-for-activate-worker.js @@ -0,0 +1,17 @@ +var activatePromiseResolve; + +addEventListener('activate', function(evt) { + evt.waitUntil(new Promise(function(resolve) { + activatePromiseResolve = resolve; + })); +}); + +addEventListener('message', function(evt) { + if (typeof activatePromiseResolve === 'function') { + activatePromiseResolve(); + } +}); + +addEventListener('fetch', function(evt) { + evt.respondWith(new Response('Hello world')); +}); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/frame-for-getregistrations.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/frame-for-getregistrations.html new file mode 100644 index 00000000000..7fc35f18914 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/frame-for-getregistrations.html @@ -0,0 +1,19 @@ + +Service Worker: frame for getRegistrations() + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/get-host-info.sub.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/get-host-info.sub.js new file mode 100644 index 00000000000..b64334df667 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/get-host-info.sub.js @@ -0,0 +1,26 @@ +function get_host_info() { + var ORIGINAL_HOST = '127.0.0.1'; + var REMOTE_HOST = 'localhost'; + var UNAUTHENTICATED_HOST = 'example.test'; + var HTTP_PORT = 8000; + var HTTPS_PORT = 8443; + try { + // In W3C test, we can get the hostname and port number in config.json + // using wptserve's built-in pipe. + // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes + HTTP_PORT = eval('{{ports[http][0]}}'); + HTTPS_PORT = eval('{{ports[https][0]}}'); + ORIGINAL_HOST = eval('\'{{host}}\''); + REMOTE_HOST = 'www1.' + ORIGINAL_HOST; + } catch (e) { + } + return { + HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT, + HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT, + HTTPS_ORIGIN_WITH_CREDS: 'https://foo:bar@' + ORIGINAL_HOST + ':' + HTTPS_PORT, + HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT, + HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT, + HTTPS_REMOTE_ORIGIN_WITH_CREDS: 'https://foo:bar@' + REMOTE_HOST + ':' + HTTPS_PORT, + UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT + }; +} diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/indexeddb-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/indexeddb-worker.js new file mode 100644 index 00000000000..ef89550b3e0 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/indexeddb-worker.js @@ -0,0 +1,26 @@ +var port; +self.addEventListener('message', function(e) { + var message = e.data; + if ('port' in message) + doIndexedDBTest(message.port); + }); + +function doIndexedDBTest(port) { + var delete_request = indexedDB.deleteDatabase('db'); + delete_request.onsuccess = function() { + var open_request = indexedDB.open('db'); + open_request.onupgradeneeded = function() { + var db = open_request.result; + db.createObjectStore('store'); + }; + open_request.onsuccess = function() { + var db = open_request.result; + var tx = db.transaction('store', 'readwrite'); + var store = tx.objectStore('store'); + store.put('value', 'key'); + tx.oncomplete = function() { + port.postMessage('done'); + }; + }; + }; +} diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/install-event-type-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/install-event-type-worker.js new file mode 100644 index 00000000000..d729afa090c --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/install-event-type-worker.js @@ -0,0 +1,8 @@ +importScripts('worker-testharness.js'); + +self.oninstall = function(event) { + assert_true(event instanceof ExtendableEvent); + assert_equals(event.type, 'install'); + assert_false(event.cancelable); + assert_false(event.bubbles); +}; 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 new file mode 100644 index 00000000000..2ed7ef4bdf6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-worker.sub.js @@ -0,0 +1,108 @@ +importScripts('interfaces.js'); +importScripts('worker-testharness.js'); +importScripts('../resources/testharness-helpers.js'); + +var EVENT_HANDLER = 'object'; + +test(function() { + verify_interface('ServiceWorkerGlobalScope', + self, + { + clients: 'object', + close: 'function', + registration: 'object', + skipWaiting: 'function', + + onactivate: EVENT_HANDLER, + onfetch: EVENT_HANDLER, + oninstall: EVENT_HANDLER, + onmessage: EVENT_HANDLER + }); + }, 'ServiceWorkerGlobalScope'); + +test(function() { + verify_interface('Clients', + self.clients, + { + claim: 'function', + matchAll: 'function' + }); + }, 'Clients'); + +test(function() { + verify_interface('Client'); + // FIXME: Get an instance and test it, or ensure property exists on + // prototype. + }, 'Client'); + +test(function() { + verify_interface('WindowClient'); + // FIXME: Get an instance and test it, or ensure property exists on + // prototype. + }, 'WindowClient'); + +test(function() { + verify_interface('CacheStorage', + self.caches, + { + match: 'function', + has: 'function', + open: 'function', + delete: 'function', + keys: 'function' + }); + }, 'CacheStorage'); + +promise_test(function(t) { + return create_temporary_cache(t) + .then(function(cache) { + verify_interface('Cache', + cache, + { + match: 'function', + matchAll: 'function', + add: 'function', + addAll: 'function', + put: 'function', + delete: 'function', + keys: 'function' + }); + }); + }, 'Cache'); + +test(function() { + var req = new Request('http://{{host}}/', + {method: 'POST', + headers: [['Content-Type', 'Text/Html']]}); + assert_equals( + new ExtendableEvent('ExtendableEvent').type, + 'ExtendableEvent', 'Type of ExtendableEvent should be ExtendableEvent'); + assert_equals( + new FetchEvent('FetchEvent', {request: req}).type, + 'FetchEvent', 'Type of FetchEvent should be FetchEvent'); + assert_equals( + new FetchEvent('FetchEvent', {request: req}).cancelable, + false, 'Default FetchEvent.cancelable should be false'); + assert_equals( + new FetchEvent('FetchEvent', {request: req}).bubbles, + 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'); + assert_equals( + new FetchEvent('FetchEvent', {request: req, cancelable: false}).cancelable, + false, 'FetchEvent.cancelable should be false'); + assert_equals( + 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, + 'http://{{host}}/', + 'FetchEvent.request.url should return the value it was initialized to'); + }, 'Event constructors'); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces.js new file mode 100644 index 00000000000..eb00df65ff3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces.js @@ -0,0 +1,15 @@ +function verify_interface(name, instance, attributes) { + assert_true(name in self, + name + ' should be an defined type'); + if (instance) { + assert_true(instance instanceof self[name], + instance + ' should be an instance of ' + name); + Object.keys(attributes || {}).forEach(function(attribute) { + var type = attributes[attribute]; + assert_true(attribute in instance, + attribute + ' should be an attribute of ' + name); + assert_equals(typeof instance[attribute], type, + attribute + ' should be of type ' + type); + }); + } +} diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-blobtype-iframe.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-blobtype-iframe.https.html new file mode 100644 index 00000000000..f111bd9244e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-blobtype-iframe.https.html @@ -0,0 +1,29 @@ + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-blobtype-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-blobtype-worker.js new file mode 100644 index 00000000000..93f496ef44e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-blobtype-worker.js @@ -0,0 +1,10 @@ +self.addEventListener('fetch', function(event) { + var url = event.request.url; + if (url.indexOf('dummy?test') == -1) { + return; + } + event.respondWith(new Promise(function(resolve) { + // null byte in blob type + resolve(new Response(new Blob([],{type: 'a\0b'}))); + })); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-chunked-encoding-with-flush.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-chunked-encoding-with-flush.py new file mode 100644 index 00000000000..c91250a9d1f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-chunked-encoding-with-flush.py @@ -0,0 +1,11 @@ +import time +def main(request, response): + response.headers.set("Content-Type", "application/javascript") + response.headers.set("Transfer-encoding", "chunked") + response.write_status_headers() + + time.sleep(1) + response.explicit_flush = True + + response.writer.write("XX\r\n\r\n") + response.writer.flush() diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-chunked-encoding.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-chunked-encoding.py new file mode 100644 index 00000000000..ae2c1f21b2e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-chunked-encoding.py @@ -0,0 +1,2 @@ +def main(request, response): + return [("Content-Type", "application/javascript"), ("Transfer-encoding", "chunked")], "XX\r\n\r\n" diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-header-iframe.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-header-iframe.https.html new file mode 100644 index 00000000000..19f302c3510 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-header-iframe.https.html @@ -0,0 +1,26 @@ + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-header-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-header-worker.js new file mode 100644 index 00000000000..31e7f29d06f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/invalid-header-worker.js @@ -0,0 +1,12 @@ +self.addEventListener('fetch', function(event) { + var url = event.request.url; + if (url.indexOf('dummy?test') == -1) { + return; + } + event.respondWith(new Promise(function(resolve) { + var headers = new Headers; + headers.append('foo', 'foo'); + headers.append('foo', 'b\0r'); // header value with a null byte + resolve(new Response('hello world', {'headers': headers})); + })); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/load_worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/load_worker.js new file mode 100644 index 00000000000..2c80f25a3db --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/load_worker.js @@ -0,0 +1,29 @@ +self.onmessage = function (evt) { + if (evt.data == "xhr") { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "synthesized-response.txt", true); + xhr.responseType = "text"; + xhr.send(); + xhr.onload = function (evt) { + postMessage(xhr.responseText); + }; + xhr.onerror = function() { + postMessage("XHR failed!"); + }; + } else if (evt.data == "fetch") { + fetch("synthesized-response.txt") + .then(function(response) { + return response.text(); + }) + .then(function(data) { + postMessage(data); + }) + .catch(function(error) { + postMessage("Fetch failed!"); + }); + } else if (evt.data == "importScripts") { + importScripts("synthesized-response.js"); + } else { + throw "Unexpected message! " + evt.data; + } +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/malformed-worker.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/malformed-worker.py new file mode 100644 index 00000000000..501521ff3e3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/malformed-worker.py @@ -0,0 +1,10 @@ +def main(request, response): + headers = [("Content-Type", "application/javascript")] + + body = {'parse-error': 'var foo = function() {;', + 'undefined-error': 'foo.bar = 42;', + 'uncaught-exception': 'throw new DOMException("AbortError");', + 'caught-exception': 'try { throw new Error; } catch(e) {}', + 'import-malformed-script': 'importScripts("malformed-worker.py?parse-error");', + 'import-no-such-script': 'importScripts("no-such-script.js");'}[request.url_parts.query] + return headers, body diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/mime-type-worker.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/mime-type-worker.py new file mode 100644 index 00000000000..a16684de5cb --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/mime-type-worker.py @@ -0,0 +1,4 @@ +def main(request, response): + if 'mime' in request.GET: + return [('Content-Type', request.GET['mime'])], "" + return [], "" diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-other-origin.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-other-origin.html new file mode 100644 index 00000000000..c1441ba685a --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-other-origin.html @@ -0,0 +1,66 @@ + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-out-scope.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-out-scope.py new file mode 100644 index 00000000000..4b40762d89f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-out-scope.py @@ -0,0 +1,15 @@ +def main(request, response): + if "url" in request.GET: + headers = [("Location", request.GET["url"])] + return 302, headers, '' + + return [], ''' + + +''' diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-scope1.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-scope1.py new file mode 100644 index 00000000000..4b40762d89f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-scope1.py @@ -0,0 +1,15 @@ +def main(request, response): + if "url" in request.GET: + headers = [("Location", request.GET["url"])] + return 302, headers, '' + + return [], ''' + + +''' diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-scope2.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-scope2.py new file mode 100644 index 00000000000..4b40762d89f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-scope2.py @@ -0,0 +1,15 @@ +def main(request, response): + if "url" in request.GET: + headers = [("Location", request.GET["url"])] + return 302, headers, '' + + return [], ''' + + +''' diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-worker.js new file mode 100644 index 00000000000..cb15b3ff113 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/navigation-redirect-worker.js @@ -0,0 +1,75 @@ +// We store an empty response for each fetch event request we see +// in this Cache object so we can get the list of urls in the +// message event. +var cacheName = 'urls-' + self.registration.scope; + +var waitUntilPromiseList = []; + +self.addEventListener('message', function(event) { + var urls; + event.waitUntil(Promise.all(waitUntilPromiseList).then(function() { + waitUntilPromiseList = []; + return caches.open(cacheName); + }).then(function(cache) { + return cache.keys(); + }).then(function(requestList) { + urls = requestList.map(function(request) { return request.url; }); + return caches.delete(cacheName); + }).then(function() { + event.data.port.postMessage({urls: urls}); + })); + }); + +function get_query_params(url) { + var search = (new URL(url)).search; + if (!search) { + return {}; + } + var ret = {}; + var params = search.substring(1).split('&'); + params.forEach(function(param) { + var element = param.split('='); + ret[decodeURIComponent(element[0])] = decodeURIComponent(element[1]); + }); + return ret; +} + +self.addEventListener('fetch', function(event) { + var waitUntilPromise = caches.open(cacheName).then(function(cache) { + return cache.put(event.request, new Response()); + }); + event.waitUntil(waitUntilPromise); + + var params = get_query_params(event.request.url); + if (!params['sw']) { + // To avoid races, add the waitUntil() promise to our global list. + // If we get a message event before we finish here, it will wait + // these promises to complete before proceeding to read from the + // cache. + waitUntilPromiseList.push(waitUntilPromise); + return; + } + + event.respondWith(waitUntilPromise.then(function() { + if (params['sw'] == 'gen') { + return Response.redirect(params['url']); + } else if (params['sw'] == 'fetch') { + return fetch(event.request); + } else if (params['sw'] == 'opaque') { + return fetch(new Request(event.request.url, {redirect: 'manual'})); + } else if (params['sw'] == 'opaqueThroughCache') { + var url = event.request.url; + var cache; + return caches.delete(url) + .then(function() { return self.caches.open(url); }) + .then(function(c) { + cache = c; + return fetch(new Request(url, {redirect: 'manual'})); + }) + .then(function(res) { return cache.put(event.request, res); }) + .then(function() { return cache.match(url); }); + } + + // unexpected... trigger an interception failure + })); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-from-nested-event-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-from-nested-event-worker.js new file mode 100644 index 00000000000..7c97014fd04 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-from-nested-event-worker.js @@ -0,0 +1,13 @@ +var max_nesting_level = 8; + +self.addEventListener('message', function(event) { + var level = event.data; + if (level < max_nesting_level) + dispatchEvent(new MessageEvent('message', { data: level + 1 })); + throw Error('error at level ' + level); + }); + +self.addEventListener('activate', function(event) { + dispatchEvent(new MessageEvent('message', { data: 1 })); + }); + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-then-cancel-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-then-cancel-worker.js new file mode 100644 index 00000000000..0bd9d318b24 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-then-cancel-worker.js @@ -0,0 +1,3 @@ +self.onerror = function(event) { return true; }; + +self.addEventListener('activate', function(event) { throw new Error(); }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-then-prevent-default-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-then-prevent-default-worker.js new file mode 100644 index 00000000000..d56c9511391 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-then-prevent-default-worker.js @@ -0,0 +1,7 @@ +// Ensure we can handle multiple error handlers. One error handler +// calling preventDefault should cause the event to be treated as +// handled. +self.addEventListener('error', function(event) {}); +self.addEventListener('error', function(event) { event.preventDefault(); }); +self.addEventListener('error', function(event) {}); +self.addEventListener('activate', function(event) { throw new Error(); }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-with-empty-onerror-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-with-empty-onerror-worker.js new file mode 100644 index 00000000000..eb12ae862c5 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-with-empty-onerror-worker.js @@ -0,0 +1,2 @@ +self.addEventListener('error', function(event) {}); +self.addEventListener('activate', function(event) { throw new Error(); }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-worker.js new file mode 100644 index 00000000000..1e88ac5c4e7 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/onactivate-throw-error-worker.js @@ -0,0 +1,7 @@ +// Ensure we can handle multiple activate handlers. One handler throwing an +// error should cause the event dispatch to be treated as having unhandled +// errors. +self.addEventListener('activate', function(event) {}); +self.addEventListener('activate', function(event) {}); +self.addEventListener('activate', function(event) { throw new Error(); }); +self.addEventListener('activate', function(event) {}); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-from-nested-event-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-from-nested-event-worker.js new file mode 100644 index 00000000000..6729ab61a37 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-from-nested-event-worker.js @@ -0,0 +1,12 @@ +var max_nesting_level = 8; + +self.addEventListener('message', function(event) { + var level = event.data; + if (level < max_nesting_level) + dispatchEvent(new MessageEvent('message', { data: level + 1 })); + throw Error('error at level ' + level); + }); + +self.addEventListener('install', function(event) { + dispatchEvent(new MessageEvent('message', { data: 1 })); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-then-cancel-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-then-cancel-worker.js new file mode 100644 index 00000000000..c2c499ab1a3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-then-cancel-worker.js @@ -0,0 +1,3 @@ +self.onerror = function(event) { return true; }; + +self.addEventListener('install', function(event) { throw new Error(); }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-then-prevent-default-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-then-prevent-default-worker.js new file mode 100644 index 00000000000..7667c2781d0 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-then-prevent-default-worker.js @@ -0,0 +1,7 @@ +// Ensure we can handle multiple error handlers. One error handler +// calling preventDefault should cause the event to be treated as +// handled. +self.addEventListener('error', function(event) {}); +self.addEventListener('error', function(event) { event.preventDefault(); }); +self.addEventListener('error', function(event) {}); +self.addEventListener('install', function(event) { throw new Error(); }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-with-empty-onerror-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-with-empty-onerror-worker.js new file mode 100644 index 00000000000..8f56d1bf149 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-with-empty-onerror-worker.js @@ -0,0 +1,2 @@ +self.addEventListener('error', function(event) {}); +self.addEventListener('install', function(event) { throw new Error(); }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-worker.js new file mode 100644 index 00000000000..cc2f6d7e5e7 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/oninstall-throw-error-worker.js @@ -0,0 +1,7 @@ +// Ensure we can handle multiple install handlers. One handler throwing an +// error should cause the event dispatch to be treated as having unhandled +// errors. +self.addEventListener('install', function(event) {}); +self.addEventListener('install', function(event) {}); +self.addEventListener('install', function(event) { throw new Error(); }); +self.addEventListener('install', function(event) {}); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/other.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/other.html new file mode 100644 index 00000000000..b9f35043877 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/other.html @@ -0,0 +1,3 @@ + +Other +Here's an other html file. diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/override_assert_object_equals.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/override_assert_object_equals.js new file mode 100644 index 00000000000..835046d472b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/override_assert_object_equals.js @@ -0,0 +1,58 @@ +// .body attribute of Request and Response object are experimental feture. It is +// enabled when --enable-experimental-web-platform-features flag is set. +// Touching this attribute can change the behavior of the objects. To avoid +// touching it while comparing the objects in LayoutTest, we overwrite +// assert_object_equals method. + +(function() { + var original_assert_object_equals = self.assert_object_equals; + function _brand(object) { + return Object.prototype.toString.call(object).match(/^\[object (.*)\]$/)[1]; + } + var assert_request_equals = function(actual, expected, prefix) { + if (typeof actual !== 'object') { + assert_equals(actual, expected, prefix); + return; + } + assert_true(actual instanceof Request, prefix); + assert_true(expected instanceof Request, prefix); + assert_equals(actual.bodyUsed, expected.bodyUsed, prefix + '.bodyUsed'); + assert_equals(actual.method, expected.method, prefix + '.method'); + assert_equals(actual.url, expected.url, prefix + '.url'); + original_assert_object_equals(actual.headers, expected.headers, + prefix + '.headers'); + assert_equals(actual.context, expected.context, prefix + '.context'); + assert_equals(actual.referrer, expected.referrer, prefix + '.referrer'); + assert_equals(actual.mode, expected.mode, prefix + '.mode'); + assert_equals(actual.credentials, expected.credentials, + prefix + '.credentials'); + assert_equals(actual.cache, expected.cache, prefix + '.cache'); + }; + var assert_response_equals = function(actual, expected, prefix) { + if (typeof actual !== 'object') { + assert_equals(actual, expected, prefix); + return; + } + assert_true(actual instanceof Response, prefix); + assert_true(expected instanceof Response, prefix); + assert_equals(actual.bodyUsed, expected.bodyUsed, prefix + '.bodyUsed'); + assert_equals(actual.type, expected.type, prefix + '.type'); + assert_equals(actual.url, expected.url, prefix + '.url'); + assert_equals(actual.status, expected.status, prefix + '.status'); + assert_equals(actual.statusText, expected.statusText, + prefix + '.statusText'); + original_assert_object_equals(actual.headers, expected.headers, + prefix + '.headers'); + }; + var assert_object_equals = function(actual, expected, description) { + var prefix = (description ? description + ': ' : '') + _brand(expected); + if (expected instanceof Request) { + assert_request_equals(actual, expected, prefix); + } else if (expected instanceof Response) { + assert_response_equals(actual, expected, prefix); + } else { + original_assert_object_equals(actual, expected, description); + } + }; + self.assert_object_equals = assert_object_equals; +})(); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/performance-timeline-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/performance-timeline-worker.js new file mode 100644 index 00000000000..6f7df75e921 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/performance-timeline-worker.js @@ -0,0 +1,58 @@ +importScripts('/resources/testharness.js'); + +promise_test(function(test) { + var durationMsec = 100; + // There are limits to our accuracy here. Timers may fire up to a + // millisecond early due to platform-dependent rounding. In addition + // the performance API introduces some rounding as well to prevent + // timing attacks. + var accuracy = 1.5; + return new Promise(function(resolve) { + performance.mark('startMark'); + setTimeout(resolve, durationMsec); + }).then(function() { + performance.mark('endMark'); + performance.measure('measure', 'startMark', 'endMark'); + var startMark = performance.getEntriesByName('startMark')[0]; + var endMark = performance.getEntriesByName('endMark')[0]; + var measure = performance.getEntriesByType('measure')[0]; + assert_equals(measure.startTime, startMark.startTime); + assert_approx_equals(endMark.startTime - startMark.startTime, + measure.duration, 0.001); + assert_greater_than(measure.duration, durationMsec - accuracy); + assert_equals(performance.getEntriesByType('mark').length, 2); + assert_equals(performance.getEntriesByType('measure').length, 1); + performance.clearMarks('startMark'); + performance.clearMeasures('measure'); + assert_equals(performance.getEntriesByType('mark').length, 1); + assert_equals(performance.getEntriesByType('measure').length, 0); + }); + }, 'User Timing'); + +promise_test(function(test) { + return fetch('dummy.txt') + .then(function(resp) { + return resp.text(); + }) + .then(function(text) { + var expectedResources = ['testharness.js', 'dummy.txt']; + assert_equals(performance.getEntriesByType('resource').length, expectedResources.length); + for (var i = 0; i < expectedResources.length; i++) { + var entry = performance.getEntriesByType('resource')[i]; + assert_true(entry.name.endsWith(expectedResources[i])); + assert_equals(entry.workerStart, 0); + assert_greater_than(entry.startTime, 0); + assert_greater_than(entry.responseEnd, entry.startTime); + } + return new Promise(function(resolve) { + performance.onresourcetimingbufferfull = resolve; + performance.setResourceTimingBufferSize(expectedResources.length); + }); + }) + .then(function() { + performance.clearResourceTimings(); + assert_equals(performance.getEntriesByType('resource').length, 0); + }) + }, 'Resource Timing'); + +done(); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/postmessage-msgport-to-client-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/postmessage-msgport-to-client-worker.js new file mode 100644 index 00000000000..3475321f4a6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/postmessage-msgport-to-client-worker.js @@ -0,0 +1,20 @@ +self.onmessage = function(e) { + self.clients.matchAll().then(function(clients) { + clients.forEach(function(client) { + var messageChannel = new MessageChannel(); + messageChannel.port1.onmessage = + onMessageViaMessagePort.bind(null, client); + client.postMessage({port: messageChannel.port2}, + [messageChannel.port2]); + }); + }); +}; + +function onMessageViaMessagePort(client, e) { + var message = e.data; + if ('value' in message) { + client.postMessage({ack: 'Acking value: ' + message.value}); + } else if ('done' in message) { + client.postMessage({done: true}); + } +} diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/postmessage-to-client-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/postmessage-to-client-worker.js new file mode 100644 index 00000000000..290a4a9b3e9 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/postmessage-to-client-worker.js @@ -0,0 +1,10 @@ +self.onmessage = function(e) { + self.clients.matchAll().then(function(clients) { + clients.forEach(function(client) { + client.postMessage('Sending message via clients'); + if (!Array.isArray(clients)) + client.postMessage('clients is not an array'); + client.postMessage('quit'); + }); + }); +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/postmessage-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/postmessage-worker.js new file mode 100644 index 00000000000..858cf04267c --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/postmessage-worker.js @@ -0,0 +1,19 @@ +var port; + +// Exercise the 'onmessage' handler: +self.onmessage = function(e) { + var message = e.data; + if ('port' in message) { + port = message.port; + } +}; + +// And an event listener: +self.addEventListener('message', function(e) { + var message = e.data; + if ('value' in message) { + port.postMessage('Acking value: ' + message.value); + } else if ('done' in message) { + port.postMessage('quit'); + } + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/redirect.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/redirect.py new file mode 100644 index 00000000000..20521b00c9c --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/redirect.py @@ -0,0 +1,25 @@ +def main(request, response): + if 'Status' in request.GET: + status = int(request.GET["Status"]) + else: + status = 302 + + headers = [] + + url = request.GET['Redirect'] + headers.append(("Location", url)) + + if "ACAOrigin" in request.GET: + for item in request.GET["ACAOrigin"].split(","): + headers.append(("Access-Control-Allow-Origin", item)) + + for suffix in ["Headers", "Methods", "Credentials"]: + query = "ACA%s" % suffix + header = "Access-Control-Allow-%s" % suffix + if query in request.GET: + headers.append((header, request.GET[query])) + + if "ACEHeaders" in request.GET: + headers.append(("Access-Control-Expose-Headers", request.GET["ACEHeaders"])) + + return status, headers, "" diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/referer-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/referer-iframe.html new file mode 100644 index 00000000000..31cadcd2c7a --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/referer-iframe.html @@ -0,0 +1,39 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/register-closed-window-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/register-closed-window-iframe.html new file mode 100644 index 00000000000..ed743ea056e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/register-closed-window-iframe.html @@ -0,0 +1,16 @@ + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/registration-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/registration-worker.js new file mode 100644 index 00000000000..44d1d2774a2 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/registration-worker.js @@ -0,0 +1 @@ +// empty for now diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/reject-install-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/reject-install-worker.js new file mode 100644 index 00000000000..41f07fd5db8 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/reject-install-worker.js @@ -0,0 +1,3 @@ +self.oninstall = function(event) { + event.waitUntil(Promise.reject()); +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/request-end-to-end-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/request-end-to-end-worker.js new file mode 100644 index 00000000000..323c7f24367 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/request-end-to-end-worker.js @@ -0,0 +1,32 @@ +var port = undefined; + +onmessage = function(e) { + var message = e.data; + if (typeof message === 'object' && 'port' in message) { + port = message.port; + } +}; + +onfetch = function(e) { + var headers = {}; + var errorNameWhileAppendingHeader; + for (var header of e.request.headers) { + var key = header[0], value = header[1]; + headers[key] = value; + } + var errorNameWhileAddingHeader = ''; + try { + e.request.headers.append('Test-Header', 'TestValue'); + } catch (e) { + errorNameWhileAppendingHeader = e.name; + } + port.postMessage({ + url: e.request.url, + mode: e.request.mode, + method: e.request.method, + referrer: e.request.referrer, + headers: headers, + headerSize: e.request.headers.size, + errorNameWhileAppendingHeader: errorNameWhileAppendingHeader + }); +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/request-headers.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/request-headers.py new file mode 100644 index 00000000000..29897f4ecff --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/request-headers.py @@ -0,0 +1,6 @@ +import json + +def main(request, response): + data = {key:request.headers[key] for key,value in request.headers.iteritems()} + + return [("Content-Type", "application/json")], json.dumps(data) 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 new file mode 100644 index 00000000000..2af6793696b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-iframe.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-worker.js new file mode 100644 index 00000000000..481a6536afc --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-worker.js @@ -0,0 +1,5 @@ +self.addEventListener('fetch', function(event) { + if (event.request.url.indexOf('dummy.js') != -1) { + event.respondWith(new Response()); + } + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/service-worker-csp-worker.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/service-worker-csp-worker.py new file mode 100644 index 00000000000..4e5c6f3b6ea --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/service-worker-csp-worker.py @@ -0,0 +1,153 @@ +bodyDefault = ''' +importScripts('worker-testharness.js'); +importScripts('test-helpers.sub.js'); +importScripts('../resources/get-host-info.sub.js'); + +var host_info = get_host_info(); + +test(function() { + var import_script_failed = false; + try { + importScripts(host_info.HTTPS_REMOTE_ORIGIN + + base_path() + 'empty.js'); + } catch(e) { + import_script_failed = true; + } + assert_true(import_script_failed, + 'Importing the other origins script should fail.'); + }, 'importScripts test for default-src'); + +async_test(function(t) { + fetch(host_info.HTTPS_REMOTE_ORIGIN + + base_path() + 'fetch-access-control.py?ACAOrigin=*', + {mode: 'cors'}) + .then(function(response){ + assert_unreached('fetch should fail.'); + }, function(){ + t.done(); + }) + .catch(unreached_rejection(t)); + }, 'Fetch test for default-src'); + +async_test(function(t) { + var REDIRECT_URL = host_info.HTTPS_ORIGIN + + base_path() + 'redirect.py?Redirect='; + var OTHER_BASE_URL = host_info.HTTPS_REMOTE_ORIGIN + + base_path() + 'fetch-access-control.py?' + fetch(REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*'), + {mode: 'cors'}) + .then(function(response){ + assert_unreached('Redirected fetch should fail.'); + }, function(){ + t.done(); + }) + .catch(unreached_rejection(t)); + }, 'Redirected fetch test for default-src');''' + +bodyScript = ''' +importScripts('worker-testharness.js'); +importScripts('test-helpers.sub.js'); +importScripts('../resources/get-host-info.sub.js'); + +var host_info = get_host_info(); + +test(function() { + var import_script_failed = false; + try { + importScripts(host_info.HTTPS_REMOTE_ORIGIN + + base_path() + 'empty.js'); + } catch(e) { + import_script_failed = true; + } + assert_true(import_script_failed, + 'Importing the other origins script should fail.'); + }, 'importScripts test for script-src'); + +async_test(function(t) { + fetch(host_info.HTTPS_REMOTE_ORIGIN + + base_path() + 'fetch-access-control.py?ACAOrigin=*', + {mode: 'cors'}) + .then(function(response){ + t.done(); + }, function(){ + assert_unreached('fetch should not fail.'); + }) + .catch(unreached_rejection(t)); + }, 'Fetch test for script-src'); + +async_test(function(t) { + var REDIRECT_URL = host_info.HTTPS_ORIGIN + + base_path() + 'redirect.py?Redirect='; + var OTHER_BASE_URL = host_info.HTTPS_REMOTE_ORIGIN + + base_path() + 'fetch-access-control.py?' + fetch(REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*'), + {mode: 'cors'}) + .then(function(response){ + t.done(); + }, function(){ + assert_unreached('Redirected fetch should not fail.'); + }) + .catch(unreached_rejection(t)); + }, 'Redirected fetch test for script-src');''' + +bodyConnect = ''' +importScripts('worker-testharness.js'); +importScripts('test-helpers.sub.js'); +importScripts('../resources/get-host-info.sub.js'); + +var host_info = get_host_info(); + +test(function() { + var import_script_failed = false; + try { + importScripts(host_info.HTTPS_REMOTE_ORIGIN + + base_path() + 'empty.js'); + } catch(e) { + import_script_failed = true; + } + assert_false(import_script_failed, + 'Importing the other origins script should not fail.'); + }, 'importScripts test for connect-src'); + +async_test(function(t) { + fetch(host_info.HTTPS_REMOTE_ORIGIN + + base_path() + 'fetch-access-control.py?ACAOrigin=*', + {mode: 'cors'}) + .then(function(response){ + assert_unreached('fetch should fail.'); + }, function(){ + t.done(); + }) + .catch(unreached_rejection(t)); + }, 'Fetch test for connect-src'); + +async_test(function(t) { + var REDIRECT_URL = host_info.HTTPS_ORIGIN + + base_path() + 'redirect.py?Redirect='; + var OTHER_BASE_URL = host_info.HTTPS_REMOTE_ORIGIN + + base_path() + 'fetch-access-control.py?' + fetch(REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*'), + {mode: 'cors'}) + .then(function(response){ + assert_unreached('Redirected fetch should fail.'); + }, function(){ + t.done(); + }) + .catch(unreached_rejection(t)); + }, 'Redirected fetch test for connect-src');''' + +def main(request, response): + headers = [] + headers.append(('Content-Type', 'application/javascript')) + directive = request.GET['directive'] + body = 'ERROR: Unknown directive' + if directive == 'default': + headers.append(('Content-Security-Policy', "default-src 'self'")) + body = bodyDefault + elif directive == 'script': + headers.append(('Content-Security-Policy', "script-src 'self'")) + body = bodyScript + elif directive == 'connect': + headers.append(('Content-Security-Policy', "connect-src 'self'")) + body = bodyConnect + return headers, body diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/shared-worker-controlled.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/shared-worker-controlled.js new file mode 100644 index 00000000000..1ccc2fe3bdb --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/shared-worker-controlled.js @@ -0,0 +1,8 @@ +onconnect = function(e) { + var port = e.ports[0]; + var xhr = new XMLHttpRequest(); + xhr.onload = function() { port.postMessage(this.responseText); }; + xhr.onerror = function(e) { port.postMessage(e); }; + xhr.open('GET', 'dummy.txt?simple', true); + xhr.send(); +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/shared-worker-import.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/shared-worker-import.js new file mode 100644 index 00000000000..7c554bd7415 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/shared-worker-import.js @@ -0,0 +1 @@ +importScripts('import-dummy-shared-worker.js'); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/silence.oga b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/silence.oga new file mode 100644 index 00000000000..af591880436 Binary files /dev/null and b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/silence.oga differ diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/simple-intercept-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/simple-intercept-worker.js new file mode 100644 index 00000000000..f8b5f8c5cb7 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/simple-intercept-worker.js @@ -0,0 +1,5 @@ +self.onfetch = function(event) { + if (event.request.url.indexOf('simple') != -1) + event.respondWith( + new Response(new Blob(['intercepted by service worker']))); +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/simple.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/simple.html new file mode 100644 index 00000000000..0c3e3e78707 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/simple.html @@ -0,0 +1,3 @@ + +Simple +Here's a simple html file. diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/simple.txt b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/simple.txt new file mode 100644 index 00000000000..9e3cb91fb9b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/simple.txt @@ -0,0 +1 @@ +a simple text file diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/skip-waiting-installed-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/skip-waiting-installed-worker.js new file mode 100644 index 00000000000..bf582c77074 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/skip-waiting-installed-worker.js @@ -0,0 +1,24 @@ +self.state = 'starting'; + +self.addEventListener('install', function() { + self.state = 'installing'; + }); + +self.addEventListener('message', function(event) { + var port = event.data.port; + if (self.state !== 'installing') { + port.postMessage('FAIL: Worker should be waiting in installed state'); + return; + } + self.skipWaiting() + .then(function(result) { + if (result !== undefined) { + port.postMessage('FAIL: Promise should be resolved with undefined'); + return; + } + port.postMessage('PASS'); + }) + .catch(function(e) { + port.postMessage('FAIL: unexpected exception: ' + e); + }); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/skip-waiting-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/skip-waiting-worker.js new file mode 100644 index 00000000000..1d6bcb39faf --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/skip-waiting-worker.js @@ -0,0 +1,25 @@ +importScripts('worker-testharness.js'); + +promise_test(function() { + // wait for the worker to reach "installing" state, otherwise skipWaiting() + // will fail. Bug 1228277 + return new Promise(function(res, rej) { + oninstall = res; + }).then(() => skipWaiting()) + .then(function(result) { + assert_equals(result, undefined, + 'Promise should be resolved with undefined'); + }) + .then(function() { + var promises = []; + for (var i = 0; i < 8; ++i) + promises.push(self.skipWaiting()); + return Promise.all(promises); + }) + .then(function(results) { + results.forEach(function(r) { + assert_equals(r, undefined, + 'Promises should be resolved with undefined'); + }); + }); + }, 'skipWaiting'); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/square.png b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/square.png new file mode 100644 index 00000000000..01c9666a8de Binary files /dev/null and b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/square.png differ diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/success.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/success.py new file mode 100644 index 00000000000..bcbb487d2b2 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/success.py @@ -0,0 +1,8 @@ +def main(request, response): + headers = [] + + if "ACAOrigin" in request.GET: + for item in request.GET["ACAOrigin"].split(","): + headers.append(("Access-Control-Allow-Origin", item)) + + return headers, "{ \"result\": \"success\" }" 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 new file mode 100644 index 00000000000..b0ffbd40625 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/test-helpers.sub.js @@ -0,0 +1,227 @@ +// Adapter for testharness.js-style tests with Service Workers + +function service_worker_unregister_and_register(test, url, scope) { + if (!scope || scope.length == 0) + return Promise.reject(new Error('tests must define a scope')); + + var options = { scope: scope }; + return service_worker_unregister(test, scope) + .then(function() { + return navigator.serviceWorker.register(url, options); + }) + .catch(unreached_rejection(test, + 'unregister and register should not fail')); +} + +// This unregisters the registration that precisely matches scope. Use this +// when unregistering by scope. If no registration is found, it just resolves. +function service_worker_unregister(test, scope) { + var absoluteScope = (new URL(scope, window.location).href); + return navigator.serviceWorker.getRegistration(scope) + .then(function(registration) { + if (registration && registration.scope === absoluteScope) + return registration.unregister(); + }) + .catch(unreached_rejection(test, 'unregister should not fail')); +} + +function service_worker_unregister_and_done(test, scope) { + return service_worker_unregister(test, scope) + .then(test.done.bind(test)); +} + +function unreached_fulfillment(test, prefix) { + return test.step_func(function(result) { + var error_prefix = prefix || 'unexpected fulfillment'; + assert_unreached(error_prefix + ': ' + result); + }); +} + +// Rejection-specific helper that provides more details +function unreached_rejection(test, prefix) { + return test.step_func(function(error) { + var reason = error.message || error.name || error; + var error_prefix = prefix || 'unexpected rejection'; + assert_unreached(error_prefix + ': ' + reason); + }); +} + +// Adds an iframe to the document and returns a promise that resolves to the +// iframe when it finishes loading. The caller is responsible for removing the +// iframe later if needed. +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 normalizeURL(url) { + return new URL(url, self.location).toString().replace(/#.*$/, ''); +} + +function wait_for_update(test, registration) { + if (!registration || registration.unregister == undefined) { + return Promise.reject(new Error( + 'wait_for_update must be passed a ServiceWorkerRegistration')); + } + + return new Promise(test.step_func(function(resolve) { + registration.addEventListener('updatefound', test.step_func(function() { + resolve(registration.installing); + })); + })); +} + +function wait_for_state(test, worker, state) { + if (!worker || worker.state == undefined) { + return Promise.reject(new Error( + 'wait_for_state must be passed a ServiceWorker')); + } + if (worker.state === state) + return Promise.resolve(state); + + if (state === 'installing') { + switch (worker.state) { + case 'installed': + case 'activating': + case 'activated': + case 'redundant': + return Promise.reject(new Error( + 'worker is ' + worker.state + ' but waiting for ' + state)); + } + } + + if (state === 'installed') { + switch (worker.state) { + case 'activating': + case 'activated': + case 'redundant': + return Promise.reject(new Error( + 'worker is ' + worker.state + ' but waiting for ' + state)); + } + } + + if (state === 'activating') { + switch (worker.state) { + case 'activated': + case 'redundant': + return Promise.reject(new Error( + 'worker is ' + worker.state + ' but waiting for ' + state)); + } + } + + if (state === 'activated') { + switch (worker.state) { + case 'redundant': + return Promise.reject(new Error( + 'worker is ' + worker.state + ' but waiting for ' + state)); + } + } + + return new Promise(test.step_func(function(resolve) { + worker.addEventListener('statechange', test.step_func(function() { + if (worker.state === state) + resolve(state); + })); + })); +} + +// Declare a test that runs entirely in the ServiceWorkerGlobalScope. The |url| +// is the service worker script URL. This function: +// - Instantiates a new test with the description specified in |description|. +// The test will succeed if the specified service worker can be successfully +// registered and installed. +// - Creates a new ServiceWorker registration with a scope unique to the current +// document URL. Note that this doesn't allow more than one +// service_worker_test() to be run from the same document. +// - Waits for the new worker to begin installing. +// - Imports tests results from tests running inside the ServiceWorker. +function service_worker_test(url, description) { + // If the document URL is https://example.com/document and the script URL is + // https://example.com/script/worker.js, then the scope would be + // https://example.com/script/scope/document. + var scope = new URL('scope' + window.location.pathname, + new URL(url, window.location)).toString(); + promise_test(function(test) { + return service_worker_unregister_and_register(test, url, scope) + .then(function(registration) { + add_completion_callback(function() { + registration.unregister(); + }); + return wait_for_update(test, registration) + .then(function(worker) { + return fetch_tests_from_worker(worker); + }); + }); + }, description); +} + +function base_path() { + return location.pathname.replace(/\/[^\/]*$/, '/'); +} + +function test_login(test, origin, username, password, cookie) { + return new Promise(function(resolve, reject) { + with_iframe( + origin + base_path() + + 'resources/fetch-access-control-login.html') + .then(test.step_func(function(frame) { + var channel = new MessageChannel(); + channel.port1.onmessage = test.step_func(function() { + frame.remove(); + resolve(); + }); + frame.contentWindow.postMessage( + {username: username, password: password, cookie: cookie}, + origin, [channel.port2]); + })); + }); +} + +function test_websocket(test, frame, url) { + return new Promise(function(resolve, reject) { + var ws = new frame.contentWindow.WebSocket(url, ['echo', 'chat']); + var openCalled = false; + ws.addEventListener('open', test.step_func(function(e) { + assert_equals(ws.readyState, 1, "The WebSocket should be open"); + openCalled = true; + ws.close(); + }), true); + + ws.addEventListener('close', test.step_func(function(e) { + assert_true(openCalled, "The WebSocket should be closed after being opened"); + resolve(); + }), true); + + ws.addEventListener('error', reject); + }); +} + +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]}}', + 'username1s', 'password1s', 'cookie1') + .then(function() { + return test_login(test, 'https://{{host}}:{{ports[https][0]}}', + 'username2s', 'password2s', 'cookie2'); + }); +} + +function websocket(test, frame) { + return test_websocket(test, frame, get_websocket_url()); +} + +function get_websocket_url() { + return 'wss://{{host}}:{{ports[wss][0]}}/echo'; +} diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/testharness-helpers.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/testharness-helpers.js new file mode 100644 index 00000000000..4d7af1ff9ca --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/testharness-helpers.js @@ -0,0 +1,163 @@ +/* + * testharness-helpers contains various useful extensions to testharness.js to + * allow them to be used across multiple tests before they have been + * upstreamed. This file is intended to be usable from both document and worker + * environments, so code should for example not rely on the DOM. + */ + +// Returns a promise that fulfills after the provided |promise| is fulfilled. +// The |test| succeeds only if |promise| rejects with an exception matching +// |code|. Accepted values for |code| follow those accepted for assert_throws(). +// The optional |description| describes the test being performed. +// +// E.g.: +// assert_promise_rejects( +// new Promise(...), // something that should throw an exception. +// 'NotFoundError', +// 'Should throw NotFoundError.'); +// +// assert_promise_rejects( +// new Promise(...), +// new TypeError(), +// 'Should throw TypeError'); +function assert_promise_rejects(promise, code, description) { + return promise.then( + function() { + throw 'assert_promise_rejects: ' + description + ' Promise did not reject.'; + }, + function(e) { + if (code !== undefined) { + assert_throws(code, function() { throw e; }, description); + } + }); +} + +// Asserts that two objects |actual| and |expected| are weakly equal under the +// following definition: +// +// |a| and |b| are weakly equal if any of the following are true: +// 1. If |a| is not an 'object', and |a| === |b|. +// 2. If |a| is an 'object', and all of the following are true: +// 2.1 |a.p| is weakly equal to |b.p| for all own properties |p| of |a|. +// 2.2 Every own property of |b| is an own property of |a|. +// +// This is a replacement for the the version of assert_object_equals() in +// testharness.js. The latter doesn't handle own properties correctly. I.e. if +// |a.p| is not an own property, it still requires that |b.p| be an own +// property. +// +// Note that |actual| must not contain cyclic references. +self.assert_object_equals = function(actual, expected, description) { + var object_stack = []; + + function _is_equal(actual, expected, prefix) { + if (typeof actual !== 'object') { + assert_equals(actual, expected, prefix); + return; + } + assert_true(typeof expected === 'object', prefix); + assert_equals(object_stack.indexOf(actual), -1, + prefix + ' must not contain cyclic references.'); + + object_stack.push(actual); + + Object.getOwnPropertyNames(expected).forEach(function(property) { + assert_own_property(actual, property, prefix); + _is_equal(actual[property], expected[property], + prefix + '.' + property); + }); + Object.getOwnPropertyNames(actual).forEach(function(property) { + assert_own_property(expected, property, prefix); + }); + + object_stack.pop(); + } + + function _brand(object) { + return Object.prototype.toString.call(object).match(/^\[object (.*)\]$/)[1]; + } + + _is_equal(actual, expected, + (description ? description + ': ' : '') + _brand(expected)); +}; + +// Equivalent to assert_in_array, but uses a weaker equivalence relation +// (assert_object_equals) than '==='. +function assert_object_in_array(actual, expected_array, description) { + assert_true(expected_array.some(function(element) { + try { + assert_object_equals(actual, element); + return true; + } catch (e) { + return false; + } + }), description); +} + +// Assert that the two arrays |actual| and |expected| contain the same set of +// elements as determined by assert_object_equals. The order is not significant. +// +// |expected| is assumed to not contain any duplicates as determined by +// assert_object_equals(). +function assert_array_equivalent(actual, expected, description) { + assert_true(Array.isArray(actual), description); + assert_equals(actual.length, expected.length, description); + expected.forEach(function(expected_element) { + // assert_in_array treats the first argument as being 'actual', and the + // second as being 'expected array'. We are switching them around because + // we want to be resilient against the |actual| array containing + // duplicates. + assert_object_in_array(expected_element, actual, description); + }); +} + +// Asserts that two arrays |actual| and |expected| contain the same set of +// elements as determined by assert_object_equals(). The corresponding elements +// must occupy corresponding indices in their respective arrays. +function assert_array_objects_equals(actual, expected, description) { + assert_true(Array.isArray(actual), description); + assert_equals(actual.length, expected.length, description); + actual.forEach(function(value, index) { + assert_object_equals(value, expected[index], + description + ' : object[' + index + ']'); + }); +} + +// Asserts that |object| that is an instance of some interface has the attribute +// |attribute_name| following the conditions specified by WebIDL, but it's +// acceptable that the attribute |attribute_name| is an own property of the +// object because we're in the middle of moving the attribute to a prototype +// chain. Once we complete the transition to prototype chains, +// assert_will_be_idl_attribute must be replaced with assert_idl_attribute +// defined in testharness.js. +// +// FIXME: Remove assert_will_be_idl_attribute once we complete the transition +// of moving the DOM attributes to prototype chains. (http://crbug.com/43394) +function assert_will_be_idl_attribute(object, attribute_name, description) { + assert_true(typeof object === "object", description); + + assert_true("hasOwnProperty" in object, description); + + // Do not test if |attribute_name| is not an own property because + // |attribute_name| is in the middle of the transition to a prototype + // chain. (http://crbug.com/43394) + + assert_true(attribute_name in object, description); +} + +// Stringifies a DOM object. This function stringifies not only own properties +// but also DOM attributes which are on a prototype chain. Note that +// JSON.stringify only stringifies own properties. +function stringifyDOMObject(object) +{ + function deepCopy(src) { + if (typeof src != "object") + return src; + var dst = Array.isArray(src) ? [] : {}; + for (var property in src) { + dst[property] = deepCopy(src[property]); + } + return dst; + } + return JSON.stringify(deepCopy(object)); +} diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/unregister-controller-page.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/unregister-controller-page.html new file mode 100644 index 00000000000..18a95ee892b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/unregister-controller-page.html @@ -0,0 +1,16 @@ + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-nocookie-worker.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-nocookie-worker.py new file mode 100644 index 00000000000..0f09b7e32c0 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-nocookie-worker.py @@ -0,0 +1,15 @@ +import time + +def main(request, response): + # no-cache itself to ensure the user agent finds a new version for each update. + headers = [('Cache-Control', 'no-cache, must-revalidate'), + ('Pragma', 'no-cache')] + + # Set a normal mimetype. + content_type = 'application/javascript' + + headers.append(('Content-Type', content_type)) + # Return a different script for each access. Use .time() and .clock() for + # best time resolution across different platforms. + return headers, '// %s %s' % (time.time(), time.clock()) + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-worker.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-worker.py new file mode 100644 index 00000000000..bc9b32ad3e6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-worker.py @@ -0,0 +1,46 @@ +import time + +def main(request, response): + # Set mode to 'init' for initial fetch. + mode = 'init' + if 'mode' in request.cookies: + mode = request.cookies['mode'].value + + # no-cache itself to ensure the user agent finds a new version for each update. + headers = [('Cache-Control', 'no-cache, must-revalidate'), + ('Pragma', 'no-cache')] + + content_type = '' + extra_body = '' + + if mode == 'init': + # Set a normal mimetype. + # Set cookie value to 'normal' so the next fetch will work in 'normal' mode. + content_type = 'application/javascript' + response.set_cookie('mode', 'normal') + elif mode == 'normal': + # Set a normal mimetype. + # Set cookie value to 'error' so the next fetch will work in 'error' mode. + content_type = 'application/javascript' + response.set_cookie('mode', 'error'); + elif mode == 'error': + # Set a disallowed mimetype. + # Set cookie value to 'syntax-error' so the next fetch will work in 'syntax-error' mode. + content_type = 'text/html' + response.set_cookie('mode', 'syntax-error'); + elif mode == 'syntax-error': + # Set cookie value to 'throw-install' so the next fetch will work in 'throw-install' mode. + content_type = 'application/javascript' + response.set_cookie('mode', 'throw-install'); + extra_body = 'badsyntax(isbad;' + elif mode == 'throw-install': + # Unset and delete cookie to clean up the test setting. + content_type = 'application/javascript' + response.delete_cookie('mode') + extra_body = "addEventListener('install', function(e) { throw new Error('boom'); });" + + headers.append(('Content-Type', content_type)) + # Return a different script for each access. Use .time() and .clock() for + # best time resolution across different platforms. + return headers, '/* %s %s */ %s' % (time.time(), time.clock(), extra_body) + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update/update-after-oneday.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update/update-after-oneday.https.html new file mode 100644 index 00000000000..9d4c9827218 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update/update-after-oneday.https.html @@ -0,0 +1,8 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/wait-forever-in-install-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/wait-forever-in-install-worker.js new file mode 100644 index 00000000000..32349594cc3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/wait-forever-in-install-worker.js @@ -0,0 +1,3 @@ +self.addEventListener('install', function(event) { + event.waitUntil(new Promise(function() {})); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/websocket.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/websocket.js new file mode 100644 index 00000000000..fc6abd283a0 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/websocket.js @@ -0,0 +1,7 @@ +self.urls = []; +self.addEventListener('fetch', function(event) { + self.urls.push(event.request.url); + }); +self.addEventListener('message', function(event) { + event.data.port.postMessage({urls: self.urls}); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/worker-interception-iframe.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/worker-interception-iframe.https.html new file mode 100644 index 00000000000..12a461ea5db --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/worker-interception-iframe.https.html @@ -0,0 +1,39 @@ + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/worker-load-interceptor.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/worker-load-interceptor.js new file mode 100644 index 00000000000..960c6328ce5 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/worker-load-interceptor.js @@ -0,0 +1,13 @@ +importScripts('get-host-info.sub.js'); + +var response_text = "This load was successfully intercepted."; +var response_script = "postMessage(\"This load was successfully intercepted.\");"; + +self.onfetch = function(event) { + var url = event.request.url; + if (url.indexOf("synthesized-response.txt") != -1) { + event.respondWith(new Response(response_text)); + } else if (url.indexOf("synthesized-response.js") != -1) { + event.respondWith(new Response(response_script)); + } +}; diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/worker-testharness.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/worker-testharness.js new file mode 100644 index 00000000000..fdf5868e33e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/worker-testharness.js @@ -0,0 +1,49 @@ +/* + * worker-test-harness should be considered a temporary polyfill around + * testharness.js for supporting Service Worker based tests. It should not be + * necessary once the test harness is able to drive worker based tests natively. + * See https://github.com/w3c/testharness.js/pull/82 for status of effort to + * update upstream testharness.js. Once the upstreaming is complete, tests that + * reference worker-test-harness should be updated to directly import + * testharness.js. + */ + +importScripts('/resources/testharness.js'); + +(function() { + var next_cache_index = 1; + + // Returns a promise that resolves to a newly created Cache object. The + // returned Cache will be destroyed when |test| completes. + function create_temporary_cache(test) { + var uniquifier = String(++next_cache_index); + var cache_name = self.location.pathname + '/' + uniquifier; + + test.add_cleanup(function() { + self.caches.delete(cache_name); + }); + + return self.caches.delete(cache_name) + .then(function() { + return self.caches.open(cache_name); + }); + } + + self.create_temporary_cache = create_temporary_cache; +})(); + +// Runs |test_function| with a temporary unique Cache passed in as the only +// argument. The function is run as a part of Promise chain owned by +// promise_test(). As such, it is expected to behave in a manner identical (with +// the exception of the argument) to a function passed into promise_test(). +// +// E.g.: +// cache_test(function(cache) { +// // Do something with |cache|, which is a Cache object. +// }, "Some Cache test"); +function cache_test(test_function, description) { + promise_test(function(test) { + return create_temporary_cache(test) + .then(test_function); + }, description); +} diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/xhr.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/xhr.js new file mode 100644 index 00000000000..387c4a48ed5 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/xhr.js @@ -0,0 +1,6 @@ +self.addEventListener('activate', function(event) { + event.waitUntil(clients.claim()); + }); +self.addEventListener('message', function(event) { + event.data.port.postMessage({xhr: !!("XMLHttpRequest" in self)}); + }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/service-worker-csp-connect.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/service-worker-csp-connect.https.html new file mode 100644 index 00000000000..226f4a40e4e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/service-worker-csp-connect.https.html @@ -0,0 +1,10 @@ + +Service Worker: CSP connect directive for ServiceWorker script + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/service-worker-csp-default.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/service-worker-csp-default.https.html new file mode 100644 index 00000000000..1d4e7624d86 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/service-worker-csp-default.https.html @@ -0,0 +1,10 @@ + +Service Worker: CSP default directive for ServiceWorker script + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/service-worker-csp-script.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/service-worker-csp-script.https.html new file mode 100644 index 00000000000..14c2eb72bdc --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/service-worker-csp-script.https.html @@ -0,0 +1,10 @@ + +Service Worker: CSP script directive for ServiceWorker script + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/serviceworkerobject-scripturl.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/serviceworkerobject-scripturl.https.html new file mode 100644 index 00000000000..95587a5a42d --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/serviceworkerobject-scripturl.https.html @@ -0,0 +1,26 @@ + +ServiceWorker object: scriptURL property + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/shared-worker-controlled.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/shared-worker-controlled.https.html new file mode 100644 index 00000000000..33d52e01199 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/shared-worker-controlled.https.html @@ -0,0 +1,77 @@ + +Service Worker: controlling a SharedWorker + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-installed.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-installed.https.html new file mode 100644 index 00000000000..42e4000b1f6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-installed.https.html @@ -0,0 +1,67 @@ + +Service Worker: Skip waiting installed worker + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https.html new file mode 100644 index 00000000000..5f84f0b8eda --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https.html @@ -0,0 +1,60 @@ + +Service Worker: Skip waiting using registration + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-without-client.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-without-client.https.html new file mode 100644 index 00000000000..38fca172604 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-without-client.https.html @@ -0,0 +1,13 @@ + +Service Worker: Skip waiting without client + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https.html new file mode 100644 index 00000000000..2535ffe09fc --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https.html @@ -0,0 +1,42 @@ + +Service Worker: Skip waiting without using registration + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting.https.html new file mode 100644 index 00000000000..7c1c41f3f75 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/skip-waiting.https.html @@ -0,0 +1,54 @@ + +Service Worker: Skip waiting + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/state.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/state.https.html new file mode 100644 index 00000000000..3810362e053 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/state.https.html @@ -0,0 +1,69 @@ + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/synced-state.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/synced-state.https.html new file mode 100644 index 00000000000..d842378be75 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/synced-state.https.html @@ -0,0 +1,64 @@ + +ServiceWorker: worker objects have synced state + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/uncontrolled-page.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/uncontrolled-page.https.html new file mode 100644 index 00000000000..a9523a54cdc --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/uncontrolled-page.https.html @@ -0,0 +1,39 @@ + +Service Worker: Registration + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/unregister-controller.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/unregister-controller.https.html new file mode 100644 index 00000000000..3bf4cff7200 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/unregister-controller.https.html @@ -0,0 +1,108 @@ + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/unregister-then-register-new-script.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/unregister-then-register-new-script.https.html new file mode 100644 index 00000000000..385430c2d8e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/unregister-then-register-new-script.https.html @@ -0,0 +1,159 @@ + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/unregister-then-register.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/unregister-then-register.https.html new file mode 100644 index 00000000000..d75904d158f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/unregister-then-register.https.html @@ -0,0 +1,129 @@ + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/unregister.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/unregister.https.html new file mode 100644 index 00000000000..492aecb21a8 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/unregister.https.html @@ -0,0 +1,40 @@ + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/update-after-navigation-fetch-event.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/update-after-navigation-fetch-event.https.html new file mode 100644 index 00000000000..04cd9960fc6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/update-after-navigation-fetch-event.https.html @@ -0,0 +1,34 @@ + +Service Worker: Update should be triggered after a navigation fetch event. + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/update-after-oneday.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/update-after-oneday.https.html new file mode 100644 index 00000000000..151a59ebc3f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/update-after-oneday.https.html @@ -0,0 +1,50 @@ + + +Service Worker: Functional events should trigger update if last update time is over 24 hours + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/update.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/update.https.html new file mode 100644 index 00000000000..8b41e52d8b8 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/update.https.html @@ -0,0 +1,124 @@ + +Service Worker: Registration update() + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/waiting.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/waiting.https.html new file mode 100644 index 00000000000..eff9c80a4f6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/waiting.https.html @@ -0,0 +1,44 @@ + +ServiceWorker: navigator.serviceWorker.waiting + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/websocket.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/websocket.https.html new file mode 100644 index 00000000000..3dfa6e51497 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/websocket.https.html @@ -0,0 +1,46 @@ + +Service Worker: WebSocket handshake channel is not intercepted + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/worker-interception.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/worker-interception.https.html new file mode 100644 index 00000000000..3ec66a54b6e --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/worker-interception.https.html @@ -0,0 +1,155 @@ + +Service Worker: intercepting Worker script loads + + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/xhr.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/xhr.https.html new file mode 100644 index 00000000000..776e61db16d --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/xhr.https.html @@ -0,0 +1,35 @@ + +Service Worker: XHR doesn't exist + + + + + diff --git a/tests/wpt/web-platform-tests/shadow-dom/resources/shadow-dom-utils.js b/tests/wpt/web-platform-tests/shadow-dom/resources/shadow-dom-utils.js new file mode 100644 index 00000000000..e00d4d14675 --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/resources/shadow-dom-utils.js @@ -0,0 +1,154 @@ +// Copyright 2012 Google Inc. All Rights Reserved. + +/* +Distributed under both the W3C Test Suite License [1] and the W3C +3-clause BSD License [2]. To contribute to a W3C Test Suite, see the +policies and contribution forms [3]. + +[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license +[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license +[3] http://www.w3.org/2004/10/27-testcases +*/ + +"use strict"; + +// custom element is also allowed. +var ATTACHSHADOW_SAFELISTED_ELEMENTS = [ + 'article', + 'aside', + 'blockquote', + 'body', + 'div', + 'footer', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'header', + 'nav', + 'p', + 'section', + 'span' +]; + +var HTML5_ELEMENT_NAMES = [ + 'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', + 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', + 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'command', + 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', + 'em', 'embed', + 'fieldset', 'figcaption', 'figure', 'footer', 'form', + 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', + 'html', + 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', + 'label', 'legend', 'li', 'link', + 'map', 'mark', 'menu', 'meta', 'meter', + 'nav', 'noscript', + 'object', 'ol', 'optgroup', 'option', 'output', + 'p', 'param', 'pre', 'progress', + 'q', + 'rp', 'rt', 'ruby', + 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', + 'strong', 'style', 'sub', + 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', + 'title', 'tr', 'track', + 'u', 'ul', + 'var', 'video', + 'wbr' +]; + +function unit(f) { + return function () { + var ctx = newContext(); + try { + f(ctx); + } finally { + cleanContext(ctx); + } + } +} + +function step_unit(f, ctx, t) { + return function () { + var done = false; + try { + f(); + done = true; + } finally { + if (done) { + t.done(); + } + cleanContext(ctx); + } + } +} + +function assert_nodelist_contents_equal_noorder(actual, expected, message) { + assert_equals(actual.length, expected.length, message); + var used = []; + for (var i = 0; i < expected.length; i++) { + used.push(false); + } + for (i = 0; i < expected.length; i++) { + var found = false; + for (var j = 0; j < actual.length; j++) { + if (used[j] == false && expected[i] == actual[j]) { + used[j] = true; + found = true; + break; + } + } + if (!found) { + assert_unreached(message + ". Fail reason: element not found: " + expected[i]); + } + } +} + +//Example taken from http://www.w3.org/TR/shadow-dom/#event-retargeting-example +function createTestMediaPlayer(d) { + d.body.innerHTML = '' + + '
' + + '' + + '
' + + '
' + + '
'; + + var playerShadowRoot = d.querySelector('#player-shadow-host').createShadowRoot(); + playerShadowRoot.innerHTML = '' + + '
' + + '' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
'; + + var timeLineShadowRoot = playerShadowRoot.querySelector('#timeline-shadow-host').createShadowRoot(); + timeLineShadowRoot.innerHTML = '
'; + + var volumeShadowRoot = playerShadowRoot.querySelector('#volume-shadow-host').createShadowRoot(); + volumeShadowRoot.innerHTML = '
'; + + return { + 'playerShadowRoot': playerShadowRoot, + 'timeLineShadowRoot': timeLineShadowRoot, + 'volumeShadowRoot': volumeShadowRoot + }; +} + +//FIXME This call of initKeyboardEvent works for WebKit-only. +//See https://bugs.webkit.org/show_bug.cgi?id=16735 +// and https://bugs.webkit.org/show_bug.cgi?id=13368. Add check for browser here +function fireKeyboardEvent(doc, element, key) { + var event = doc.createEvent('KeyboardEvent'); + event.initKeyboardEvent("keydown", true, true, doc.defaultView, key, 0, false, false, false, false); + element.dispatchEvent(event); +} diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html deleted file mode 100644 index bb43206b9d0..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - -Shadow DOM Test: A_10_02_01_01 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html deleted file mode 100644 index 1d52beca9ec..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - -Shadow DOM Test: A_10_02_01_05 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html index 3f3843f1947..7b5a08d3c33 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html @@ -16,14 +16,14 @@ policies and contribution forms [3]. - +
- - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html deleted file mode 100644 index 45ea0d5c71b..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - -Shadow DOM Test: Non-element node cannot be a shadow host - - - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html index 4645d55105a..d6077da9302 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html @@ -16,14 +16,14 @@ policies and contribution forms [3]. - +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html index 30223725832..3a2e69165d8 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html @@ -16,14 +16,15 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html deleted file mode 100644 index cbf22abac75..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - -Shadow DOM Test: A_10_02_02_03 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html index 8558f24fd37..e859a847b34 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html @@ -13,15 +13,16 @@ policies and contribution forms [3]. Shadow DOM Test - event path - + - + +
- - - - -
- - - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html index 492650e847b..d305d9b1894 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html @@ -17,18 +17,19 @@ policies and contribution forms [3]. - + +
- + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html index d97286f637d..ab3b314bcc3 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html @@ -16,25 +16,26 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html index bccc0539ffd..7ea514ec7c4 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html @@ -16,58 +16,59 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html index 47f98988ac9..5b6ced6d1dc 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html @@ -16,20 +16,21 @@ policies and contribution forms [3]. - + +
- + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html index f7f221ec265..55f4d94d9ae 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html @@ -16,21 +16,22 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html deleted file mode 100644 index fb411d98068..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - -Shadow DOM Test: ShadowRoot olderShadowRoot - - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html index e87ff419a65..892558af536 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html @@ -16,14 +16,14 @@ policies and contribution forms [3]. - +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html index d0c4451cd68..70971553b8a 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html @@ -16,33 +16,34 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html index 3b9fde76a37..46ab47faf17 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html @@ -16,7 +16,7 @@ policies and contribution forms [3]. - +
@@ -29,10 +29,10 @@ test(function () { d.body.appendChild(el); try { - el.elementFromPoint(1, 1); - assert_true(false, 'TypeMismatchError should be thrown'); + el.elementFromPoint(1, 1); + assert_true(false, 'TypeMismatchError should be thrown'); } catch(e) { - assert_true(e instanceof TypeError, 'Wrong error type'); + assert_true(e instanceof TypeError, 'Wrong error type'); } }, 'A_10_01_02_06_01_T01'); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html index 120f207f77d..4bf5afb250a 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html @@ -16,14 +16,14 @@ policies and contribution forms [3]. - +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html index b7b544735b7..129f316708f 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html @@ -16,25 +16,26 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-001.html deleted file mode 100644 index 2d53d51f539..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-001.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - -Shadow DOM Test: A_10_04_01 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-002.html deleted file mode 100644 index aa433babaa0..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-002.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - -Shadow DOM Test: A_10_04_02 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-003.html deleted file mode 100644 index 7ab035ece47..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-003.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - -Shadow DOM Test: A_10_04_03 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-005.html deleted file mode 100644 index 00d8354c4d4..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-005.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - -Shadow DOM Test: A_10_04_05 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-006.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-006.html deleted file mode 100644 index 54c6362a984..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-006.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - -Shadow DOM Test: A_10_04_06 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-001.html deleted file mode 100644 index 2f8167294ec..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-001.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - -Shadow DOM Test: A_10_05_01 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-002.html deleted file mode 100644 index 85f7f2b1b23..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-002.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - -Shadow DOM Test: A_10_05_02 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-004.html deleted file mode 100644 index 1ab2b7d2a9b..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-004.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - -Shadow DOM Test: A_10_05_04 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-001.html index 9e508c499b6..e10ef19b899 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-001.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -36,13 +37,13 @@ A_05_05_01_T01.step(unit(function (ctx) { //For #volume-slider-thumb relative target #volume-slider-thumb roots.volumeShadowRoot.querySelector('#volume-slider-thumb').addEventListener('click', - A_05_05_01_T01.step_func(function(event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb', - 'Point 1: Wrong target'); - assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider-thumb', - 'Point 1: Wrong currentTarget'); - }), false); + A_05_05_01_T01.step_func(function(event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb', + 'Point 1: Wrong target'); + assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider-thumb', + 'Point 1: Wrong currentTarget'); + }), false); var event = d.createEvent('HTMLEvents'); event.initEvent ('click', true, false); @@ -69,13 +70,13 @@ A_05_05_01_T02.step(unit(function (ctx) { //For #volume-shadow-root relative target #volume-slider-thumb roots.volumeShadowRoot.addEventListener('click', - A_05_05_01_T02.step_func(function(event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb', - 'Wrong target'); - assert_true(event.currentTarget == roots.volumeShadowRoot, - 'Wrong currentTarget'); - }), false); + A_05_05_01_T02.step_func(function(event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb', + 'Wrong target'); + assert_true(event.currentTarget == roots.volumeShadowRoot, + 'Wrong currentTarget'); + }), false); var event = d.createEvent('HTMLEvents'); event.initEvent ('click', true, false); @@ -102,19 +103,19 @@ A_05_05_01_T03.step(unit(function (ctx) { //For #volume-slider relative target #volume-shadow-host roots.playerShadowRoot.querySelector('#volume-slider').addEventListener('click', - A_05_05_01_T03.step_func(function(event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', - 'Wrong target'); - assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider', - 'Wrong currentTarget'); - }), false); + A_05_05_01_T03.step_func(function(event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', + 'Wrong target'); + assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider', + 'Wrong currentTarget'); + }), false); var event = d.createEvent('HTMLEvents'); event.initEvent ('click', true, false); roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event); - assert_true(invoked, 'Event listener was not invoked'); + assert_true(invoked, 'Event listener was not invoked'); A_05_05_01_T03.done(); })); @@ -136,21 +137,21 @@ A_05_05_01_T04.step(unit(function (ctx) { //For #volume-slider-container relative target #volume-shadow-host roots.playerShadowRoot.querySelector('#volume-slider-container').addEventListener('click', - A_05_05_01_T04.step_func(function(event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', - 'Wrong target'); - assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider-container', - 'Wrong currentTarget'); - }), false); + A_05_05_01_T04.step_func(function(event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', + 'Wrong target'); + assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider-container', + 'Wrong currentTarget'); + }), false); var event = d.createEvent('HTMLEvents'); event.initEvent ('click', true, false); roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event); - assert_true(invoked, 'Event listener was not invoked'); + assert_true(invoked, 'Event listener was not invoked'); - A_05_05_01_T04.done(); + A_05_05_01_T04.done(); })); @@ -169,21 +170,21 @@ A_05_05_01_T05.step(unit(function (ctx) { //For #controls relative target #volume-shadow-host roots.playerShadowRoot.querySelector('#controls').addEventListener('click', - A_05_05_01_T05.step_func(function(event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', - 'Wrong target'); - assert_equals(event.currentTarget.getAttribute('id'), 'controls', - 'Wrong currentTarget'); - }), false); + A_05_05_01_T05.step_func(function(event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', + 'Wrong target'); + assert_equals(event.currentTarget.getAttribute('id'), 'controls', + 'Wrong currentTarget'); + }), false); var event = d.createEvent('HTMLEvents'); event.initEvent ('click', true, false); roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event); - assert_true(invoked, 'Event listener was not invoked'); + assert_true(invoked, 'Event listener was not invoked'); - A_05_05_01_T05.done(); + A_05_05_01_T05.done(); })); @@ -202,21 +203,21 @@ A_05_05_01_T06.step(unit(function (ctx) { //For #player-shadow-host relative target #player-shadow-host d.querySelector('#player-shadow-host').addEventListener('click', - A_05_05_01_T06.step_func(function(event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'player-shadow-host', - 'Wrong target'); - assert_equals(event.currentTarget.getAttribute('id'), 'player-shadow-host', - 'Wrong currentTarget'); - }), false); + A_05_05_01_T06.step_func(function(event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'player-shadow-host', + 'Wrong target'); + assert_equals(event.currentTarget.getAttribute('id'), 'player-shadow-host', + 'Wrong currentTarget'); + }), false); var event = d.createEvent('HTMLEvents'); event.initEvent ('click', true, false); roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event); - assert_true(invoked, 'Event listener was not invoked'); + assert_true(invoked, 'Event listener was not invoked'); - A_05_05_01_T06.done(); + A_05_05_01_T06.done(); })); @@ -236,21 +237,21 @@ A_05_05_01_T07.step(unit(function (ctx) { //For #player relative target #player-shadow-host d.querySelector('#player').addEventListener('click', - A_05_05_01_T07.step_func(function(event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'player-shadow-host', - 'Wrong target'); - assert_equals(event.currentTarget.getAttribute('id'), 'player', - 'Wrong currentTarget'); - }), false); + A_05_05_01_T07.step_func(function(event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'player-shadow-host', + 'Wrong target'); + assert_equals(event.currentTarget.getAttribute('id'), 'player', + 'Wrong currentTarget'); + }), false); var event = d.createEvent('HTMLEvents'); event.initEvent ('click', true, false); roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event); - assert_true(invoked, 'Event listener was not invoked'); + assert_true(invoked, 'Event listener was not invoked'); - A_05_05_01_T07.done(); + A_05_05_01_T07.done(); })); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-002.html index 2c8fbab4ce4..8ea42cad733 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-002.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -36,11 +37,11 @@ A_05_05_02_T01.step(unit(function (ctx) { //For #volume-shadow-root adjusted related target #volume-shadow-root roots.volumeShadowRoot.addEventListener('mouseover', - A_05_05_02_T01.step_func(function(event) { - invoked = true; - assert_true(event.relatedTarget === roots.volumeShadowRoot, - 'Wrong relatedTarget'); - }), false); + A_05_05_02_T01.step_func(function(event) { + invoked = true; + assert_true(event.relatedTarget === roots.volumeShadowRoot, + 'Wrong relatedTarget'); + }), false); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-003.html index 6d217bb6db7..b0a5a30af5b 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-003.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-003.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -44,20 +45,20 @@ A_05_05_03_T01.step(unit(function (ctx) { s.appendChild(input2); input1.addEventListener('focusin', A_05_05_03_T01.step_func(function(event) { - assert_equals(event.deepPath.length, 7); - assert_equals(event.deepPath[0].id, 'input1'); - assert_equals(event.deepPath[1].id, 'shadow'); - assert_equals(event.deepPath[2].id, 'host'); - assert_equals(event.deepPath[3].tagName, 'BODY'); - assert_equals(event.deepPath[4].tagName, 'HTML'); - assert_equals(event.deepPath[5], d); - assert_equals(event.deepPath[6], ctx.iframes[0].contentWindow); + assert_equals(event.deepPath().length, 7); + assert_equals(event.deepPath()[0].id, 'input1'); + assert_equals(event.deepPath()[1].id, 'shadow'); + assert_equals(event.deepPath()[2].id, 'host'); + assert_equals(event.deepPath()[3].tagName, 'BODY'); + assert_equals(event.deepPath()[4].tagName, 'HTML'); + assert_equals(event.deepPath()[5], d); + assert_equals(event.deepPath()[6], ctx.iframes[0].contentWindow); }), false); input2.addEventListener('focusin', A_05_05_03_T01.step_func(function(event) { - assert_equals(event.deepPath.length, 2); - assert_equals(event.deepPath[0].id, 'input2'); - assert_equals(event.deepPath[1].id, 'shadow'); + assert_equals(event.deepPath().length, 2); + assert_equals(event.deepPath()[0].id, 'input2'); + assert_equals(event.deepPath()[1].id, 'shadow'); A_05_05_03_T01.done(); }), false); @@ -69,7 +70,7 @@ A_05_05_03_T01.step(unit(function (ctx) { // In this case, original relatedTarget is #input1, and original target // is #input2. // It should be viewed outside the shadow as "target == relatedTarget" - // after event retargeting, therefore, event.deepPath above the shadow + // after event retargeting, therefore, event.deepPath() above the shadow // host will be trimmed. // Expected event path for #input2: // , #shadow-root diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-001.html index b0e0199dd1a..c40b5bfb04a 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-001.html @@ -16,7 +16,7 @@ policies and contribution forms [3]. - +
@@ -31,23 +31,23 @@ A_05_01_01_T1.step(function () { iframe.onload = A_05_01_01_T1.step_func(function () { try { - var d = iframe.contentDocument; - var div = d.createElement('div'); - d.body.appendChild(div); + var d = iframe.contentDocument; + var div = d.createElement('div'); + d.body.appendChild(div); - var s = div.createShadowRoot(); + var s = div.createShadowRoot(); - var div2 = d.createElement('div'); - s.appendChild(div2); + var div2 = d.createElement('div'); + s.appendChild(div2); - var inp = d.createElement('input'); - inp.setAttribute('type', 'text'); - inp.setAttribute('id', 'inpid'); - div2.appendChild(inp); + var inp = d.createElement('input'); + inp.setAttribute('type', 'text'); + inp.setAttribute('id', 'inpid'); + div2.appendChild(inp); - div2.addEventListener('click', A_05_01_01_T1.step_func(function (event) { + div2.addEventListener('click', A_05_01_01_T1.step_func(function (event) { assert_equals(event.target.tagName, 'INPUT', 'Information about target of the event that ' + - 'doesn\'t cross the shadow boundaries should not be adjusted'); + 'doesn\'t cross the shadow boundaries should not be adjusted'); }), false); var event = d.createEvent('HTMLEvents'); @@ -72,24 +72,24 @@ A_05_01_01_T2.step(function () { iframe.onload = A_05_01_01_T2.step_func(function () { try { - var d = iframe.contentDocument; + var d = iframe.contentDocument; - var div = d.createElement('div'); - d.body.appendChild(div); + var div = d.createElement('div'); + d.body.appendChild(div); - var s = div.createShadowRoot(); + var s = div.createShadowRoot(); - var div2 = d.createElement('div'); - s.appendChild(div2); + var div2 = d.createElement('div'); + s.appendChild(div2); - var inp = d.createElement('input'); - inp.setAttribute('type', 'text'); - inp.setAttribute('id', 'inpid'); - div2.appendChild(inp); + var inp = d.createElement('input'); + inp.setAttribute('type', 'text'); + inp.setAttribute('id', 'inpid'); + div2.appendChild(inp); - div.addEventListener('click', A_05_01_01_T2.step_func(function (event) { + div.addEventListener('click', A_05_01_01_T2.step_func(function (event) { assert_equals(event.target.tagName, 'DIV', 'Information about event target crossing ' + - 'the shadow boundaries should be adjusted'); + 'the shadow boundaries should be adjusted'); }), false); var event = d.createEvent('HTMLEvents'); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-002.html deleted file mode 100644 index 5550b85ad98..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-002.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -Shadow DOM Test: A_05_01_02 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-003.html index 2c469fdcc2f..a79b9cd3137 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-003.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-003.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -24,16 +25,16 @@ policies and contribution forms [3]. var A_05_01_03_T01 = async_test('A_05_01_03_T01'); A_05_01_03_T01.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); d.body.innerHTML = '' + - '
' + - '
' + - '1' + - '2' + - '3' + - '
' + - '
'; + '
' + + '
' + + '1' + + '2' + + '3' + + '
' + + '
'; var ul = d.querySelector('#shadow-root'); var s = ul.createShadowRoot(); @@ -43,17 +44,17 @@ A_05_01_03_T01.step(unit(function (ctx) { div.innerHTML = 'Fallback item'; s.appendChild(div); - d.body.addEventListener('click', A_05_01_03_T01.step_func(function (event) { + d.body.addEventListener('click', A_05_01_03_T01.step_func(function (event) { assert_equals(event.target.getAttribute('id'), 'shadow-root', 'Information about ' + - 'event target crossing the shadow boundaries should be adjusted for the fallback ' + - 'content'); + 'event target crossing the shadow boundaries should be adjusted for the fallback ' + + 'content'); }), false); var event = d.createEvent('HTMLEvents'); event.initEvent ("click", true, false); s.querySelector('#flbk').dispatchEvent(event); - A_05_01_03_T01.done(); + A_05_01_03_T01.done(); })); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-004.html index 7db6fa116fa..c91e25b7022 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-004.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-004.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -24,18 +25,18 @@ policies and contribution forms [3]. var A_05_01_04_T01 = async_test('A_05_01_04_T01'); A_05_01_04_T01.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example //For #volume-slider-thumb relative target is #volume-slider-thumb roots.volumeShadowRoot.querySelector('#volume-slider-thumb').addEventListener('click', - A_05_01_04_T01.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb', - 'Wrong related target'); + A_05_01_04_T01.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -44,7 +45,7 @@ A_05_01_04_T01.step(unit(function (ctx) { assert_true(invoked, 'Event listener was not invoked'); - A_05_01_04_T01.done(); + A_05_01_04_T01.done(); })); @@ -52,8 +53,8 @@ A_05_01_04_T01.step(unit(function (ctx) { var A_05_01_04_T02 = async_test('A_05_01_04_T02'); A_05_01_04_T02.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -61,10 +62,10 @@ A_05_01_04_T02.step(unit(function (ctx) { //For #volume-shadow-host relative target is #volume-shadow-host roots.playerShadowRoot.querySelector('#volume-shadow-host').addEventListener('click', - A_05_01_04_T02.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', - 'Wrong related target'); + A_05_01_04_T02.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -82,8 +83,8 @@ A_05_01_04_T02.step(unit(function (ctx) { var A_05_01_04_T03 = async_test('A_05_01_04_T03'); A_05_01_04_T03.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -91,10 +92,10 @@ A_05_01_04_T03.step(unit(function (ctx) { //For #volume-slider relative target is #volume-shadow-host roots.playerShadowRoot.querySelector('#volume-slider').addEventListener('click', - A_05_01_04_T03.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', - 'Wrong related target'); + A_05_01_04_T03.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -110,8 +111,8 @@ A_05_01_04_T03.step(unit(function (ctx) { var A_05_01_04_T04 = async_test('A_05_01_04_T04'); A_05_01_04_T04.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -119,10 +120,10 @@ A_05_01_04_T04.step(unit(function (ctx) { //For #volume-slider-container relative target is #volume-shadow-host roots.playerShadowRoot.querySelector('#volume-slider-container').addEventListener('click', - A_05_01_04_T04.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', - 'Wrong related target'); + A_05_01_04_T04.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -138,8 +139,8 @@ A_05_01_04_T04.step(unit(function (ctx) { var A_05_01_04_T05 = async_test('A_05_01_04_T05'); A_05_01_04_T05.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -147,10 +148,10 @@ A_05_01_04_T05.step(unit(function (ctx) { //For #controls relative target is #volume-shadow-host roots.playerShadowRoot.querySelector('#controls').addEventListener('click', - A_05_01_04_T05.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', - 'Wrong related target'); + A_05_01_04_T05.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -166,8 +167,8 @@ A_05_01_04_T05.step(unit(function (ctx) { var A_05_01_04_T06 = async_test('A_05_01_04_T06'); A_05_01_04_T06.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -175,10 +176,10 @@ A_05_01_04_T06.step(unit(function (ctx) { //For #player-shadow-host relative target is #player-shadow-host roots.playerShadowRoot.addEventListener('click', - A_05_01_04_T06.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', - 'Wrong related target'); + A_05_01_04_T06.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-shadow-host', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -195,8 +196,8 @@ A_05_01_04_T06.step(unit(function (ctx) { var A_05_01_04_T07 = async_test('A_05_01_04_T07'); A_05_01_04_T07.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -204,10 +205,10 @@ A_05_01_04_T07.step(unit(function (ctx) { //For #player relative target is #player-shadow-host d.querySelector('#player').addEventListener('click', - A_05_01_04_T07.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'player-shadow-host', - 'Wrong related target'); + A_05_01_04_T07.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'player-shadow-host', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -223,8 +224,8 @@ A_05_01_04_T07.step(unit(function (ctx) { var A_05_01_04_T08 = async_test('A_05_01_04_T08'); A_05_01_04_T08.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -232,10 +233,10 @@ A_05_01_04_T08.step(unit(function (ctx) { //For #volume-slider relative target is #volume-slider roots.playerShadowRoot.querySelector('#volume-slider').addEventListener('click', - A_05_01_04_T08.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-slider', - 'Wrong related target'); + A_05_01_04_T08.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-slider', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -251,8 +252,8 @@ A_05_01_04_T08.step(unit(function (ctx) { var A_05_01_04_T09 = async_test('A_05_01_04_T09'); A_05_01_04_T09.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -260,10 +261,10 @@ A_05_01_04_T09.step(unit(function (ctx) { //For #volume-slider-container relative target is #volume-slider roots.playerShadowRoot.querySelector('#volume-slider-container').addEventListener('click', - A_05_01_04_T09.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-slider', - 'Wrong related target'); + A_05_01_04_T09.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-slider', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -279,8 +280,8 @@ A_05_01_04_T09.step(unit(function (ctx) { var A_05_01_04_T10 = async_test('A_05_01_04_T10'); A_05_01_04_T10.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -288,10 +289,10 @@ A_05_01_04_T10.step(unit(function (ctx) { //For #controls relative target is #volume-slider roots.playerShadowRoot.querySelector('#controls').addEventListener('click', - A_05_01_04_T10.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-slider', - 'Wrong related target'); + A_05_01_04_T10.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-slider', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -307,8 +308,8 @@ A_05_01_04_T10.step(unit(function (ctx) { var A_05_01_04_T11 = async_test('A_05_01_04_T11'); A_05_01_04_T11.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -316,10 +317,10 @@ A_05_01_04_T11.step(unit(function (ctx) { //For #player-shadow-root relative target is #volume-slider roots.playerShadowRoot.addEventListener('click', - A_05_01_04_T11.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-slider', - 'Wrong related target'); + A_05_01_04_T11.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-slider', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); @@ -336,8 +337,8 @@ A_05_01_04_T11.step(unit(function (ctx) { var A_05_01_04_T12 = async_test('A_05_01_04_T12'); A_05_01_04_T12.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); - var invoked = false; + var d = newRenderedHTMLDocument(ctx); + var invoked = false; roots = createTestMediaPlayer(d); //expected result of what relative target should be see @@ -345,10 +346,10 @@ A_05_01_04_T12.step(unit(function (ctx) { //For #player relative target is #player-shadow-host d.querySelector('#player').addEventListener('click', - A_05_01_04_T12.step_func(function (event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'player-shadow-host', - 'Wrong related target'); + A_05_01_04_T12.step_func(function (event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'player-shadow-host', + 'Wrong related target'); }), false); var event = d.createEvent('HTMLEvents'); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-001.html index 45b358e7763..cb7efec60f1 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-001.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-002.html index a1c2106ffd5..cea27ce7dca 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-002.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-003.html index 7f420ae46d2..edf525c5349 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-003.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-003.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-004.html index b12de533d66..7f552b28efb 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-004.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-004.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-005.html index 4f3bfe1af22..883165f0bcf 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-005.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-005.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-006.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-006.html index e00c122b4ff..f51f2c4e4e0 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-006.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-006.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-007.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-007.html index ad630d80997..49d3577a4e0 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-007.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-007.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-008.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-008.html index 375dab6d2e1..430d8916fc1 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-008.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-008.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-009.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-009.html index 86a17578a0f..2d5bebbeb54 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-009.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-009.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-001.html index 254c34e358e..506315fd92e 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-001.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -50,11 +51,11 @@ A_05_03_01_T01.step(unit(function (ctx) { d.body.appendChild(inp2); s.addEventListener('DOMFocusOut', A_05_03_01_T01.step_func(function(event) { - assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: Wrong target'); + assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: Wrong target'); }), false); d.body.addEventListener('DOMFocusOut', A_05_03_01_T01.step_func(function(event) { - assert_equals(event.target.getAttribute('id'), 'host', 'Inside shadow tree: Wrong target'); + assert_equals(event.target.getAttribute('id'), 'host', 'Inside shadow tree: Wrong target'); }), false); inp1.focus(); @@ -92,11 +93,11 @@ A_05_03_01_T02.step(unit(function (ctx) { inp2.focus(); s.addEventListener('DOMFocusIn', A_05_03_01_T02.step_func(function(event) { - assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target'); + assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target'); }), false); d.body.addEventListener('DOMFocusIn', A_05_03_01_T02.step_func(function(event) { - assert_equals(event.target.getAttribute('id'), 'host', 'Outside shadow tree: Wrong target'); + assert_equals(event.target.getAttribute('id'), 'host', 'Outside shadow tree: Wrong target'); }), false); inp1.focus(); @@ -135,7 +136,7 @@ A_05_03_01_T03.step(unit(function (ctx) { inp1.focus(); d.body.addEventListener('DOMFocusIn', A_05_03_01_T03.step_func(function(event) { - assert_true(false, 'Event should be stopped at Shadow boundary'); + assert_true(false, 'Event should be stopped at Shadow boundary'); }), false); inp2.focus(); @@ -152,35 +153,35 @@ var A_05_03_01_T04 = async_test('A_05_03_01_T04'); A_05_03_01_T04.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var host = d.createElement('div'); - host.setAttribute('style', 'height:50%; width:100%'); - host.setAttribute('id', 'host'); - d.body.appendChild(host); + var host = d.createElement('div'); + host.setAttribute('style', 'height:50%; width:100%'); + host.setAttribute('id', 'host'); + d.body.appendChild(host); - //Shadow root to play with - var s = host.createShadowRoot(); + //Shadow root to play with + var s = host.createShadowRoot(); - var inp1 = d.createElement('input'); - inp1.setAttribute('id', 'inp1'); - inp1.setAttribute('type', 'checkbox'); - s.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('id', 'inp1'); + inp1.setAttribute('type', 'checkbox'); + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('id', 'inp2'); - inp2.setAttribute('type', 'checkbox'); - s.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('id', 'inp2'); + inp2.setAttribute('type', 'checkbox'); + s.appendChild(inp2); - inp1.focus(); + inp1.focus(); - d.body.addEventListener('DOMFocusOut', A_05_03_01_T04.step_func(function(event) { - assert_true(false, 'Event should be stopped at Shadow boundary'); - }), false); + d.body.addEventListener('DOMFocusOut', A_05_03_01_T04.step_func(function(event) { + assert_true(false, 'Event should be stopped at Shadow boundary'); + }), false); - inp2.focus(); + inp2.focus(); - A_05_03_01_T04.done(); + A_05_03_01_T04.done(); })); @@ -192,63 +193,63 @@ var A_05_03_01_T05 = async_test('A_05_03_01_T05'); A_05_03_01_T05.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var host = d.createElement('div'); - host.setAttribute('id', 'host'); - d.body.appendChild(host); + var host = d.createElement('div'); + host.setAttribute('id', 'host'); + d.body.appendChild(host); - var inp1 = d.createElement('input'); - inp1.setAttribute('id', 'inp1'); - inp1.setAttribute('type', 'checkbox'); - inp1.setAttribute('class', 'clazz1'); - host.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('id', 'inp1'); + inp1.setAttribute('type', 'checkbox'); + inp1.setAttribute('class', 'clazz1'); + host.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('id', 'inp2'); - inp2.setAttribute('type', 'checkbox'); - inp2.setAttribute('class', 'clazz2'); - host.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('id', 'inp2'); + inp2.setAttribute('type', 'checkbox'); + inp2.setAttribute('class', 'clazz2'); + host.appendChild(inp2); - var inp3 = d.createElement('input'); - inp3.setAttribute('id', 'inp3'); - inp3.setAttribute('type', 'checkbox'); - inp3.setAttribute('class', 'clazz1'); - host.appendChild(inp3); + var inp3 = d.createElement('input'); + inp3.setAttribute('id', 'inp3'); + inp3.setAttribute('type', 'checkbox'); + inp3.setAttribute('class', 'clazz1'); + host.appendChild(inp3); - //Shadow root to play with - var s = host.createShadowRoot(); + //Shadow root to play with + var s = host.createShadowRoot(); - var shadowDiv = document.createElement('div'); - shadowDiv.innerHTML = ''; - s.appendChild(shadowDiv); + var shadowDiv = document.createElement('div'); + shadowDiv.innerHTML = ''; + s.appendChild(shadowDiv); - //element outside the shadow tree - var inp4 = d.createElement('input'); - inp4.setAttribute('id', 'inp4'); - inp4.setAttribute('type', 'checkbox'); - inp4.setAttribute('class', 'clazz1'); - d.body.appendChild(inp4); + //element outside the shadow tree + var inp4 = d.createElement('input'); + inp4.setAttribute('id', 'inp4'); + inp4.setAttribute('type', 'checkbox'); + inp4.setAttribute('class', 'clazz1'); + d.body.appendChild(inp4); - inp1.focus(); + inp1.focus(); - s.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) { - assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' + - 'Event for nodes, distributed ' + - 'agains insertion points shouldn\'t be retargeted'); - }), false); + s.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) { + assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' + + 'Event for nodes, distributed ' + + 'agains insertion points shouldn\'t be retargeted'); + }), false); - d.body.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) { - assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' + - 'Event for nodes, distributed ' + - 'agains insertion points shouldn\'t be retargeted'); - }), false); + d.body.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) { + assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' + + 'Event for nodes, distributed ' + + 'agains insertion points shouldn\'t be retargeted'); + }), false); - inp4.focus(); + inp4.focus(); - A_05_03_01_T05.done(); + A_05_03_01_T05.done(); })); @@ -258,63 +259,63 @@ var A_05_03_01_T06 = async_test('A_05_03_01_T06'); A_05_03_01_T06.step(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var host = d.createElement('div'); - host.setAttribute('id', 'host'); - d.body.appendChild(host); + var host = d.createElement('div'); + host.setAttribute('id', 'host'); + d.body.appendChild(host); - var inp1 = d.createElement('input'); - inp1.setAttribute('id', 'inp1'); - inp1.setAttribute('type', 'checkbox'); - inp1.setAttribute('class', 'clazz1'); - host.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('id', 'inp1'); + inp1.setAttribute('type', 'checkbox'); + inp1.setAttribute('class', 'clazz1'); + host.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('id', 'inp2'); - inp2.setAttribute('type', 'checkbox'); - inp2.setAttribute('class', 'clazz2'); - host.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('id', 'inp2'); + inp2.setAttribute('type', 'checkbox'); + inp2.setAttribute('class', 'clazz2'); + host.appendChild(inp2); - var inp3 = d.createElement('input'); - inp3.setAttribute('id', 'inp3'); - inp3.setAttribute('type', 'checkbox'); - inp3.setAttribute('class', 'clazz1'); - host.appendChild(inp3); + var inp3 = d.createElement('input'); + inp3.setAttribute('id', 'inp3'); + inp3.setAttribute('type', 'checkbox'); + inp3.setAttribute('class', 'clazz1'); + host.appendChild(inp3); - //Shadow root to play with - var s = host.createShadowRoot(); + //Shadow root to play with + var s = host.createShadowRoot(); - var shadowDiv = document.createElement('div'); - shadowDiv.innerHTML = ''; - s.appendChild(shadowDiv); + var shadowDiv = document.createElement('div'); + shadowDiv.innerHTML = ''; + s.appendChild(shadowDiv); - //element outside the shadow tree - var inp4 = d.createElement('input'); - inp4.setAttribute('id', 'inp4'); - inp4.setAttribute('type', 'checkbox'); - inp4.setAttribute('class', 'clazz1'); - d.body.appendChild(inp4); + //element outside the shadow tree + var inp4 = d.createElement('input'); + inp4.setAttribute('id', 'inp4'); + inp4.setAttribute('type', 'checkbox'); + inp4.setAttribute('class', 'clazz1'); + d.body.appendChild(inp4); - inp4.focus(); + inp4.focus(); - s.addEventListener('DOMFocusIn', A_05_03_01_T06.step_func(function(event) { - assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' + - 'Event for nodes, distributed ' + - 'agains insertion points shouldn\'t be retargeted'); - }), false); + s.addEventListener('DOMFocusIn', A_05_03_01_T06.step_func(function(event) { + assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' + + 'Event for nodes, distributed ' + + 'agains insertion points shouldn\'t be retargeted'); + }), false); - d.body.addEventListener('DOMFocusIn', A_05_03_01_T05.step_func(function(event) { - assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' + - 'Event for nodes, distributed ' + - 'agains insertion points shouldn\'t be retargeted'); - }), false); + d.body.addEventListener('DOMFocusIn', A_05_03_01_T05.step_func(function(event) { + assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' + + 'Event for nodes, distributed ' + + 'agains insertion points shouldn\'t be retargeted'); + }), false); - inp1.focus(); + inp1.focus(); - A_05_03_01_T06.done(); + A_05_03_01_T06.done(); })); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html index 0129e9ce87c..0e22dd6fbd8 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -40,11 +41,11 @@ A_05_03_02_T01.step(unit(function (ctx) { //For #volume-slider relative target is #volume-slider roots.playerShadowRoot.querySelector('.volume-slider').addEventListener('blur', - A_05_03_02_T01.step_func(function(event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-slider', - 'Wrong target'); - }), false); + A_05_03_02_T01.step_func(function(event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-slider', + 'Wrong target'); + }), false); // move focus out of shadow tree. blur should be fired d.querySelector('#outside-control').focus(); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html index 90191c46755..19e4b9967ce 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -40,11 +41,11 @@ A_05_03_03_T01.step(unit(function (ctx) { //For #volume-slider relative target is #volume-slider roots.playerShadowRoot.querySelector('.volume-slider').addEventListener('focus', - A_05_03_03_T01.step_func(function(event) { - invoked = true; - assert_equals(event.target.getAttribute('id'), 'volume-slider', - 'Wrong target'); - }), false); + A_05_03_03_T01.step_func(function(event) { + invoked = true; + assert_equals(event.target.getAttribute('id'), 'volume-slider', + 'Wrong target'); + }), false); roots.playerShadowRoot.querySelector('.volume-slider').focus(); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-001.html index 8a31bea609e..a791b4ce046 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-001.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -46,11 +47,11 @@ A_05_02_01_T01.step(unit(function (ctx) { s.appendChild(div2); s.addEventListener('mouseover', A_05_02_01_T01.step_func(function(event) { - assert_equals(event.relatedTarget.getAttribute('id'), 'div1', 'Wrong relatedTarget'); + assert_equals(event.relatedTarget.getAttribute('id'), 'div1', 'Wrong relatedTarget'); }), false); d.body.addEventListener('mouseover', A_05_02_01_T01.step_func(function(event) { - assert_true(false, 'Event must be stopped at Shadow boundary'); + assert_true(false, 'Event must be stopped at Shadow boundary'); }), false); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-002.html index 2c7c0cdd16b..317537d2f38 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-002.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -46,7 +47,7 @@ A_05_02_02_T01.step(unit(function (ctx) { d.body.appendChild(div2); d.body.addEventListener('mouseover', A_05_02_02_T01.step_func(function(event) { - assert_equals(event.relatedTarget.getAttribute('id'), 'host', 'Wrong related target'); + assert_equals(event.relatedTarget.getAttribute('id'), 'host', 'Wrong related target'); }), false); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-003.html index e7539f7a77f..377550239b5 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-003.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-003.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -46,7 +47,7 @@ A_05_02_03_T01.step(unit(function (ctx) { s.appendChild(div2); s.addEventListener('mouseover', A_05_02_03_T01.step_func(function(event) { - assert_true(false, 'Event listeners shouldn\'t be invoked if target and relatedTarget are the same'); + assert_true(false, 'Event listeners shouldn\'t be invoked if target and relatedTarget are the same'); }), false); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/test-001.html index 552cfa6643c..cea9294c289 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/events/test-001.html @@ -16,7 +16,7 @@ policies and contribution forms [3]. - +
@@ -31,34 +31,34 @@ A_05_00_01_T1.step(function () { iframe.onload = A_05_00_01_T1.step_func(function () { try { - var d = iframe.contentDocument; + var d = iframe.contentDocument; - var div = d.createElement('div'); - d.body.appendChild(div); + var div = d.createElement('div'); + d.body.appendChild(div); - var s = div.createShadowRoot(); + var s = div.createShadowRoot(); - var div2 = d.createElement('div'); - s.appendChild(div2); + var div2 = d.createElement('div'); + s.appendChild(div2); - var inp = d.createElement('input'); - inp.setAttribute('type', 'text'); - inp.setAttribute('id', 'inpid'); - div2.appendChild(inp); + var inp = d.createElement('input'); + inp.setAttribute('type', 'text'); + inp.setAttribute('id', 'inpid'); + div2.appendChild(inp); - div2.addEventListener('DOMAttrModified', A_05_00_01_T1.step_func(function (event) { + div2.addEventListener('DOMAttrModified', A_05_00_01_T1.step_func(function (event) { assert_true(false, 'The mutation event types must never be dispatched in a shadow DOM subtree'); }), false); - /* - var attr = inp.getAttributeNode ("value"); + /* + var attr = inp.getAttributeNode ("value"); var event = d.createEvent('MutationEvent'); event.initMutationEvent ("DOMAttrModified", true, true, attr, null, 'new value', "value", MutationEvent.MODIFICATION); inp.dispatchEvent(event); - */ - inp.value = 'new value'; - inp.setAttribute ("newAttr" , "firstValue"); - inp.setAttribute ("newAttr" , "secondValue"); - inp.removeAttribute ("newAttr"); + */ + inp.value = 'new value'; + inp.setAttribute ("newAttr" , "firstValue"); + inp.setAttribute ("newAttr" , "secondValue"); + inp.removeAttribute ("newAttr"); } finally { iframe.parentNode.removeChild(iframe); } diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-001.html index d8d8669354b..126876367a4 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-001.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -24,15 +25,15 @@ policies and contribution forms [3]. //test iframe test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('iframe'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; @@ -46,15 +47,15 @@ test(unit(function (ctx) { //test object test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('object'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; @@ -68,15 +69,15 @@ test(unit(function (ctx) { //test video test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('video'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; @@ -90,15 +91,15 @@ test(unit(function (ctx) { //test audio test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('audio'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; @@ -112,15 +113,15 @@ test(unit(function (ctx) { //test canvas test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('canvas'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; @@ -134,7 +135,7 @@ test(unit(function (ctx) { //test map test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); var img = d.createElement('img'); img.setAttribute('usemap', '#theMap'); @@ -143,14 +144,14 @@ test(unit(function (ctx) { d.body.appendChild(img); - // create element + // create element var el = d.createElement('map'); el.setAttribute('name', 'theMap'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); @@ -165,15 +166,15 @@ test(unit(function (ctx) { //test textarea test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('textarea'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; @@ -187,15 +188,15 @@ test(unit(function (ctx) { //test progress test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('progress'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; @@ -209,15 +210,15 @@ test(unit(function (ctx) { //test meter test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('meter'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-002.html index ac32bc5f7c8..8c2c6575ae7 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-002.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -24,9 +25,9 @@ policies and contribution forms [3]. //test img test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('img'); d.body.appendChild(el); @@ -35,7 +36,7 @@ test(unit(function (ctx) { s.innerHTML = ''; assert_true(s.querySelector('#cont') != null, 'img should allow one insertion point ' + - 'that matches nothing'); + 'that matches nothing'); }), 'A_09_00_02_T01'); @@ -43,9 +44,9 @@ test(unit(function (ctx) { //test embed test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('embed'); d.body.appendChild(el); @@ -54,7 +55,7 @@ test(unit(function (ctx) { s.innerHTML = ''; assert_true(s.querySelector('#cont') != null, 'embed should allow one insertion point ' + - 'that matches nothing'); + 'that matches nothing'); }), 'A_09_00_02_T02'); @@ -62,9 +63,9 @@ test(unit(function (ctx) { //test embed test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('input'); d.body.appendChild(el); @@ -73,7 +74,7 @@ test(unit(function (ctx) { s.innerHTML = ''; assert_true(s.querySelector('#cont') != null, 'input should allow one insertion point ' + - 'that matches nothing'); + 'that matches nothing'); }), 'A_09_00_02_T03'); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-003.html index e44c45d1a98..fc52026f776 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-003.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-003.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -24,15 +25,15 @@ policies and contribution forms [3]. //test universal selector test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('fieldset'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; @@ -47,23 +48,23 @@ test(unit(function (ctx) { //test legend:first-of-type test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('fieldset'); d.body.appendChild(el); el.innerHTML = '' + - '' - 'This is a node that should be distributed' + - '' + - 'Unlucky content'; + '' + 'This is a node that should be distributed' + + '' + + 'Unlucky content'; var s = el.createShadowRoot(); s.innerHTML = ''; assert_true(d.querySelector('#shadow').offsetTop > 0, 'fieldset should allow insertion point ' + - 'with legend:first-of-type matching criteria'); + 'with legend:first-of-type matching criteria'); assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered'); }), 'A_09_00_03_T02'); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-004.html index 3610c457440..8ac5371c532 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-004.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-004.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -24,16 +25,16 @@ policies and contribution forms [3]. //test universal selector test(unit(function (ctx) { - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - // create element + // create element var el = d.createElement('details'); el.setAttribute('open', 'open'); d.body.appendChild(el); el.innerHTML = '' + - 'This is a node that should be distributed' + - 'This is a fallback content'; + 'This is a node that should be distributed' + + 'This is a fallback content'; var s = el.createShadowRoot(); s.innerHTML = ''; diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-001.html index 4b1015d99c3..99a4edc2963 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-001.html @@ -16,14 +16,14 @@ policies and contribution forms [3]. - +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html index 0c3984a2eac..e39ef062659 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html @@ -16,14 +16,14 @@ policies and contribution forms [3]. - +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html index 6b9c83ed8f5..c6dfbc4f08e 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html @@ -16,7 +16,7 @@ policies and contribution forms [3]. - +
@@ -24,24 +24,24 @@ policies and contribution forms [3]. var A_08_02_03_T01 = async_test('A_08_02_03_T01', { timeout: 5000 }); A_08_02_03_T01.checkIframeContent = A_08_02_03_T01.step_func(function () { - //remember value to check before cleaning the context (it'll destroy the iframe) - var valueToCheck = A_08_02_03_T01.iframe.contentWindow.document.URL; - cleanContext(A_08_02_03_T01.ctx); + //remember value to check before cleaning the context (it'll destroy the iframe) + var valueToCheck = A_08_02_03_T01.iframe.contentWindow.document.URL; + cleanContext(A_08_02_03_T01.ctx); - assert_true(valueToCheck.indexOf('inp1=value1') > 0, - 'html form should submit all of its fields'); + assert_true(valueToCheck.indexOf('inp1=value1') > 0, + 'html form should submit all of its fields'); - // Expected behavior is not quite clear. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=20320 - assert_true(valueToCheck.indexOf('inp2=value2') > 0, - 'html form should submit all of its fields including the shadow ones'); + // Expected behavior is not quite clear. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=20320 + assert_true(valueToCheck.indexOf('inp2=value2') > 0, + 'html form should submit all of its fields including the shadow ones'); - A_08_02_03_T01.done(); + A_08_02_03_T01.done(); }); A_08_02_03_T01.step(function () { - A_08_02_03_T01.ctx = newContext(); + A_08_02_03_T01.ctx = newContext(); var d = newRenderedHTMLDocument(A_08_02_03_T01.ctx); //create iframe diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-001.html index 52c689c1bd8..c0c6048f729 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-001.html @@ -16,7 +16,7 @@ policies and contribution forms [3]. - +
@@ -24,20 +24,20 @@ policies and contribution forms [3]. var A_08_01_01_T01 = async_test('A_08_01_01_T01', { timeout: 5000 }); A_08_01_01_T01.checkIframeContent = A_08_01_01_T01.step_func(function () { - //remember value to check before cleaning the context (it'll destroy the iframe) - var valueToCheck = A_08_01_01_T01.iframe.contentWindow; - cleanContext(A_08_01_01_T01.ctx); + //remember value to check before cleaning the context (it'll destroy the iframe) + var valueToCheck = A_08_01_01_T01.iframe.contentWindow; + cleanContext(A_08_01_01_T01.ctx); - assert_equals(valueToCheck, null, - 'base html element ih a shadow tree must beahve like inert one'); + assert_equals(valueToCheck, null, + 'base html element ih a shadow tree must beahve like inert one'); - A_08_01_01_T01.done(); + A_08_01_01_T01.done(); }); A_08_01_01_T01.step(function () { - A_08_01_01_T01.ctx = newContext(); + A_08_01_01_T01.ctx = newContext(); var d = newRenderedHTMLDocument(A_08_01_01_T01.ctx); //create iframe diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html index b7c6399f5e0..918588b6746 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html @@ -16,26 +16,27 @@ policies and contribution forms [3]. - + +
- - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-001.html deleted file mode 100644 index 839e5dfdab5..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-001.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - -Shadow DOM Test: A_04_04_01 - - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-002.html deleted file mode 100644 index 4e656257d05..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-002.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - -Shadow DOM Test: A_04_04_01 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/custom-pseudo-elements/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/custom-pseudo-elements/test-001.html deleted file mode 100644 index e963ba4bc8a..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/custom-pseudo-elements/test-001.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - -Shadow DOM Test: A_04_10_01 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html deleted file mode 100644 index e19d98845c3..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - -Shadow DOM Test: Distribution: Unordered list (Reference) - - - -

-You should see an unordered list below, consisting of ten elements -each of which contains a capital letter ranging from "A" to "J", -in alphabetical order. -

-
    -
  • A
  • -
  • B
  • -
  • C
  • -
  • D
  • -
  • E
  • -
  • F
  • -
  • G
  • -
  • H
  • -
  • I
  • -
  • J
  • -
- - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html deleted file mode 100644 index 891b4248946..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -Shadow DOM Test: Distribution: Unordered list - - - - - - - -

-You should see an unordered list below, consisting of ten elements -each of which contains a capital letter ranging from "A" to "J", -in alphabetical order. -

-
    -
  • H
  • -
  • B
  • -
  • E
  • -
  • I
  • -
  • C
  • -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html deleted file mode 100644 index 5114b64b4ea..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - -Shadow DOM Test: Distribution: Ordered list (Reference) - - - - -

-You should see an ordered list below, consisting of ten elements numbered -from 1 through 10, and each line should contain a capital letter ranging from -"A" to "J", in alphabetical order. -

-
    -
  1. A
  2. -
  3. B
  4. -
  5. C
  6. -
  7. D
  8. -
  9. E
  10. -
  11. F
  12. -
  13. G
  14. -
  15. H
  16. -
  17. I
  18. -
  19. J
  20. -
- - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html deleted file mode 100644 index e0d93ad6f34..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - -Shadow DOM Test: Distribution: Ordered list - - - - - - - - - -

-You should see an ordered list below, consisting of ten elements numbered -from 1 through 10, and each line should contain a capital letter ranging from -"A" to "J", in alphabetical order. -

-
    -
  1. H
  2. -
  3. B
  4. -
  5. E
  6. -
  7. I
  8. -
  9. C
  10. -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-003.html deleted file mode 100644 index 957030810e8..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-003.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -Shadow DOM Test: Invariants after distribution - - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-003.html deleted file mode 100644 index cb377f39462..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-003.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - -Shadow DOM Test: A_04_02_03 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html index de1b5404908..13fa063912f 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html @@ -16,7 +16,7 @@ policies and contribution forms [3]. - +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-005.html deleted file mode 100644 index c3103a0f7c8..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-005.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - -Shadow DOM Test: A_04_02_05 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest-ref.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest-ref.html index f4b8bab7602..3050cefe9d9 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest-ref.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest-ref.html @@ -4,7 +4,7 @@ Shadow DOM Test Ref file - Tests nested shadow tree. - + diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002-ref.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002-ref.html deleted file mode 100644 index 8e538c91e59..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002-ref.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - -Shadow DOM Test: Basic reprojection with a select attribute (reference) - - - - - -

You should see green text saying "Apple" below.

-
-
Hello a Shadow Root2.
-
-
Apple.
-
-
- - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html deleted file mode 100644 index 8cc408d8860..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - -Shadow DOM Test - Tests a reprojection with a select attribute. - - - - - - - - - -

You should see green text saying "Apple" below.

-
-
Apple.
-
Orange.
-
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/test-001.html deleted file mode 100644 index 00a2a3e854a..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/test-001.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - -Shadow DOM Test: A_04_06_01 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-001.html deleted file mode 100644 index 86b1f2b96fc..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-001.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_01 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-002.html deleted file mode 100644 index cd5b59cdc11..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-002.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_02 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-003.html deleted file mode 100644 index 8a25ebc5af2..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-003.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_03 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-004.html deleted file mode 100644 index 8abcb7b7d9b..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-004.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_04 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-005.html deleted file mode 100644 index 5069f219bed..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-005.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_05 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-001.html index 8ab15a1ac3e..fb228cda5dd 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-001.html @@ -16,7 +16,7 @@ policies and contribution forms [3]. - + '; + ''; - d.body.innerHTML = - '
    ' + - '
  • 1
  • ' + - '
  • 2
  • ' + - '
  • 3
  • ' + - '
  • 4
  • ' + - '
  • 5
  • ' + - '
  • 6
  • ' + - '
'; + d.body.innerHTML = + '
    ' + + '
  • 1
  • ' + + '
  • 2
  • ' + + '
  • 3
  • ' + + '
  • 4
  • ' + + '
  • 5
  • ' + + '
  • 6
  • ' + + '
'; - var host = d.querySelector('#shHost'); - var s = host.createShadowRoot(); + var host = d.querySelector('#shHost'); + var s = host.createShadowRoot(); - var div = d.createElement('div'); - div.innerHTML ='
'; - s.appendChild(div); + var div = d.createElement('div'); + div.innerHTML ='
'; + s.appendChild(div); - var defHeight1 = d.querySelector('#li1').offsetHeight; - var defHeight3 = d.querySelector('#li3').offsetHeight; - var defHeight5 = d.querySelector('#li5').offsetHeight; + var defHeight1 = d.querySelector('#li1').offsetHeight; + var defHeight3 = d.querySelector('#li3').offsetHeight; + var defHeight5 = d.querySelector('#li5').offsetHeight; - var style = d.createElement('style'); - style.innerHTML =':root {' + - 'var-text-size: 30px;' + - '}' + - 'body {' + - 'font-size: var(text-size);' + - '}'; - s.appendChild(style); + var style = d.createElement('style'); + style.innerHTML =':root {' + + 'var-text-size: 30px;' + + '}' + + 'body {' + + 'font-size: var(text-size);' + + '}'; + s.appendChild(style); - assert_true(d.querySelector('#li1').offsetHeight > defHeight1, 'Point 1: Element height should be changed'); - assert_true(d.querySelector('#li3').offsetHeight > defHeight3, 'Point 2: Element height should be changed'); - assert_true(d.querySelector('#li5').offsetHeight > defHeight5, 'Point 3: Element height should be changed'); + assert_true(d.querySelector('#li1').offsetHeight > defHeight1, 'Point 1: Element height should be changed'); + assert_true(d.querySelector('#li3').offsetHeight > defHeight3, 'Point 2: Element height should be changed'); + assert_true(d.querySelector('#li5').offsetHeight > defHeight5, 'Point 3: Element height should be changed'); }), 'A_06_01_01_T01'); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/deep-combinator/deep-combinator-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/deep-combinator/deep-combinator-001.html deleted file mode 100644 index a5ac473860b..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/deep-combinator/deep-combinator-001.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - -Shadow DOM Test: /deep/ combinator - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html index abef32a1811..01db057ae2e 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html @@ -15,7 +15,7 @@ policies and contribution forms [3]. - + '; + '.invis {' + + 'display:none;' + + '}' + + ''; var host = d.createElement('div'); d.body.appendChild(host); - //Shadow root to play with - var s = host.createShadowRoot(); + //Shadow root to play with + var s = host.createShadowRoot(); - var div1 = d.createElement('div'); - div1.innerHTML ='This is the shadow tree'; - s.appendChild(div1); + var div1 = d.createElement('div'); + div1.innerHTML ='This is the shadow tree'; + s.appendChild(div1); - //apply-author-styles flag is false by default. Invisible style shouldn't be applied - assert_true(s.querySelector('#shd').offsetTop > 0, - 'CSS styles declared in enclosing tree must not be applied in a shadow tree ' + - 'if the apply-author-styles flag is set to false'); + //apply-author-styles flag is false by default. Invisible style shouldn't be applied + assert_true(s.querySelector('#shd').offsetTop > 0, + 'CSS styles declared in enclosing tree must not be applied in a shadow tree ' + + 'if the apply-author-styles flag is set to false'); }), 'A_06_00_01_T01'); @@ -57,115 +58,28 @@ test(unit(function (ctx) { var d = newRenderedHTMLDocument(ctx); d.head.innerHTML = ''; + '.invis {' + + 'display:none;' + + '}' + + ''; var host = d.createElement('div'); d.body.appendChild(host); - //Shadow root to play with - var s = host.createShadowRoot(); + //Shadow root to play with + var s = host.createShadowRoot(); - var div1 = d.createElement('div'); - div1.innerHTML ='This is the shadow tree'; - s.appendChild(div1); + var div1 = d.createElement('div'); + div1.innerHTML ='This is the shadow tree'; + s.appendChild(div1); - //apply-author-styles flag is set to false. Invisible style shouldn't be applied - assert_true(s.querySelector('#shd').offsetTop > 0, - 'CSS styles declared in enclosing tree must not be applied in a shadow tree ' + - 'if the apply-author-styles flag is set to false'); + //apply-author-styles flag is set to false. Invisible style shouldn't be applied + assert_true(s.querySelector('#shd').offsetTop > 0, + 'CSS styles declared in enclosing tree must not be applied in a shadow tree ' + + 'if the apply-author-styles flag is set to false'); }), 'A_06_00_01_T02'); - -//test apply-author-styles flag in a nested tree (default value) -test(unit(function (ctx) { - - var d = newRenderedHTMLDocument(ctx); - - d.head.innerHTML = ''; - - var host = d.createElement('div'); - d.body.appendChild(host); - - //Shadow root to play with - var s1 = host.createShadowRoot(); - - var div1 = d.createElement('div'); - div1.innerHTML = 'This is an old shadow tree'; - s1.appendChild(div1); - - //younger tree - var s2 = host.createShadowRoot(); - var div1 = d.createElement('div'); - div1.innerHTML = 'This is a young shadow tree' + - 'This is the shadow tree fallback content'; - s2.appendChild(div1); - - - //apply-author-styles flag is false by default. Invisible style shouldn't be applied - //shd1 and shd2 should be visible. sh3 not because the tree should be active - assert_true(s1.querySelector('#shd1').offsetTop > 0, - 'Point 1: CSS styles declared in enclosing tree must not be applied in a shadow tree ' + - 'if the apply-author-styles flag is set to false'); - assert_true(s2.querySelector('#shd2').offsetTop > 0, - 'Point 2: CSS styles declared in enclosing tree must not be applied in a shadow tree ' + - 'if the apply-author-styles flag is set to false'); - assert_equals(s2.querySelector('#shd3').offsetTop, 0, - 'Fallback content shouldn\'t be rendered for active tree'); - - -}), 'A_06_00_01_T03'); - - -//test apply-author-styles flag in a nested tree (set it) -test(unit(function (ctx) { - - var d = newRenderedHTMLDocument(ctx); - - d.head.innerHTML = ''; - - var host = d.createElement('div'); - d.body.appendChild(host); - - //Shadow root to play with - var s1 = host.createShadowRoot(); - - var div1 = d.createElement('div'); - div1.innerHTML = 'This is an old shadow tree'; - s1.appendChild(div1); - - //younger tree - var s2 = host.createShadowRoot(); - var div1 = d.createElement('div'); - div1.innerHTML = 'This is a young shadow tree' + - 'This is the shadow tree fallback content'; - s2.appendChild(div1); - - - //apply-author-styles flag is set to false. Invisible style shouldn't be applied - //shd1 and shd2 should be visible. sh3 not because the tree should be active - assert_true(s1.querySelector('#shd1').offsetTop > 0, - 'Point 1: CSS styles declared in enclosing tree must not be applied in a shadow tree ' + - 'if the apply-author-styles flag is set to false'); - assert_true(s2.querySelector('#shd2').offsetTop > 0, - 'Point 2: CSS styles declared in enclosing tree must not be applied in a shadow tree ' + - 'if the apply-author-styles flag is set to false'); - assert_equals(s2.querySelector('#shd3').offsetTop, 0, - 'Fallback content shouldn\'t be rendered for active tree'); - - -}), 'A_06_00_01_T04'); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-003.html index 7e18934d59c..bac7006a657 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-003.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-003.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -42,7 +43,7 @@ test(unit(function (ctx) { //Shadow root to play with var s = host.createShadowRoot(); - assert_equals(s.styleSheets.length, 0, 'There should be no style sheets'); + assert_equals(s.styleSheets.length, 0, 'There should be no style sheets'); }), 'A_06_00_03_T02'); //TODO Now this tests produces an error on Chromium because styleSheets.length diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-005.html index f5eaeabb8a1..faba0a20a31 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-005.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-005.html @@ -16,45 +16,46 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-007.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-007.html deleted file mode 100644 index d29f1f6c615..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-007.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -Shadow DOM Test: A_06_00_08 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-008.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-008.html index 7f9b0c7311b..733b80fe2aa 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-008.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-008.html @@ -16,80 +16,41 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-009.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-009.html deleted file mode 100644 index 63f6aa40a65..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-009.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - -Shadow DOM Test: A_06_00_10 - - - - - - - - -
- - - diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-010.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-010.html index 9da81ffd086..69a1c7bf196 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-010.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/styles/test-010.html @@ -16,39 +16,40 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/testcommon.js b/tests/wpt/web-platform-tests/shadow-dom/untriaged/testcommon.js deleted file mode 100644 index cce78e9c2d8..00000000000 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/testcommon.js +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. - -/* -Distributed under both the W3C Test Suite License [1] and the W3C -3-clause BSD License [2]. To contribute to a W3C Test Suite, see the -policies and contribution forms [3]. - -[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license -[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license -[3] http://www.w3.org/2004/10/27-testcases -*/ - -"use strict"; - -var HTML5_ELEMENT_NAMES = [ - 'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', - 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', - 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'command', - 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', - 'em', 'embed', - 'fieldset', 'figcaption', 'figure', 'footer', 'form', - 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', - 'html', - 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', - 'label', 'legend', 'li', 'link', - 'map', 'mark', 'menu', 'meta', 'meter', - 'nav', 'noscript', - 'object', 'ol', 'optgroup', 'option', 'output', - 'p', 'param', 'pre', 'progress', - 'q', - 'rp', 'rt', 'ruby', - 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', - 'strong', 'style', 'sub', - 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', - 'title', 'tr', 'track', - 'u', 'ul', - 'var', 'video', - 'wbr' -]; - -// http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#form-associated-element -var HTML5_FORM_ASSOCIATED_ELEMENTS = ['button', 'fieldset', 'input', 'keygen', 'label', - 'object', 'output', 'select', 'textarea']; - -// Whether to work around vendor prefixes. -var USE_VENDOR_SPECIFIC_WORKAROUND = true; - -function activateVendorSpecificWorkaround() { - if (Element.prototype.webkitCreateShadowRoot && - !Element.prototype.createShadowRoot) { - Element.prototype.createShadowRoot = - Element.prototype.webkitCreateShadowRoot; - - Object.defineProperty(Element.prototype, 'pseudo', { - get: function () { return this.webkitPseudo; }, - set: function (value) { return this.webkitPseudo = value; } - }); - - Object.defineProperty(Element.prototype, 'shadowRoot', { - get: function () { return this.webkitShadowRoot; } - }); - } -} - -if (USE_VENDOR_SPECIFIC_WORKAROUND) - activateVendorSpecificWorkaround(); - -// ---------------------------------------------------------------------------- -// Deprecated: The code below is preserved only for the existing tests that are -// using it. Now vendor prefixes are handled in a way that does not require -// manual intervention. New tests should just use unprefixed APIs and you -// are all set. -// -// These functions will eventually be removed when no tests use them. - -function ShadowDomNotSupportedError() { - this.message = "Shadow DOM is not supported"; -} - -// To allow using of both prefixed and non-prefixed API we do -// the following hook -function addPrefixed(element) { - if (element && !element.pseudo) { - Object.defineProperty(element, 'pseudo', { - get: function () { return element.webkitPseudo; }, - set: function (value) { return element.webkitPseudo = value; } - }); - } -} - -function addDocumentPrefixed(d) { - if (d) { - if (d.body) { - addPrefixed(d.body); - } - if (d.head) { - addPrefixed(d.head); - } - if (d.documentElement) { - addPrefixed(d.documentElement); - } - d.oldCreate = d.createElement; - d.createElement = function(tagName) { - var el = d.oldCreate(tagName); - addPrefixed(el); - return el; - }; - } -} - - -function rethrowInternalErrors(e) { - if (e instanceof ShadowDomNotSupportedError) { - throw e; - } - -} - -function newDocument() { - var d = document.implementation.createDocument( - 'http://www.w3.org/1999/xhtml', 'html'); - //FIXME remove the call below when non-prefixed API is used - addDocumentPrefixed(d); - return d; -} - -function newHTMLDocument() { - var d = document.implementation.createHTMLDocument('Test Document'); - //FIXME remove the call below when non-prefixed API is used - addDocumentPrefixed(d); - return d; -} - -function newIFrame(ctx, src) { - if (typeof(ctx) == 'undefined' || typeof (ctx.iframes) != 'object') { - assert_unreached('Illegal context object in newIFrame'); - } - - var iframe = document.createElement('iframe'); - if (!ctx.debug) { - iframe.style.display = 'none'; - } - if (typeof(src) != 'undefined') { - iframe.src = src; - } - document.body.appendChild(iframe); - ctx.iframes.push(iframe); - - assert_true(typeof(iframe.contentWindow) != 'undefined' - && typeof(iframe.contentWindow.document) != 'undefined' - && iframe.contentWindow.document != document, 'Failed to create new rendered document' - ); - return iframe; -} -function newRenderedHTMLDocument(ctx) { - var frame = newIFrame(ctx); - var d = frame.contentWindow.document; - //FIXME remove the call below when non-prefixed API is used - addDocumentPrefixed(d); - return d; -} - -// End deprecated. -// ---------------------------------------------------------------------------- - -function newContext() { - return {iframes:[]}; -} - -function cleanContext(ctx) { - if (!ctx.debug) { - ctx.iframes.forEach(function (e) { - e.parentNode.removeChild(e); - }); - } -} - -function unit(f) { - return function () { - var ctx = newContext(); - try { - f(ctx); - } finally { - cleanContext(ctx); - } - } -} - -function step_unit(f, ctx, t) { - return function () { - var done = false; - try { - f(); - done = true; - } finally { - if (done) { - t.done(); - } - cleanContext(ctx); - } - } -} - -function assert_nodelist_contents_equal_noorder(actual, expected, message) { - assert_equals(actual.length, expected.length, message); - var used = []; - for (var i = 0; i < expected.length; i++) { - used.push(false); - } - for (i = 0; i < expected.length; i++) { - var found = false; - for (var j = 0; j < actual.length; j++) { - if (used[j] == false && expected[i] == actual[j]) { - used[j] = true; - found = true; - break; - } - } - if (!found) { - assert_unreached(message + ". Fail reason: element not found: " + expected[i]); - } - } -} - - -//Example taken from http://www.w3.org/TR/shadow-dom/#event-retargeting-example -function createTestMediaPlayer(d) { - d.body.innerHTML = '' + - '
' + - '' + - '
' + - '
' + - '
'; - - var playerShadowRoot = d.querySelector('#player-shadow-host').createShadowRoot(); - playerShadowRoot.innerHTML = '' + - '
' + - '' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
'; - - var timeLineShadowRoot = playerShadowRoot.querySelector('#timeline-shadow-host').createShadowRoot(); - timeLineShadowRoot.innerHTML = '
'; - - var volumeShadowRoot = playerShadowRoot.querySelector('#volume-shadow-host').createShadowRoot(); - volumeShadowRoot.innerHTML = '
'; - - return { - 'playerShadowRoot': playerShadowRoot, - 'timeLineShadowRoot': timeLineShadowRoot, - 'volumeShadowRoot': volumeShadowRoot - }; -} - -//FIXME This call of initKeyboardEvent works for WebKit-only. -//See https://bugs.webkit.org/show_bug.cgi?id=16735 -// and https://bugs.webkit.org/show_bug.cgi?id=13368. Add check for browser here -function fireKeyboardEvent(doc, element, key) { - var event = doc.createEvent('KeyboardEvent'); - event.initKeyboardEvent("keydown", true, true, doc.defaultView, key, 0, false, false, false, false); - element.dispatchEvent(event); -} diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-001.html index 25c548b0cb7..6d9850b3497 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-001.html @@ -16,30 +16,31 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-002.html index 79081843569..9019760b7d8 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-002.html @@ -16,31 +16,32 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html index c22aab32c86..52f53551c6e 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html index d751f47de7c..b19f10a9539 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -25,60 +26,60 @@ var A_07_02_01_T01 = async_test('A_07_02_01_T01'); A_07_02_01_T01.step(unit(function (ctx) { - var counter = 0; + var counter = 0; - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - }), false); - d.body.appendChild(chb1); + var chb1 = d.createElement('input'); + chb1.setAttribute('type', 'checkbox'); + chb1.setAttribute('id', 'chb1'); + chb1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { + assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); + }), false); + d.body.appendChild(chb1); - var host = d.createElement('div'); - d.body.appendChild(host); - var s = host.createShadowRoot(); + var host = d.createElement('div'); + d.body.appendChild(host); + var s = host.createShadowRoot(); - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { - assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); - }), false); - s.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('type', 'text'); + inp1.setAttribute('id', 'shInp1'); + inp1.setAttribute('value', 'Input 1'); + inp1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { + assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); + }), false); + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { - assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); - }), false); - s.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('type', 'text'); + inp2.setAttribute('id', 'shInp2'); + inp2.setAttribute('value', 'Input 2'); + inp2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { + assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); + }), false); + s.appendChild(inp2); - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { - assert_equals(counter++, 3, 'Point 4: wrong focus navigation order'); - }), false); - d.body.appendChild(chb2); + var chb2 = d.createElement('input'); + chb2.setAttribute('type', 'checkbox'); + chb2.setAttribute('id', 'chb2'); + chb2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { + assert_equals(counter++, 3, 'Point 4: wrong focus navigation order'); + }), false); + d.body.appendChild(chb2); - chb1.focus(); + chb1.focus(); - //simulate TAB clicks - fireKeyboardEvent(d, chb1, 'U+0009'); + //simulate TAB clicks + fireKeyboardEvent(d, chb1, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); + fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); + fireKeyboardEvent(d, inp2, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); + fireKeyboardEvent(d, chb2, 'U+0009'); - A_07_02_01_T01.done(); + A_07_02_01_T01.done(); })); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html index 17c52b314a9..e50d4f33462 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -26,99 +27,99 @@ var A_07_02_02_T02 = async_test('A_07_02_02_T02'); A_07_02_02_T01.step(unit(function (ctx) { - var counter = 0; + var counter = 0; - var expectations = []; + var expectations = []; - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var host = d.createElement('div'); - d.body.appendChild(host); + var host = d.createElement('div'); + d.body.appendChild(host); - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - assert_true(false, 'Element shouldn\'t be rendered'); - }), false); - host.appendChild(chb1); + var chb1 = d.createElement('input'); + chb1.setAttribute('type', 'checkbox'); + chb1.setAttribute('id', 'chb1'); + chb1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { + assert_true(false, 'Element shouldn\'t be rendered'); + }), false); + host.appendChild(chb1); - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('class', 'shadow'); - chb2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - expectations[1] = true; - }), false); - expectations[1] = false; - host.appendChild(chb2); + var chb2 = d.createElement('input'); + chb2.setAttribute('type', 'checkbox'); + chb2.setAttribute('id', 'chb2'); + chb2.setAttribute('class', 'shadow'); + chb2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { + assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); + expectations[1] = true; + }), false); + expectations[1] = false; + host.appendChild(chb2); - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('class', 'shadow'); - chb3.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); - expectations[2] = true; - }), false); - expectations[2] = false; - host.appendChild(chb3); + var chb3 = d.createElement('input'); + chb3.setAttribute('type', 'checkbox'); + chb3.setAttribute('id', 'chb3'); + chb3.setAttribute('class', 'shadow'); + chb3.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { + assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); + expectations[2] = true; + }), false); + expectations[2] = false; + host.appendChild(chb3); - var s = host.createShadowRoot(); + var s = host.createShadowRoot(); - var div = d.createElement('div'); - div.innerHTML = ''; - s.appendChild(div); + var div = d.createElement('div'); + div.innerHTML = ''; + s.appendChild(div); - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - expectations[3] = false; - }), false); - expectations[3] = true; - s.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('type', 'text'); + inp1.setAttribute('id', 'shInp1'); + inp1.setAttribute('value', 'Input 1'); + inp1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { + expectations[3] = false; + }), false); + expectations[3] = true; + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - expectations[4] = false; - }), false); - expectations[4] = true; - s.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('type', 'text'); + inp2.setAttribute('id', 'shInp2'); + inp2.setAttribute('value', 'Input 2'); + inp2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { + expectations[4] = false; + }), false); + expectations[4] = true; + s.appendChild(inp2); - var chb4 = d.createElement('input'); - chb4.setAttribute('type', 'checkbox'); - chb4.setAttribute('id', 'chb4'); - chb4.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - assert_equals(counter++, 2, 'Point 5: wrong focus navigation order'); - expectations[5] = true; - }), false); - expectations[5] = false; - d.body.appendChild(chb4); + var chb4 = d.createElement('input'); + chb4.setAttribute('type', 'checkbox'); + chb4.setAttribute('id', 'chb4'); + chb4.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { + assert_equals(counter++, 2, 'Point 5: wrong focus navigation order'); + expectations[5] = true; + }), false); + expectations[5] = false; + d.body.appendChild(chb4); - chb2.focus(); + chb2.focus(); - //simulate TAB clicks - fireKeyboardEvent(d, chb2, 'U+0009'); + //simulate TAB clicks + fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); + fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); + fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); + fireKeyboardEvent(d, inp2, 'U+0009'); - fireKeyboardEvent(d, chb4, 'U+0009'); + fireKeyboardEvent(d, chb4, 'U+0009'); - for (var i = 1; i < expectations.length; i++) { - if (!expectations[i]) { - assert_true(false, 'Point ' + i + ' event listener was not invoked'); - } - } + for (var i = 1; i < expectations.length; i++) { + if (!expectations[i]) { + assert_true(false, 'Point ' + i + ' event listener was not invoked'); + } + } A_07_02_02_T01.done(); })); @@ -127,108 +128,108 @@ A_07_02_02_T01.step(unit(function (ctx) { A_07_02_02_T02.step(unit(function (ctx) { - var counter = 0; + var counter = 0; - var expectations = []; + var expectations = []; - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var chb0 = d.createElement('input'); - chb0.setAttribute('type', 'checkbox'); - chb0.setAttribute('id', 'chb0'); + var chb0 = d.createElement('input'); + chb0.setAttribute('type', 'checkbox'); + chb0.setAttribute('id', 'chb0'); d.body.appendChild(chb0); - var host = d.createElement('div'); - d.body.appendChild(host); + var host = d.createElement('div'); + d.body.appendChild(host); - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_true(false, 'Element shouldn\'t be rendered'); - }), false); - host.appendChild(chb1); + var chb1 = d.createElement('input'); + chb1.setAttribute('type', 'checkbox'); + chb1.setAttribute('id', 'chb1'); + chb1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { + assert_true(false, 'Element shouldn\'t be rendered'); + }), false); + host.appendChild(chb1); - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('class', 'shadow'); - chb2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); - expectations[1] = true; - }), false); - expectations[1] = false; - host.appendChild(chb2); + var chb2 = d.createElement('input'); + chb2.setAttribute('type', 'checkbox'); + chb2.setAttribute('id', 'chb2'); + chb2.setAttribute('class', 'shadow'); + chb2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { + assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); + expectations[1] = true; + }), false); + expectations[1] = false; + host.appendChild(chb2); - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('class', 'shadow'); - chb3.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 3, 'Point 4: wrong focus navigation order'); - expectations[2] = true; - }), false); - expectations[2] = false; - host.appendChild(chb3); + var chb3 = d.createElement('input'); + chb3.setAttribute('type', 'checkbox'); + chb3.setAttribute('id', 'chb3'); + chb3.setAttribute('class', 'shadow'); + chb3.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { + assert_equals(counter++, 3, 'Point 4: wrong focus navigation order'); + expectations[2] = true; + }), false); + expectations[2] = false; + host.appendChild(chb3); - var s = host.createShadowRoot(); + var s = host.createShadowRoot(); - var div = d.createElement('div'); - div.innerHTML = ''; - s.appendChild(div); + var div = d.createElement('div'); + div.innerHTML = ''; + s.appendChild(div); - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); + var inp1 = d.createElement('input'); + inp1.setAttribute('type', 'text'); + inp1.setAttribute('id', 'shInp1'); + inp1.setAttribute('value', 'Input 1'); + inp1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { + assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - expectations[3] = true; - }), false); - expectations[3] = false; - s.appendChild(inp1); + expectations[3] = true; + }), false); + expectations[3] = false; + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); - expectations[4] = true; - }), false); - expectations[4] = false; - s.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('type', 'text'); + inp2.setAttribute('id', 'shInp2'); + inp2.setAttribute('value', 'Input 2'); + inp2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { + assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); + expectations[4] = true; + }), false); + expectations[4] = false; + s.appendChild(inp2); - var chb4 = d.createElement('input'); - chb4.setAttribute('type', 'checkbox'); - chb4.setAttribute('id', 'chb4'); - chb4.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 4, 'Point 5: wrong focus navigation order'); - expectations[5] = true; - }), false); - expectations[5] = false; - d.body.appendChild(chb4); + var chb4 = d.createElement('input'); + chb4.setAttribute('type', 'checkbox'); + chb4.setAttribute('id', 'chb4'); + chb4.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { + assert_equals(counter++, 4, 'Point 5: wrong focus navigation order'); + expectations[5] = true; + }), false); + expectations[5] = false; + d.body.appendChild(chb4); - chb0.focus(); + chb0.focus(); - //simulate TAB clicks - fireKeyboardEvent(d, inp1, 'U+0009'); + //simulate TAB clicks + fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); + fireKeyboardEvent(d, inp2, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); + fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); + fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, chb4, 'U+0009'); + fireKeyboardEvent(d, chb4, 'U+0009'); - for (var i = 1; i < expectations.length; i++) { - if (!expectations[i]) { - assert_true(false, 'Point ' + i + ' event listener was not invoked'); - } - } + for (var i = 1; i < expectations.length; i++) { + if (!expectations[i]) { + assert_true(false, 'Point ' + i + ' event listener was not invoked'); + } + } A_07_02_02_T02.done(); })); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html index 46082347587..13ee0bdeaeb 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -25,99 +26,99 @@ var A_07_02_03_T01 = async_test('A_07_02_03_T01'); A_07_02_03_T01.step(unit(function (ctx) { - var counter = 0; + var counter = 0; - var invoked = []; + var invoked = []; - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - // TODO according CSS3 nav-index is a replacement for tabindex - //chb1.setAttribute('nav-index', '4'); - chb1.setAttribute('tabindex', '4'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 1, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); + var chb1 = d.createElement('input'); + chb1.setAttribute('type', 'checkbox'); + // TODO according CSS3 nav-index is a replacement for tabindex + //chb1.setAttribute('nav-index', '4'); + chb1.setAttribute('tabindex', '4'); + chb1.setAttribute('id', 'chb1'); + chb1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { + assert_equals(counter++, 1, 'Point 1: wrong focus navigation order'); + invoked[1] = true; + }), false); + invoked[1] = false; + d.body.appendChild(chb1); - var host = d.createElement('div'); - d.body.appendChild(host); - var s = host.createShadowRoot(); + var host = d.createElement('div'); + d.body.appendChild(host); + var s = host.createShadowRoot(); - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - //inp1.setAttribute('nav-index', '3'); - inp1.setAttribute('tabindex', '3'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 4, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - s.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('type', 'text'); + inp1.setAttribute('id', 'shInp1'); + //inp1.setAttribute('nav-index', '3'); + inp1.setAttribute('tabindex', '3'); + inp1.setAttribute('value', 'Input 1'); + inp1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { + assert_equals(counter++, 4, 'Point 2: wrong focus navigation order'); + invoked[2] = true; + }), false); + invoked[2] = false; + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - //inp2.setAttribute('nav-index', '2'); - inp2.setAttribute('tabindex', '2'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 3, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - s.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('type', 'text'); + inp2.setAttribute('id', 'shInp2'); + //inp2.setAttribute('nav-index', '2'); + inp2.setAttribute('tabindex', '2'); + inp2.setAttribute('value', 'Input 2'); + inp2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { + assert_equals(counter++, 3, 'Point 3: wrong focus navigation order'); + invoked[3] = true; + }), false); + invoked[3] = false; + s.appendChild(inp2); - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - //chb2.setAttribute('nav-index', '1'); - chb2.setAttribute('tabindex', '1'); - chb2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 0, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - d.body.appendChild(chb2); + var chb2 = d.createElement('input'); + chb2.setAttribute('type', 'checkbox'); + chb2.setAttribute('id', 'chb2'); + //chb2.setAttribute('nav-index', '1'); + chb2.setAttribute('tabindex', '1'); + chb2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { + assert_equals(counter++, 0, 'Point 4: wrong focus navigation order'); + invoked[4] = true; + }), false); + invoked[4] = false; + d.body.appendChild(chb2); - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - //chb3.setAttribute('nav-index', '5'); - chb3.setAttribute('tabindex', '5'); - chb3.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 2, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(chb3); + var chb3 = d.createElement('input'); + chb3.setAttribute('type', 'checkbox'); + chb3.setAttribute('id', 'chb3'); + //chb3.setAttribute('nav-index', '5'); + chb3.setAttribute('tabindex', '5'); + chb3.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { + assert_equals(counter++, 2, 'Point 5: wrong focus navigation order'); + invoked[5] = true; + }), false); + invoked[5] = false; + d.body.appendChild(chb3); - chb2.focus(); + chb2.focus(); - //simulate TAB clicks. Expected order: chb2, chb1, chb3, inp2, inp1 - fireKeyboardEvent(d, chb2, 'U+0009'); + //simulate TAB clicks. Expected order: chb2, chb1, chb3, inp2, inp1 + fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, chb1, 'U+0009'); + fireKeyboardEvent(d, chb1, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); + fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); + fireKeyboardEvent(d, inp2, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); + fireKeyboardEvent(d, inp1, 'U+0009'); - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } + for (var i = 1; i < invoked.length; i++) { + if (!invoked[i]) { + assert_true(false, 'Piont ' + i + ' event listener was not invoked'); + } + } - A_07_02_03_T01.done(); + A_07_02_03_T01.done(); })); // test nodes, distributed into insertion points @@ -125,111 +126,111 @@ var A_07_02_03_T02 = async_test('A_07_02_03_T02'); A_07_02_03_T02.step(unit(function (ctx) { - var counter = 0; + var counter = 0; - var invoked = []; + var invoked = []; - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var host = d.createElement('div'); - d.body.appendChild(host); + var host = d.createElement('div'); + d.body.appendChild(host); - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.setAttribute('tabindex', '1'); - chb1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); + var chb1 = d.createElement('input'); + chb1.setAttribute('type', 'checkbox'); + chb1.setAttribute('id', 'chb1'); + chb1.setAttribute('tabindex', '1'); + chb1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { + assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); + invoked[1] = true; + }), false); + invoked[1] = false; + d.body.appendChild(chb1); - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('class', 'shadow'); - chb2.setAttribute('tabindex', '3'); - chb2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 2, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - host.appendChild(chb2); + var chb2 = d.createElement('input'); + chb2.setAttribute('type', 'checkbox'); + chb2.setAttribute('id', 'chb2'); + chb2.setAttribute('class', 'shadow'); + chb2.setAttribute('tabindex', '3'); + chb2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { + assert_equals(counter++, 2, 'Point 2: wrong focus navigation order'); + invoked[2] = true; + }), false); + invoked[2] = false; + host.appendChild(chb2); - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('class', 'shadow'); - chb3.setAttribute('tabindex', '2'); - chb3.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 1, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - host.appendChild(chb3); + var chb3 = d.createElement('input'); + chb3.setAttribute('type', 'checkbox'); + chb3.setAttribute('id', 'chb3'); + chb3.setAttribute('class', 'shadow'); + chb3.setAttribute('tabindex', '2'); + chb3.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { + assert_equals(counter++, 1, 'Point 3: wrong focus navigation order'); + invoked[3] = true; + }), false); + invoked[3] = false; + host.appendChild(chb3); - var s = host.createShadowRoot(); + var s = host.createShadowRoot(); - var div = d.createElement('div'); - div.innerHTML = ''; - s.appendChild(div); + var div = d.createElement('div'); + div.innerHTML = ''; + s.appendChild(div); - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.setAttribute('tabindex', '4'); - inp1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 4, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - s.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('type', 'text'); + inp1.setAttribute('id', 'shInp1'); + inp1.setAttribute('value', 'Input 1'); + inp1.setAttribute('tabindex', '4'); + inp1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { + assert_equals(counter++, 4, 'Point 4: wrong focus navigation order'); + invoked[4] = true; + }), false); + invoked[4] = false; + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.setAttribute('tabindex', '5'); - inp2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 5, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - s.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('type', 'text'); + inp2.setAttribute('id', 'shInp2'); + inp2.setAttribute('value', 'Input 2'); + inp2.setAttribute('tabindex', '5'); + inp2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { + assert_equals(counter++, 5, 'Point 5: wrong focus navigation order'); + invoked[5] = true; + }), false); + invoked[5] = false; + s.appendChild(inp2); - var chb4 = d.createElement('input'); - chb4.setAttribute('type', 'checkbox'); - chb4.setAttribute('id', 'chb4'); - chb4.setAttribute('tabindex', '6'); - chb4.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 3, 'Point 6: wrong focus navigation order'); - invoked[6] = true; - }), false); - invoked[6] = false; - d.body.appendChild(chb4); + var chb4 = d.createElement('input'); + chb4.setAttribute('type', 'checkbox'); + chb4.setAttribute('id', 'chb4'); + chb4.setAttribute('tabindex', '6'); + chb4.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { + assert_equals(counter++, 3, 'Point 6: wrong focus navigation order'); + invoked[6] = true; + }), false); + invoked[6] = false; + d.body.appendChild(chb4); - chb1.focus(); + chb1.focus(); - //simulate TAB clicks - //Expected order: chb1, chb3, chb2, chb4, inp1, inp2 - fireKeyboardEvent(d, chb1, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, chb4, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); + //simulate TAB clicks + //Expected order: chb1, chb3, chb2, chb4, inp1, inp2 + fireKeyboardEvent(d, chb1, 'U+0009'); + fireKeyboardEvent(d, chb3, 'U+0009'); + fireKeyboardEvent(d, chb2, 'U+0009'); + fireKeyboardEvent(d, chb4, 'U+0009'); + fireKeyboardEvent(d, inp1, 'U+0009'); + fireKeyboardEvent(d, inp2, 'U+0009'); - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } + for (var i = 1; i < invoked.length; i++) { + if (!invoked[i]) { + assert_true(false, 'Piont ' + i + ' event listener was not invoked'); + } + } - A_07_02_03_T02.done(); + A_07_02_03_T02.done(); })); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html index 10b92659efe..30b08a314b1 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html @@ -16,7 +16,8 @@ policies and contribution forms [3]. - + +
@@ -25,101 +26,101 @@ var A_07_02_04_T01 = async_test('A_07_02_04_T01'); A_07_02_04_T01.step(unit(function (ctx) { - var counter = 0; + var counter = 0; - var invoked = []; + var invoked = []; - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - // TODO according CSS3 nav-index is a replacement for tabindex - //chb1.setAttribute('nav-index', '4'); - chb1.setAttribute('tabindex', '1'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); + var chb1 = d.createElement('input'); + chb1.setAttribute('type', 'checkbox'); + // TODO according CSS3 nav-index is a replacement for tabindex + //chb1.setAttribute('nav-index', '4'); + chb1.setAttribute('tabindex', '1'); + chb1.setAttribute('id', 'chb1'); + chb1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { + assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); + invoked[1] = true; + }), false); + invoked[1] = false; + d.body.appendChild(chb1); - var host = d.createElement('div'); - //make shadow host focusable - host.setAttribute('tabindex', '3'); - d.body.appendChild(host); - var s = host.createShadowRoot(); + var host = d.createElement('div'); + //make shadow host focusable + host.setAttribute('tabindex', '3'); + d.body.appendChild(host); + var s = host.createShadowRoot(); - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - //inp1.setAttribute('nav-index', '3'); - inp1.setAttribute('tabindex', '2'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 3, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - s.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('type', 'text'); + inp1.setAttribute('id', 'shInp1'); + //inp1.setAttribute('nav-index', '3'); + inp1.setAttribute('tabindex', '2'); + inp1.setAttribute('value', 'Input 1'); + inp1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { + assert_equals(counter++, 3, 'Point 2: wrong focus navigation order'); + invoked[2] = true; + }), false); + invoked[2] = false; + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - //inp2.setAttribute('nav-index', '2'); - inp2.setAttribute('tabindex', '1'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - s.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('type', 'text'); + inp2.setAttribute('id', 'shInp2'); + //inp2.setAttribute('nav-index', '2'); + inp2.setAttribute('tabindex', '1'); + inp2.setAttribute('value', 'Input 2'); + inp2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { + assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); + invoked[3] = true; + }), false); + invoked[3] = false; + s.appendChild(inp2); - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - //chb2.setAttribute('nav-index', '1'); - chb2.setAttribute('tabindex', '2'); - chb2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 1, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - d.body.appendChild(chb2); + var chb2 = d.createElement('input'); + chb2.setAttribute('type', 'checkbox'); + chb2.setAttribute('id', 'chb2'); + //chb2.setAttribute('nav-index', '1'); + chb2.setAttribute('tabindex', '2'); + chb2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { + assert_equals(counter++, 1, 'Point 4: wrong focus navigation order'); + invoked[4] = true; + }), false); + invoked[4] = false; + d.body.appendChild(chb2); - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - //chb3.setAttribute('nav-index', '5'); - chb3.setAttribute('tabindex', '4'); - chb3.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 4, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(chb3); + var chb3 = d.createElement('input'); + chb3.setAttribute('type', 'checkbox'); + chb3.setAttribute('id', 'chb3'); + //chb3.setAttribute('nav-index', '5'); + chb3.setAttribute('tabindex', '4'); + chb3.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { + assert_equals(counter++, 4, 'Point 5: wrong focus navigation order'); + invoked[5] = true; + }), false); + invoked[5] = false; + d.body.appendChild(chb3); - chb1.focus(); + chb1.focus(); - //simulate TAB clicks. Expected order: chb1, chb2, inp2, inp1, chb3 - fireKeyboardEvent(d, chb1, 'U+0009'); + //simulate TAB clicks. Expected order: chb1, chb2, inp2, inp1, chb3 + fireKeyboardEvent(d, chb1, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); + fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); + fireKeyboardEvent(d, inp2, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); + fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); + fireKeyboardEvent(d, chb3, 'U+0009'); - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } + for (var i = 1; i < invoked.length; i++) { + if (!invoked[i]) { + assert_true(false, 'Piont ' + i + ' event listener was not invoked'); + } + } - A_07_02_04_T01.done(); + A_07_02_04_T01.done(); })); @@ -129,112 +130,112 @@ var A_07_02_04_T02 = async_test('A_07_02_04_T02'); A_07_02_04_T02.step(unit(function (ctx) { - var counter = 0; + var counter = 0; - var invoked = []; + var invoked = []; - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var host = d.createElement('div'); - host.setAttribute('tabindex', '3'); - d.body.appendChild(host); + var host = d.createElement('div'); + host.setAttribute('tabindex', '3'); + d.body.appendChild(host); - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.setAttribute('tabindex', '1'); - chb1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); + var chb1 = d.createElement('input'); + chb1.setAttribute('type', 'checkbox'); + chb1.setAttribute('id', 'chb1'); + chb1.setAttribute('tabindex', '1'); + chb1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { + assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); + invoked[1] = true; + }), false); + invoked[1] = false; + d.body.appendChild(chb1); - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('class', 'shadow'); - chb2.setAttribute('tabindex', '3'); - chb2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 4, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - host.appendChild(chb2); + var chb2 = d.createElement('input'); + chb2.setAttribute('type', 'checkbox'); + chb2.setAttribute('id', 'chb2'); + chb2.setAttribute('class', 'shadow'); + chb2.setAttribute('tabindex', '3'); + chb2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { + assert_equals(counter++, 4, 'Point 2: wrong focus navigation order'); + invoked[2] = true; + }), false); + invoked[2] = false; + host.appendChild(chb2); - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('class', 'shadow'); - chb3.setAttribute('tabindex', '2'); - chb3.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 1, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - host.appendChild(chb3); + var chb3 = d.createElement('input'); + chb3.setAttribute('type', 'checkbox'); + chb3.setAttribute('id', 'chb3'); + chb3.setAttribute('class', 'shadow'); + chb3.setAttribute('tabindex', '2'); + chb3.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { + assert_equals(counter++, 1, 'Point 3: wrong focus navigation order'); + invoked[3] = true; + }), false); + invoked[3] = false; + host.appendChild(chb3); - var s = host.createShadowRoot(); + var s = host.createShadowRoot(); - var div = d.createElement('div'); - div.innerHTML = ''; - s.appendChild(div); + var div = d.createElement('div'); + div.innerHTML = ''; + s.appendChild(div); - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.setAttribute('tabindex', '4'); - inp1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 3, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - s.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('type', 'text'); + inp1.setAttribute('id', 'shInp1'); + inp1.setAttribute('value', 'Input 1'); + inp1.setAttribute('tabindex', '4'); + inp1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { + assert_equals(counter++, 3, 'Point 4: wrong focus navigation order'); + invoked[4] = true; + }), false); + invoked[4] = false; + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.setAttribute('tabindex', '4'); - inp2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 5, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('type', 'text'); + inp2.setAttribute('id', 'shInp2'); + inp2.setAttribute('value', 'Input 2'); + inp2.setAttribute('tabindex', '4'); + inp2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { + assert_equals(counter++, 5, 'Point 5: wrong focus navigation order'); + invoked[5] = true; + }), false); + invoked[5] = false; + d.body.appendChild(inp2); - var chb4 = d.createElement('input'); - chb4.setAttribute('type', 'checkbox'); - chb4.setAttribute('id', 'chb4'); - chb4.setAttribute('tabindex', '2'); - chb4.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 2, 'Point 6: wrong focus navigation order'); - invoked[6] = true; - }), false); - invoked[6] = false; - d.body.appendChild(chb4); + var chb4 = d.createElement('input'); + chb4.setAttribute('type', 'checkbox'); + chb4.setAttribute('id', 'chb4'); + chb4.setAttribute('tabindex', '2'); + chb4.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { + assert_equals(counter++, 2, 'Point 6: wrong focus navigation order'); + invoked[6] = true; + }), false); + invoked[6] = false; + d.body.appendChild(chb4); - chb1.focus(); + chb1.focus(); - //simulate TAB clicks - //Expected order: chb1, chb3, chb4, chb2, inp1, inp2 - fireKeyboardEvent(d, chb1, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, chb4, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); + //simulate TAB clicks + //Expected order: chb1, chb3, chb4, chb2, inp1, inp2 + fireKeyboardEvent(d, chb1, 'U+0009'); + fireKeyboardEvent(d, chb3, 'U+0009'); + fireKeyboardEvent(d, chb4, 'U+0009'); + fireKeyboardEvent(d, chb2, 'U+0009'); + fireKeyboardEvent(d, inp1, 'U+0009'); + fireKeyboardEvent(d, inp2, 'U+0009'); - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Point ' + i + ' event listener was not invoked'); - } - } + for (var i = 1; i < invoked.length; i++) { + if (!invoked[i]) { + assert_true(false, 'Point ' + i + ' event listener was not invoked'); + } + } - A_07_02_04_T02.done(); + A_07_02_04_T02.done(); })); @@ -244,90 +245,90 @@ var A_07_02_04_T03 = async_test('A_07_02_04_T03'); A_07_02_04_T03.step(unit(function (ctx) { - var counter = 0; + var counter = 0; - var invoked = []; + var invoked = []; - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('tabindex', '3'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 4, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); + var chb1 = d.createElement('input'); + chb1.setAttribute('type', 'checkbox'); + chb1.setAttribute('tabindex', '3'); + chb1.setAttribute('id', 'chb1'); + chb1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { + assert_equals(counter++, 4, 'Point 1: wrong focus navigation order'); + invoked[1] = true; + }), false); + invoked[1] = false; + d.body.appendChild(chb1); - var host = d.createElement('div'); - host.setAttribute('tabindex', '1'); - d.body.appendChild(host); - var s = host.createShadowRoot(); + var host = d.createElement('div'); + host.setAttribute('tabindex', '1'); + d.body.appendChild(host); + var s = host.createShadowRoot(); - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('tabindex', '2'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - s.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('type', 'text'); + inp1.setAttribute('id', 'shInp1'); + inp1.setAttribute('tabindex', '2'); + inp1.setAttribute('value', 'Input 1'); + inp1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { + assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); + invoked[2] = true; + }), false); + invoked[2] = false; + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('tabindex', '1'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 0, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - s.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('type', 'text'); + inp2.setAttribute('id', 'shInp2'); + inp2.setAttribute('tabindex', '1'); + inp2.setAttribute('value', 'Input 2'); + inp2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { + assert_equals(counter++, 0, 'Point 3: wrong focus navigation order'); + invoked[3] = true; + }), false); + invoked[3] = false; + s.appendChild(inp2); - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('tabindex', '3'); - chb2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 2, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - s.appendChild(chb2); + var chb2 = d.createElement('input'); + chb2.setAttribute('type', 'checkbox'); + chb2.setAttribute('id', 'chb2'); + chb2.setAttribute('tabindex', '3'); + chb2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { + assert_equals(counter++, 2, 'Point 4: wrong focus navigation order'); + invoked[4] = true; + }), false); + invoked[4] = false; + s.appendChild(chb2); - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('tabindex', '2'); - chb3.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 3, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(chb3); + var chb3 = d.createElement('input'); + chb3.setAttribute('type', 'checkbox'); + chb3.setAttribute('id', 'chb3'); + chb3.setAttribute('tabindex', '2'); + chb3.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { + assert_equals(counter++, 3, 'Point 5: wrong focus navigation order'); + invoked[5] = true; + }), false); + invoked[5] = false; + d.body.appendChild(chb3); - host.focus(); + host.focus(); - //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1 - fireKeyboardEvent(d, inp2, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, chb1, 'U+0009'); + //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1 + fireKeyboardEvent(d, inp2, 'U+0009'); + fireKeyboardEvent(d, inp1, 'U+0009'); + fireKeyboardEvent(d, chb2, 'U+0009'); + fireKeyboardEvent(d, chb3, 'U+0009'); + fireKeyboardEvent(d, chb1, 'U+0009'); - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } + for (var i = 1; i < invoked.length; i++) { + if (!invoked[i]) { + assert_true(false, 'Piont ' + i + ' event listener was not invoked'); + } + } - A_07_02_04_T03.done(); + A_07_02_04_T03.done(); })); @@ -336,90 +337,90 @@ var A_07_02_04_T04 = async_test('A_07_02_04_T04'); A_07_02_04_T04.step(unit(function (ctx) { - var counter = 0; + var counter = 0; - var invoked = []; + var invoked = []; - var d = newRenderedHTMLDocument(ctx); + var d = newRenderedHTMLDocument(ctx); - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('tabindex', '1'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); + var chb1 = d.createElement('input'); + chb1.setAttribute('type', 'checkbox'); + chb1.setAttribute('tabindex', '1'); + chb1.setAttribute('id', 'chb1'); + chb1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { + assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); + invoked[1] = true; + }), false); + invoked[1] = false; + d.body.appendChild(chb1); - var host = d.createElement('div'); - host.setAttribute('tabindex', '3'); - d.body.appendChild(host); - var s = host.createShadowRoot(); + var host = d.createElement('div'); + host.setAttribute('tabindex', '3'); + d.body.appendChild(host); + var s = host.createShadowRoot(); - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('tabindex', '2'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 3, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - s.appendChild(inp1); + var inp1 = d.createElement('input'); + inp1.setAttribute('type', 'text'); + inp1.setAttribute('id', 'shInp1'); + inp1.setAttribute('tabindex', '2'); + inp1.setAttribute('value', 'Input 1'); + inp1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { + assert_equals(counter++, 3, 'Point 2: wrong focus navigation order'); + invoked[2] = true; + }), false); + invoked[2] = false; + s.appendChild(inp1); - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('tabindex', '1'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - s.appendChild(inp2); + var inp2 = d.createElement('input'); + inp2.setAttribute('type', 'text'); + inp2.setAttribute('id', 'shInp2'); + inp2.setAttribute('tabindex', '1'); + inp2.setAttribute('value', 'Input 2'); + inp2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { + assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); + invoked[3] = true; + }), false); + invoked[3] = false; + s.appendChild(inp2); - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('tabindex', '3'); - chb2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 4, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - s.appendChild(chb2); + var chb2 = d.createElement('input'); + chb2.setAttribute('type', 'checkbox'); + chb2.setAttribute('id', 'chb2'); + chb2.setAttribute('tabindex', '3'); + chb2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { + assert_equals(counter++, 4, 'Point 4: wrong focus navigation order'); + invoked[4] = true; + }), false); + invoked[4] = false; + s.appendChild(chb2); - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('tabindex', '2'); - chb3.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 1, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(chb3); + var chb3 = d.createElement('input'); + chb3.setAttribute('type', 'checkbox'); + chb3.setAttribute('id', 'chb3'); + chb3.setAttribute('tabindex', '2'); + chb3.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { + assert_equals(counter++, 1, 'Point 5: wrong focus navigation order'); + invoked[5] = true; + }), false); + invoked[5] = false; + d.body.appendChild(chb3); - chb1.focus(); + chb1.focus(); - //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1 - fireKeyboardEvent(d, chb1, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); + //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1 + fireKeyboardEvent(d, chb1, 'U+0009'); + fireKeyboardEvent(d, chb3, 'U+0009'); + fireKeyboardEvent(d, inp2, 'U+0009'); + fireKeyboardEvent(d, inp1, 'U+0009'); + fireKeyboardEvent(d, chb2, 'U+0009'); - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } + for (var i = 1; i < invoked.length; i++) { + if (!invoked[i]) { + assert_true(false, 'Piont ' + i + ' event listener was not invoked'); + } + } - A_07_02_04_T04.done(); + A_07_02_04_T04.done(); })); diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html index 29c2b368f7c..d156338b4c2 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html @@ -16,62 +16,63 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html index c566ea6aa02..76ff0f5dd68 100644 --- a/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html +++ b/tests/wpt/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html @@ -16,62 +16,64 @@ policies and contribution forms [3]. - + +
diff --git a/tests/wpt/web-platform-tests/tools/.gitmodules b/tests/wpt/web-platform-tests/tools/.gitmodules index 39a77781529..12cee69142f 100644 --- a/tests/wpt/web-platform-tests/tools/.gitmodules +++ b/tests/wpt/web-platform-tests/tools/.gitmodules @@ -15,3 +15,6 @@ [submodule "pytest"] path = pytest url = https://github.com/pytest-dev/pytest.git +[submodule "webdriver"] + path = webdriver + url = https://github.com/w3c/wdclient.git diff --git a/tests/wpt/web-platform-tests/tools/localpaths.py b/tests/wpt/web-platform-tests/tools/localpaths.py index c88e4f4cee2..cf31977ec7d 100644 --- a/tests/wpt/web-platform-tests/tools/localpaths.py +++ b/tests/wpt/web-platform-tests/tools/localpaths.py @@ -9,4 +9,6 @@ sys.path.insert(0, os.path.join(repo_root, "tools", "six")) sys.path.insert(0, os.path.join(repo_root, "tools", "html5lib")) sys.path.insert(0, os.path.join(repo_root, "tools", "wptserve")) sys.path.insert(0, os.path.join(repo_root, "tools", "pywebsocket", "src")) +sys.path.insert(0, os.path.join(repo_root, "tools", "py")) sys.path.insert(0, os.path.join(repo_root, "tools", "pytest")) +sys.path.insert(0, os.path.join(repo_root, "tools", "webdriver")) diff --git a/tests/wpt/web-platform-tests/tools/py/.hgignore b/tests/wpt/web-platform-tests/tools/py/.hgignore new file mode 100644 index 00000000000..34976da5d15 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/.hgignore @@ -0,0 +1,29 @@ + +# Automatically generated by `hgimportsvn` +syntax:glob +.svn +.hgsvn + +# These lines are suggested according to the svn:ignore property +# Feel free to enable them by uncommenting them +syntax:glob +*.pyc +*.pyo +*.swp +*.html +*.class +*.orig +*~ + +doc/_build +build/ +dist/ +*.egg-info +issue/ +env/ +3rdparty/ +.tox +lib/ +bin/ +include/ +src/ diff --git a/tests/wpt/web-platform-tests/tools/py/.hgtags b/tests/wpt/web-platform-tests/tools/py/.hgtags new file mode 100644 index 00000000000..d45ebb5a237 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/.hgtags @@ -0,0 +1,67 @@ +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/AUTHORS b/tests/wpt/web-platform-tests/tools/py/AUTHORS new file mode 100644 index 00000000000..8c0cf9b71b1 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/AUTHORS @@ -0,0 +1,24 @@ +Holger Krekel, holger at merlinux eu +Benjamin Peterson, benjamin at python org +Ronny Pfannschmidt, Ronny.Pfannschmidt at gmx de +Guido Wesdorp, johnny at johnnydebris net +Samuele Pedroni, pedronis at openend se +Carl Friedrich Bolz, cfbolz at gmx de +Armin Rigo, arigo at tunes org +Maciek Fijalkowski, fijal at genesilico pl +Brian Dorsey, briandorsey at gmail com +Floris Bruynooghe, flub at devork be +merlinux GmbH, Germany, office at merlinux eu + +Contributors include:: + +Ross Lawley +Ralf Schmitt +Chris Lamb +Harald Armin Massa +Martijn Faassen +Ian Bicking +Jan Balster +Grig Gheorghiu +Bob Ippolito +Christian Tismer diff --git a/tests/wpt/web-platform-tests/tools/py/CHANGELOG b/tests/wpt/web-platform-tests/tools/py/CHANGELOG new file mode 100644 index 00000000000..712fc4c5389 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/CHANGELOG @@ -0,0 +1,1089 @@ +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/LICENSE b/tests/wpt/web-platform-tests/tools/py/LICENSE new file mode 100644 index 00000000000..31ecdfb1dbc --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/LICENSE @@ -0,0 +1,19 @@ + + 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/py/MANIFEST.in b/tests/wpt/web-platform-tests/tools/py/MANIFEST.in new file mode 100644 index 00000000000..31fb010b487 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/MANIFEST.in @@ -0,0 +1,9 @@ +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 new file mode 100644 index 00000000000..e327e937373 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/README.txt @@ -0,0 +1,21 @@ +.. 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/bench/localpath.py b/tests/wpt/web-platform-tests/tools/py/bench/localpath.py new file mode 100644 index 00000000000..ad4fbd8e2bf --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/bench/localpath.py @@ -0,0 +1,75 @@ + +import py +import timeit + +class Listdir: + numiter = 100000 + numentries = 100 + + def setup(self): + tmpdir = py.path.local.make_numbered_dir(self.__class__.__name__) + for i in range(self.numentries): + tmpdir.join(str(i)) + self.tmpdir = tmpdir + + def run(self): + return self.tmpdir.listdir() + +class Listdir_arg(Listdir): + numiter = 100000 + numentries = 100 + + def run(self): + return self.tmpdir.listdir("47") + +class Join_onearg(Listdir): + def run(self): + self.tmpdir.join("17") + self.tmpdir.join("18") + self.tmpdir.join("19") + +class Join_multi(Listdir): + def run(self): + self.tmpdir.join("a", "b") + self.tmpdir.join("a", "b", "c") + self.tmpdir.join("a", "b", "c", "d") + +class Check(Listdir): + def run(self): + self.tmpdir.check() + self.tmpdir.check() + self.tmpdir.check() + +class CheckDir(Listdir): + def run(self): + self.tmpdir.check(dir=1) + self.tmpdir.check(dir=1) + assert not self.tmpdir.check(dir=0) + +class CheckDir2(Listdir): + def run(self): + self.tmpdir.stat().isdir() + self.tmpdir.stat().isdir() + assert self.tmpdir.stat().isdir() + +class CheckFile(Listdir): + def run(self): + self.tmpdir.check(file=1) + assert not self.tmpdir.check(file=1) + assert self.tmpdir.check(file=0) + +if __name__ == "__main__": + import time + for cls in [Listdir, Listdir_arg, + Join_onearg, Join_multi, + Check, CheckDir, CheckDir2, CheckFile,]: + + inst = cls() + inst.setup() + now = time.time() + for i in xrange(cls.numiter): + inst.run() + elapsed = time.time() - now + print "%s: %d loops took %.2f seconds, per call %.6f" %( + cls.__name__, + cls.numiter, elapsed, elapsed / cls.numiter) diff --git a/tests/wpt/web-platform-tests/tools/py/conftest.py b/tests/wpt/web-platform-tests/tools/py/conftest.py new file mode 100644 index 00000000000..11c2d442504 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/conftest.py @@ -0,0 +1,71 @@ +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/Makefile b/tests/wpt/web-platform-tests/tools/py/doc/Makefile new file mode 100644 index 00000000000..0a0e89e01fe --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/Makefile @@ -0,0 +1,133 @@ +# 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) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +help: + @echo "Please use \`make ' where 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 " 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)/* + +install: clean html + rsync -avz _build/html/ code:www-pylib/ + +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/py.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/py.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/py" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/py" + @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." diff --git a/tests/wpt/web-platform-tests/tools/py/doc/_templates/layout.html b/tests/wpt/web-platform-tests/tools/py/doc/_templates/layout.html new file mode 100644 index 00000000000..683863aa460 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/_templates/layout.html @@ -0,0 +1,18 @@ +{% extends "!layout.html" %} + +{% block footer %} +{{ super() }} + +{% endblock %} diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.0.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.0.txt new file mode 100644 index 00000000000..07109313543 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.0.txt @@ -0,0 +1,7 @@ +py lib 1.0.0: XXX +====================================================================== + +Welcome to the 1.0.0 py lib release - a library aiming to +support agile and test-driven python development on various levels. + +XXX diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.2.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.2.txt new file mode 100644 index 00000000000..bc2d2ef2908 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.2.txt @@ -0,0 +1,27 @@ +py lib 0.9.2: bugfix release +============================= + +Welcome to the 0.9.2 py lib and py.test release - +mainly fixing Windows issues, providing better +packaging and integration with setuptools. + +Here is a quick summary of what the py lib provides: + +* py.test: cross-project testing tool with many advanced features +* py.execnet: ad-hoc code distribution to SSH, Socket and local sub processes +* py.magic.greenlet: micro-threads on standard CPython ("stackless-light") +* py.path: path abstractions over local and subversion files +* rich documentation of py's exported API +* tested against Linux, Win32, OSX, works on python 2.3-2.6 + +See here for more information: + +Pypi pages: http://pypi.python.org/pypi/py/ + +Download/Install: http://codespeak.net/py/0.9.2/download.html + +Documentation/API: http://codespeak.net/py/0.9.2/index.html + +best and have fun, + +holger krekel diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.0.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.0.txt new file mode 100644 index 00000000000..7024255a195 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.0.txt @@ -0,0 +1,63 @@ + +pylib 1.0.0 released: testing-with-python innovations continue +-------------------------------------------------------------------- + +Took a few betas but finally i uploaded a `1.0.0 py lib release`_, +featuring the mature and powerful py.test tool and "execnet-style" +*elastic* distributed programming. With the new release, there are +many new advanced automated testing features - here is a quick summary: + +* funcargs_ - pythonic zero-boilerplate fixtures for Python test functions : + + - totally separates test code, test configuration and test setup + - ideal for integration and functional tests + - allows for flexible and natural test parametrization schemes + +* new `plugin architecture`_, allowing easy-to-write project-specific and cross-project single-file plugins. The most notable new external plugin is `oejskit`_ which naturally enables **running and reporting of javascript-unittests in real-life browsers**. + +* many new features done in easy-to-improve `default plugins`_, highlights: + + * xfail: mark tests as "expected to fail" and report separately. + * pastebin: automatically send tracebacks to pocoo paste service + * capture: flexibly capture stdout/stderr of subprocesses, per-test ... + * monkeypatch: safely monkeypatch modules/classes from within tests + * unittest: run and integrate traditional unittest.py tests + * figleaf: generate html coverage reports with the figleaf module + * resultlog: generate buildbot-friendly reporting output + * ... + +* `distributed testing`_ and `elastic distributed execution`_: + + - new unified "TX" URL scheme for specifying remote processes + - new distribution modes "--dist=each" and "--dist=load" + - new sync/async ways to handle 1:N communication + - improved documentation + +The py lib continues to offer most of the functionality used by +the testing tool in `independent namespaces`_. + +Some non-test related code, notably greenlets/co-routines and +api-generation now live as their own projects which simplifies the +installation procedure because no C-Extensions are required anymore. + +The whole package should work well with Linux, Win32 and OSX, on Python +2.3, 2.4, 2.5 and 2.6. (Expect Python3 compatibility soon!) + +For more info, see the py.test and py lib documentation: + + http://pytest.org + + http://pylib.org + +have fun, +holger + +.. _`independent namespaces`: http://pylib.org +.. _`funcargs`: http://codespeak.net/py/dist/test/funcargs.html +.. _`plugin architecture`: http://codespeak.net/py/dist/test/extend.html +.. _`default plugins`: http://codespeak.net/py/dist/test/plugin/index.html +.. _`distributed testing`: http://codespeak.net/py/dist/test/dist.html +.. _`elastic distributed execution`: http://codespeak.net/py/dist/execnet.html +.. _`1.0.0 py lib release`: http://pypi.python.org/pypi/py +.. _`oejskit`: http://codespeak.net/py/dist/test/plugin/oejskit.html + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.1.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.1.txt new file mode 100644 index 00000000000..0c9f8760bdb --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.1.txt @@ -0,0 +1,48 @@ +1.0.1: improved reporting, nose/unittest.py support, bug fixes +----------------------------------------------------------------------- + +This is a bugfix release of pylib/py.test also coming with: + +* improved documentation, improved navigation +* test failure reporting improvements +* support for directly running existing nose/unittest.py style tests + +visit here for more info, including quickstart and tutorials: + + http://pytest.org and http://pylib.org + + +Changelog 1.0.0 to 1.0.1 +------------------------ + +* added a default 'pytest_nose' plugin which handles nose.SkipTest, + nose-style function/method/generator setup/teardown and + tries to report functions correctly. + +* improved documentation, better navigation: see http://pytest.org + +* 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. + +* unicode fixes: capturing and unicode writes to sys.stdout + (through e.g a print statement) now work within tests, + they are encoded as "utf8" by default, also terminalwriting + was adapted and somewhat unified between windows and linux + +* 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 diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.2.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.2.txt new file mode 100644 index 00000000000..23546195353 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.2.txt @@ -0,0 +1,5 @@ +1.0.2: packaging fixes +----------------------------------------------------------------------- + +this release is purely a release for fixing packaging issues. + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.0.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.0.txt new file mode 100644 index 00000000000..0441c3215eb --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.0.txt @@ -0,0 +1,115 @@ +py.test/pylib 1.1.0: Python3, Jython, advanced skipping, cleanups ... +-------------------------------------------------------------------------------- + +Features: + +* compatible to Python3 (single py2/py3 source), `easy to install`_ +* conditional skipping_: skip/xfail based on platform/dependencies +* generalized marking_: mark tests one a whole-class or whole-module basis + +Fixes: + +* code reduction and "de-magification" (e.g. 23 KLoc -> 11 KLOC) +* distribute testing requires the now separately released execnet_ package +* funcarg-setup/caching, "same-name" test modules now cause an exlicit error +* de-cluttered reporting options, --report for skipped/xfail details + +Compatibilities + +1.1.0 should allow running test code that already worked well with 1.0.2 +plus some more due to improved unittest/nose compatibility. + +More information: http://pytest.org + +thanks and have fun, + +holger (http://twitter.com/hpk42) + +.. _execnet: http://codespeak.net/execnet +.. _`easy to install`: ../install.html +.. _marking: ../test/plugin/mark.html +.. _skipping: ../test/plugin/skipping.html + + +Changelog 1.0.2 -> 1.1.0 +----------------------------------------------------------------------- + +* 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 diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.1.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.1.txt new file mode 100644 index 00000000000..83e6a1fd8d9 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.1.txt @@ -0,0 +1,48 @@ +py.test/pylib 1.1.1: bugfix release, setuptools plugin registration +-------------------------------------------------------------------------------- + +This is a compatibility fixing release of pylib/py.test to work +better with previous 1.0.x test code bases. It also contains fixes +and changes to work with `execnet>=1.0.0`_ to provide distributed +testing and looponfailing testing modes. py-1.1.1 also introduces +a new mechanism for registering plugins via setuptools. + +What is pylib/py.test? +----------------------- + +py.test is an advanced automated testing tool working with +Python2, Python3 and Jython versions on all major operating +systems. It has an extensive plugin architecture and can run many +existing common Python test suites without modification. Moreover, +it offers some unique features not found in other +testing tools. See http://pytest.org for more info. + +The pylib also contains a localpath and svnpath implementation +and some developer-oriented command line tools. See +http://pylib.org for more info. + +thanks to all who helped and gave feedback, +have fun, + +holger (http://twitter.com/hpk42) + +.. _`execnet>=1.0.0`: http://codespeak.net/execnet + +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 diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.0.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.0.txt new file mode 100644 index 00000000000..4f6a5614476 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.0.txt @@ -0,0 +1,116 @@ +py.test/pylib 1.2.0: junitxml, standalone test scripts, pluginization +-------------------------------------------------------------------------------- + +py.test is an advanced automated testing tool working with +Python2, Python3 and Jython versions on all major operating +systems. It has a simple plugin architecture and can run many +existing common Python test suites without modification. It offers +some unique features not found in other testing tools. +See http://pytest.org for more info. + +py.test 1.2.0 brings many bug fixes and interesting new abilities: + +* --junitxml=path will create an XML file for use with CI processing +* --genscript=path creates a standalone py.test-equivalent test-script +* --ignore=path prevents collection of anything below that path +* --confcutdir=path only lookup conftest.py test configs below that path +* a 'pytest_report_header' hook to add info to the terminal report header +* a 'pytestconfig' function argument gives direct access to option values +* 'pytest_generate_tests' can now be put into a class as well +* on CPython py.test additionally installs as "py.test-VERSION", on + Jython as py.test-jython and on PyPy as py.test-pypy-XYZ + +Apart from many bug fixes 1.2.0 also has better pluginization: +Distributed testing and looponfailing testing now live in the +separately installable 'pytest-xdist' plugin. The same is true for +'pytest-figleaf' for doing coverage reporting. Those two plugins +can serve well now as blue prints for doing your own. + +thanks to all who helped and gave feedback, +have fun, + +holger krekel, January 2010 + +Changes between 1.2.0 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 + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.1.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.1.txt new file mode 100644 index 00000000000..5bf8ba22dc6 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.1.txt @@ -0,0 +1,66 @@ +py.test/pylib 1.2.1: little fixes and improvements +-------------------------------------------------------------------------------- + +py.test is an advanced automated testing tool working with +Python2, Python3 and Jython versions on all major operating +systems. It has a simple plugin architecture and can run many +existing common Python test suites without modification. It offers +some unique features not found in other testing tools. +See http://pytest.org for more info. + +py.test 1.2.1 brings bug fixes and some new options and abilities triggered +by user feedback: + +* --funcargs [testpath] will show available builtin- and project funcargs. +* display a short and concise traceback if funcarg lookup fails. +* early-load "conftest.py" files in non-dot first-level sub directories. +* --tb=line will print a single line for each failing test (issue67) +* py.cleanup has a number of new options, cleanups up setup.py related files +* fix issue78: always call python-level teardown functions even if the + according setup failed. + +For more detailed information see the changelog below. + +cheers and have fun, + +holger + + +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 diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.0.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.0.txt new file mode 100644 index 00000000000..cf97db0367a --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.0.txt @@ -0,0 +1,580 @@ +py.test/pylib 1.3.0: new options, per-plugin hooks, fixes ... +=========================================================================== + +The 1.3.0 release introduces new options, bug fixes and improved compatibility +with Python3 and Jython-2.5.1 on Windows. If you already use py-1.2 chances +are you can use py-1.3.0. See the below CHANGELOG for more details and +http://pylib.org/install.html for installation instructions. + +py.test is an advanced automated testing tool working with Python2, +Python3, Jython and PyPy versions on all major operating systems. It +offers a no-boilerplate testing approach and has inspired other testing +tools and enhancements in the standard Python library for more than five +years. It has a simple and extensive plugin architecture, configurable +reporting and provides unique ways to make it fit to your testing +process and needs. + +See http://pytest.org for more info. + +cheers and have fun, + +holger krekel + +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 collection 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 ignores xfail markers to show + you the underlying traceback. + +- 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/doc/announce/release-1.3.1.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.1.txt new file mode 100644 index 00000000000..471de408a10 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.1.txt @@ -0,0 +1,104 @@ +py.test/pylib 1.3.1: new py.test.xfail, --maxfail, better reporting +=========================================================================== + +The pylib/py.test 1.3.1 release brings: + +- the new imperative ``py.test.xfail()`` helper in order to have a test or + setup function result in an "expected failure" +- a new option ``--maxfail=NUM`` to stop the test run after some failures +- markers/decorators are now applicable to test classes (>=Python2.6) +- improved reporting, shorter tracebacks in several cases +- some simplified internals, more compatibility with Jython and PyPy +- bug fixes and various refinements + +See the below CHANGELOG entry below for more details and +http://pylib.org/install.html for installation instructions. + +If you used older versions of py.test you should be able to upgrade +to 1.3.1 without changes to your test source code. + +py.test is an automated testing tool working with Python2, +Python3, Jython and PyPy versions on all major operating systems. It +offers a no-boilerplate testing approach and has inspired other testing +tools and enhancements in the standard Python library for more than five +years. It has a simple and extensive plugin architecture, configurable +reporting and provides unique ways to make it fit to your testing +process and needs. + +See http://pytest.org for more info. + +cheers and have fun, + +holger krekel + +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) + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.2.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.2.txt new file mode 100644 index 00000000000..599dfbed755 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.2.txt @@ -0,0 +1,720 @@ +py.test/pylib 1.3.2: API and reporting refinements, many fixes +=========================================================================== + +The pylib/py.test 1.3.2 release brings many bug fixes and some new +features. It was refined for and tested against the recently released +Python2.7 and remains compatibile to the usual armada of interpreters +(Python2.4 through to Python3.1.2, Jython and PyPy). Note that for using +distributed testing features you'll need to upgrade to the jointly released +pytest-xdist-1.4 because of some internal refactorings. + +See http://pytest.org for general documentation and below for +a detailed CHANGELOG. + +cheers & particular thanks to Benjamin Peterson, Ronny Pfannschmidt +and all issue and patch contributors, + +holger krekel + +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/doc/announce/release-1.3.3.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.3.txt new file mode 100644 index 00000000000..c62cb859053 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.3.txt @@ -0,0 +1,26 @@ +py.test/pylib 1.3.3: windows and other fixes +=========================================================================== + +pylib/py.test 1.3.3 is a minor bugfix release featuring some improvements +and fixes. See changelog_ for full history. + +have fun, +holger krekel + +.. _changelog: ../changelog.html + +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 + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.4.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.4.txt new file mode 100644 index 00000000000..c156c8bdb33 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.4.txt @@ -0,0 +1,22 @@ +py.test/pylib 1.3.4: fixes and new native traceback option +=========================================================================== + +pylib/py.test 1.3.4 is a minor maintenance release mostly containing bug fixes +and a new "--tb=native" traceback option to show "normal" Python standard +tracebacks instead of the py.test enhanced tracebacks. See below for more +change info and http://pytest.org for more general information on features +and configuration of the testing tool. + +Thanks to the issue reporters and generally to Ronny Pfannschmidt for help. + +cheers, +holger krekel + +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 diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.0.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.0.txt new file mode 100644 index 00000000000..6f9a7714d9f --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.0.txt @@ -0,0 +1,47 @@ + +.. _`release-1.4.0`: + +py-1.4.0: cross-python lib for path, code, io, ... manipulations +=========================================================================== + +"py" is a small library comprising APIs for filesystem and svn path +manipulations, dynamic code construction and introspection, a Py2/Py3 +compatibility namespace ("py.builtin"), IO capturing, terminal colored printing +(on windows and linux), ini-file parsing and a lazy import mechanism. +It runs unmodified on all Python interpreters compatible to Python2.4 up +until Python 3.2. The general goal with "py" is to provide stable APIs +for some common tasks that are continously tested against many Python +interpreters and thus also to help transition. Here are some docs: + + http://pylib.org + +NOTE: The prior py-1.3.X versions contained "py.test" which now comes +as its own separate "pytest" distribution and was just released +as "pytest-2.0.0", see here for the revamped docs: + + http://pytest.org + +And "py.cleanup|py.lookup|py.countloc" etc. helpers are now part of +the pycmd distribution, see http://pypi.python.org/pypi/pycmd + +This makes "py-1.4.0" a simple library which does not install +any command line utilities anymore. + +cheers, +holger + +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 diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.1.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.1.txt new file mode 100644 index 00000000000..a5aa76b1438 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.1.txt @@ -0,0 +1,47 @@ + +.. _`release-1.4.1`: + +py-1.4.1: cross-python lib for fs path, code, io, ... manipulations +=========================================================================== + +This is a bug fix release of the "py" lib, see below for detailed changes. +The py lib is a small library comprising APIs for filesystem and svn path +manipulations, dynamic code construction and introspection, a Py2/Py3 +compatibility namespace ("py.builtin"), IO capturing, terminal colored printing +(on windows and linux), ini-file parsing and a lazy import mechanism. +It runs unmodified on all Python interpreters compatible to Python2.4 up +until Python 3.2, PyPy and Jython. The general goal with "py" is to +provide stable APIs for some common tasks that are continously tested +against many Python interpreters and thus also to help transition. Here +are some docs: + + http://pylib.org + +NOTE: The prior py-1.3.X versions contained "py.test" which since py-1.4.0 +comes as its own separate "pytest" distribution, see: + + http://pytest.org + +Also, the "py.cleanup|py.lookup|py.countloc" helpers are now part of +the pycmd distribution, see http://pypi.python.org/pypi/pycmd + + +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 star-imports, + leading to misrepresentation of import-errors in test modules + +- fix ``py.error.*`` attribute pypy access + +- allow path.samefile(arg) to succeed when arg is a relative filename + +- fix (pytest-) issue20 path.samefile(relpath) works as expected now diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/releases.txt b/tests/wpt/web-platform-tests/tools/py/doc/announce/releases.txt new file mode 100644 index 00000000000..309c29bac5d --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/announce/releases.txt @@ -0,0 +1,16 @@ +============= +Release notes +============= + +Contents: + +.. toctree:: + :maxdepth: 2 + +.. include: release-1.1.0 +.. include: release-1.0.2 + + release-1.0.1 + release-1.0.0 + release-0.9.2 + release-0.9.0 diff --git a/tests/wpt/web-platform-tests/tools/py/doc/changelog.txt b/tests/wpt/web-platform-tests/tools/py/doc/changelog.txt new file mode 100644 index 00000000000..237daca3548 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/changelog.txt @@ -0,0 +1,3 @@ +.. _`changelog`: + +.. include:: ../CHANGELOG diff --git a/tests/wpt/web-platform-tests/tools/py/doc/code.txt b/tests/wpt/web-platform-tests/tools/py/doc/code.txt new file mode 100644 index 00000000000..bdd8691da03 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/code.txt @@ -0,0 +1,150 @@ +================================================================================ +py.code: higher level python code and introspection objects +================================================================================ + +``py.code`` provides higher level APIs and objects for Code, Frame, Traceback, +ExceptionInfo and source code construction. The ``py.code`` library +tries to simplify accessing the code objects as well as creating them. +There is a small set of interfaces a user needs to deal with, all nicely +bundled together, and with a rich set of 'Pythonic' functionality. + +Contents of the library +======================= + +Every object in the ``py.code`` library wraps a code Python object related +to code objects, source code, frames and tracebacks: the ``py.code.Code`` +class wraps code objects, ``py.code.Source`` source snippets, +``py.code.Traceback` exception tracebacks, ``py.code.Frame`` frame +objects (as found in e.g. tracebacks) and ``py.code.ExceptionInfo`` the +tuple provided by sys.exc_info() (containing exception and traceback +information when an exception occurs). Also in the library is a helper function +``py.code.compile()`` that provides the same functionality as Python's +built-in 'compile()' function, but returns a wrapped code object. + +The wrappers +============ + +``py.code.Code`` +------------------- + +Code objects are instantiated with a code object or a callable as argument, +and provide functionality to compare themselves with other Code objects, get to +the source file or its contents, create new Code objects from scratch, etc. + +A quick example:: + + >>> import py + >>> c = py.code.Code(py.path.local.read) + >>> c.path.basename + 'common.py' + >>> isinstance(c.source(), py.code.Source) + True + >>> str(c.source()).split('\n')[0] + "def read(self, mode='r'):" + +.. autoclass:: py.code.Code + :members: + :inherited-members: + + +``py.code.Source`` +--------------------- + +Source objects wrap snippets of Python source code, providing a simple yet +powerful interface to read, deindent, slice, compare, compile and manipulate +them, things that are not so easy in core Python. + +Example:: + + >>> s = py.code.Source("""\ + ... def foo(): + ... print "foo" + ... """) + >>> str(s).startswith('def') # automatic de-indentation! + True + >>> s.isparseable() + True + >>> sub = s.getstatement(1) # get the statement starting at line 1 + >>> str(sub).strip() # XXX why is the strip() required?!? + 'print "foo"' + +.. autoclass:: py.code.Source + :members: + + +``py.code.Traceback`` +------------------------ + +Tracebacks are usually not very easy to examine, you need to access certain +somewhat hidden attributes of the traceback's items (resulting in expressions +such as 'fname = tb.tb_next.tb_frame.f_code.co_filename'). The Traceback +interface (and its TracebackItem children) tries to improve this. + +Example:: + + >>> import sys + >>> try: + ... py.path.local(100) # illegal argument + ... except: + ... exc, e, tb = sys.exc_info() + >>> t = py.code.Traceback(tb) + >>> first = t[1] # get the second entry (first is in this doc) + >>> first.path.basename # second is in py/path/local.py + 'local.py' + >>> isinstance(first.statement, py.code.Source) + True + >>> str(first.statement).strip().startswith('raise ValueError') + True + +.. autoclass:: py.code.Traceback + :members: + +``py.code.Frame`` +-------------------- + +Frame wrappers are used in ``py.code.Traceback`` items, and will usually not +directly be instantiated. They provide some nice methods to evaluate code +'inside' the frame (using the frame's local variables), get to the underlying +code (frames have a code attribute that points to a ``py.code.Code`` object) +and examine the arguments. + +Example (using the 'first' TracebackItem instance created above):: + + >>> frame = first.frame + >>> isinstance(frame.code, py.code.Code) + True + >>> isinstance(frame.eval('self'), py.path.local) + True + >>> [namevalue[0] for namevalue in frame.getargs()] + ['cls', 'path'] + +.. autoclass:: py.code.Frame + :members: + +``py.code.ExceptionInfo`` +---------------------------- + +A wrapper around the tuple returned by sys.exc_info() (will call sys.exc_info() +itself if the tuple is not provided as an argument), provides some handy +attributes to easily access the traceback and exception string. + +Example:: + + >>> import sys + >>> try: + ... foobar() + ... except: + ... excinfo = py.code.ExceptionInfo() + >>> excinfo.typename + 'NameError' + >>> isinstance(excinfo.traceback, py.code.Traceback) + True + >>> excinfo.exconly() + "NameError: name 'foobar' is not defined" + +.. autoclass:: py.code.ExceptionInfo + :members: + +.. autoclass:: py.code.Traceback + :members: + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/conf.py b/tests/wpt/web-platform-tests/tools/py/doc/conf.py new file mode 100644 index 00000000000..de4cbf8a46f --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/conf.py @@ -0,0 +1,263 @@ +# -*- coding: utf-8 -*- +# +# py documentation build configuration file, created by +# sphinx-quickstart on Thu Oct 21 08:30:10 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. + +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.doctest', '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 = '.txt' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'py' +copyright = u'2010, holger krekel et. al.' + +# 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. +# The full version, including alpha/beta/rc tags. +import py +release = py.__version__ +version = ".".join(release.split(".")[:2]) + +# 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 = 'default' + +# 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 +# " v 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 = ['_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 = {} + +# 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 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 = 'py' + + +# -- 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 = [ + ('index', 'py.tex', u'py Documentation', + u'holger krekel et. al.', '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 + +# 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 = 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', 'py', u'py Documentation', + [u'holger krekel et. al.'], 1) +] + +autodoc_member_order = "bysource" +autodoc_default_flags = "inherited-members" + +# -- Options for Epub output --------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = u'py' +epub_author = u'holger krekel et. al.' +epub_publisher = u'holger krekel et. al.' +epub_copyright = u'2010, holger krekel et. al.' + +# 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 + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/tests/wpt/web-platform-tests/tools/py/doc/download.html b/tests/wpt/web-platform-tests/tools/py/doc/download.html new file mode 100644 index 00000000000..5f4c466402d --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/download.html @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/example/genhtml.py b/tests/wpt/web-platform-tests/tools/py/doc/example/genhtml.py new file mode 100644 index 00000000000..b5c8f525b62 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/example/genhtml.py @@ -0,0 +1,13 @@ +from py.xml import html + +paras = "First Para", "Second para" + +doc = html.html( + html.head( + html.meta(name="Content-Type", value="text/html; charset=latin1")), + html.body( + [html.p(p) for p in paras])) + +print unicode(doc).encode('latin1') + + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/example/genhtmlcss.py b/tests/wpt/web-platform-tests/tools/py/doc/example/genhtmlcss.py new file mode 100644 index 00000000000..3e6d0af5454 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/example/genhtmlcss.py @@ -0,0 +1,23 @@ +import py +html = py.xml.html + +class my(html): + "a custom style" + class body(html.body): + style = html.Style(font_size = "120%") + + class h2(html.h2): + style = html.Style(background = "grey") + + class p(html.p): + style = html.Style(font_weight="bold") + +doc = my.html( + my.head(), + my.body( + my.h2("hello world"), + my.p("bold as bold can") + ) +) + +print doc.unicode(indent=2) diff --git a/tests/wpt/web-platform-tests/tools/py/doc/example/genxml.py b/tests/wpt/web-platform-tests/tools/py/doc/example/genxml.py new file mode 100644 index 00000000000..5f754e8897b --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/example/genxml.py @@ -0,0 +1,17 @@ + +import py +class ns(py.xml.Namespace): + pass + +doc = ns.books( + ns.book( + ns.author("May Day"), + ns.title("python for java programmers"),), + ns.book( + ns.author("why", class_="somecssclass"), + ns.title("Java for Python programmers"),), + publisher="N.N", + ) +print doc.unicode(indent=2).encode('utf8') + + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/faq.txt b/tests/wpt/web-platform-tests/tools/py/doc/faq.txt new file mode 100644 index 00000000000..52cb4b3fbd3 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/faq.txt @@ -0,0 +1,172 @@ +================================== +Frequently Asked Questions +================================== + +.. contents:: + :local: + :depth: 2 + + +On naming, nosetests, licensing and magic +=========================================== + +Why the ``py`` naming? Why not ``pytest``? +---------------------------------------------------- + +This mostly has historic reasons - the aim is +to get away from the somewhat questionable 'py' name +at some point. These days (2010) the 'py' library +almost completely comprises APIs that are used +by the ``py.test`` tool. There also are some +other uses, e.g. of the ``py.path.local()`` and +other path implementations. So it requires some +work to factor them out and do the shift. + +Why the ``py.test`` naming? +------------------------------------ + +because of TAB-completion under Bash/Shells. If you hit +``py.`` you'll get a list of available development +tools that all share the ``py.`` prefix. Another motivation +was to unify the package ("py.test") and tool filename. + +What's py.test's relation to ``nosetests``? +--------------------------------------------- + +py.test and nose_ share basic philosophy when it comes +to running Python tests. In fact, +with py.test-1.1.0 it is ever easier to run many test suites +that currently work with ``nosetests``. nose_ was created +as a clone of ``py.test`` when py.test was in the ``0.8`` release +cycle so some of the newer features_ introduced with py.test-1.0 +and py.test-1.1 have no counterpart in nose_. + +.. _nose: http://somethingaboutorange.com/mrl/projects/nose/0.11.1/ +.. _features: test/features.html +.. _apipkg: http://pypi.python.org/pypi/apipkg + + +What's this "magic" with py.test? +---------------------------------------- + +issues where people have used the term "magic" in the past: + +* `py/__init__.py`_ uses the apipkg_ mechanism for lazy-importing + and full control on what API you get when importing "import py". + +* when an ``assert`` statement fails, py.test re-interprets the expression + to show intermediate values if a test fails. If your expression + has side effects the intermediate values may not be the same, obfuscating + the initial error (this is also explained at the command line if it happens). + ``py.test --no-assert`` turns off assert re-intepretation. + Sidenote: it is good practise to avoid asserts with side effects. + + +.. _`py namespaces`: index.html +.. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py + +Where does my ``py.test`` come/import from? +---------------------------------------------- + +You can issue:: + + py.test --version + +which tells you both version and import location of the tool. + + +function arguments, parametrized tests and setup +==================================================== + +.. _funcargs: test/funcargs.html + +Is using funcarg- versus xUnit-based setup a style question? +--------------------------------------------------------------- + +It depends. For simple applications or for people experienced +with nose_ or unittest-style test setup using `xUnit style setup`_ +make some sense. For larger test suites, parametrized testing +or setup of complex test resources using funcargs_ is recommended. +Moreover, funcargs are ideal for writing advanced test support +code (like e.g. the monkeypatch_, the tmpdir_ or capture_ funcargs) +because the support code can register setup/teardown functions +in a managed class/module/function scope. + +.. _monkeypatch: test/plugin/monkeypatch.html +.. _tmpdir: test/plugin/tmpdir.html +.. _capture: test/plugin/capture.html +.. _`xUnit style setup`: test/xunit_setup.html +.. _`pytest_nose`: test/plugin/nose.html + +.. _`why pytest_pyfuncarg__ methods?`: + +Why the ``pytest_funcarg__*`` name for funcarg factories? +--------------------------------------------------------------- + +When experimenting with funcargs an explicit registration mechanism +was considered. But lacking a good use case for this indirection and +flexibility we decided to go for `Convention over Configuration`_ and +allow to directly specify the factory. Besides removing the need +for an indirection it allows to "grep" for ``pytest_funcarg__MYARG`` +and will safely find all factory functions for the ``MYARG`` function +argument. It helps to alleviate the de-coupling of function +argument usage and creation. + +.. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration + +Can I yield multiple values from a factory function? +----------------------------------------------------- + +There are two conceptual reasons why yielding from a factory function +is not possible: + +* 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. + +* 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. + +Use the `pytest_generate_tests`_ hook to solve both issues +and implement the `parametrization scheme of your choice`_. + +.. _`pytest_generate_tests`: test/funcargs.html#parametrizing-tests +.. _`parametrization scheme of your choice`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/ + + +py.test interaction with other packages +=============================================== + +Issues with py.test, multiprocess and setuptools? +------------------------------------------------------------ + +On windows the multiprocess package will instantiate sub processes +by pickling and thus implicitely re-import a lot of local modules. +Unfortuantely, 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. +There are these workarounds: + +* `install Distribute`_ as a drop-in replacement for setuptools + and install py.test + +* `directly use a checkout`_ which avoids all setuptools/Distribute + installation + +If those options are not available to you, you may also manually +fix the script that is created by setuptools by inserting an +``if __name__ == '__main__'``. Or you can create a "pytest.py" +script with this content and invoke that with the python version:: + + import py + if __name__ == '__main__': + py.cmdline.pytest() + +.. _`directly use a checkout`: install.html#directly-use-a-checkout + +.. _`install distribute`: http://pypi.python.org/pypi/distribute#installation-instructions + + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/img/pylib.png b/tests/wpt/web-platform-tests/tools/py/doc/img/pylib.png new file mode 100644 index 00000000000..2e10d438866 Binary files /dev/null and b/tests/wpt/web-platform-tests/tools/py/doc/img/pylib.png differ diff --git a/tests/wpt/web-platform-tests/tools/py/doc/index.txt b/tests/wpt/web-platform-tests/tools/py/doc/index.txt new file mode 100644 index 00000000000..7eb5c63905e --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/index.txt @@ -0,0 +1,43 @@ +.. 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 ` 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 new file mode 100644 index 00000000000..d0e981def45 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/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.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/io.txt b/tests/wpt/web-platform-tests/tools/py/doc/io.txt new file mode 100644 index 00000000000..c11308a6d28 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/io.txt @@ -0,0 +1,59 @@ +======= +py.io +======= + + +The 'py' lib provides helper classes for capturing IO during +execution of a program. + +IO Capturing examples +=============================================== + +``py.io.StdCapture`` +--------------------------- + +Basic Example:: + + >>> import py + >>> capture = py.io.StdCapture() + >>> print "hello" + >>> out,err = capture.reset() + >>> out.strip() == "hello" + True + +For calling functions you may use a shortcut:: + + >>> import py + >>> def f(): print "hello" + >>> res, out, err = py.io.StdCapture.call(f) + >>> out.strip() == "hello" + True + +``py.io.StdCaptureFD`` +--------------------------- + +If you also want to capture writes to the stdout/stderr +filedescriptors you may invoke:: + + >>> import py, sys + >>> capture = py.io.StdCaptureFD(out=False, in_=False) + >>> sys.stderr.write("world") + >>> out,err = capture.reset() + >>> err + 'world' + +py.io object reference +============================ + +.. autoclass:: py.io.StdCaptureFD + :members: + :inherited-members: + +.. autoclass:: py.io.StdCapture + :members: + :inherited-members: + +.. autoclass:: py.io.TerminalWriter + :members: + :inherited-members: + diff --git a/tests/wpt/web-platform-tests/tools/py/doc/links.inc b/tests/wpt/web-platform-tests/tools/py/doc/links.inc new file mode 100644 index 00000000000..9bcfe5cf85c --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/links.inc @@ -0,0 +1,16 @@ + +.. _`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: http://somethingaboutorange.com/mrl/projects/nose/ +.. _pytest: http://pypi.python.org/pypi/pytest +.. _mercurial: http://mercurial.selenic.com/wiki/ +.. _`setuptools`: http://pypi.python.org/pypi/setuptools +.. _`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/ diff --git a/tests/wpt/web-platform-tests/tools/py/doc/log.txt b/tests/wpt/web-platform-tests/tools/py/doc/log.txt new file mode 100644 index 00000000000..ca60fcac250 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/log.txt @@ -0,0 +1,208 @@ +.. role:: code(literal) +.. role:: file(literal) + +.. XXX figure out how the code literals should be dealt with in sphinx. There is probably something builtin. + +======================================== +py.log documentation and musings +======================================== + + +Foreword +======== + +This document is an attempt to briefly state the actual specification of the +:code:`py.log` module. It was written by Francois Pinard and also contains +some ideas for enhancing the py.log facilities. + +NOTE that :code:`py.log` is subject to refactorings, it may change with +the next release. + +This document is meant to trigger or facilitate discussions. It shamelessly +steals from the `Agile Testing`__ comments, and from other sources as well, +without really trying to sort them out. + +__ http://agiletesting.blogspot.com/2005/06/keyword-based-logging-with-py-library.html + + +Logging organisation +==================== + +The :code:`py.log` module aims a niche comparable to the one of the +`logging module`__ found within the standard Python distributions, yet +with much simpler paradigms for configuration and usage. + +__ http://www.python.org/doc/2.4.2/lib/module-logging.html + +Holger Krekel, the main :code:`py` library developer, introduced +the idea of keyword-based logging and the idea of logging *producers* and +*consumers*. A log producer is an object used by the application code +to send messages to various log consumers. When you create a log +producer, you define a set of keywords that are then used to both route +the logging messages to consumers, and to prefix those messages. + +In fact, each log producer has a few keywords associated with it for +identification purposes. These keywords form a tuple of strings, and +may be used to later retrieve a particular log producer. + +A log producer may (or may not) be associated with a log consumer, meant +to handle log messages in particular ways. The log consumers can be +``STDOUT``, ``STDERR``, log files, syslog, the Windows Event Log, user +defined functions, etc. (Yet, logging to syslog or to the Windows Event +Log is only future plans for now). A log producer has never more than +one consumer at a given time, but it is possible to dynamically switch +a producer to use another consumer. On the other hand, a single log +consumer may be associated with many producers. + +Note that creating and associating a producer and a consumer is done +automatically when not otherwise overriden, so using :code:`py` logging +is quite comfortable even in the smallest programs. More typically, +the application programmer will likely design a hierarchy of producers, +and will select keywords appropriately for marking the hierarchy tree. +If a node of the hierarchical tree of producers has to be divided in +sub-trees, all producers in the sub-trees share, as a common prefix, the +keywords of the node being divided. In other words, we go further down +in the hierarchy of producers merely by adding keywords. + +Using the py.log library +================================ + +To use the :code:`py.log` library, the user must import it into a Python +application, create at least one log producer and one log consumer, have +producers and consumers associated, and finally call the log producers +as needed, giving them log messages. + +Importing +--------- + +Once the :code:`py` library is installed on your system, a mere:: + + import py + +holds enough magic for lazily importing the various facilities of the +:code:`py` library when they are first needed. This is really how +:code:`py.log` is made available to the application. For example, after +the above ``import py``, one may directly write ``py.log.Producer(...)`` +and everything should work fine, the user does not have to worry about +specifically importing more modules. + +Creating a producer +------------------- + +There are three ways for creating a log producer instance: + + + As soon as ``py.log`` is first evaluated within an application + program, a default log producer is created, and made available under + the name ``py.log.default``. The keyword ``default`` is associated + with that producer. + + + The ``py.log.Producer()`` constructor may be explicitly called + for creating a new instance of a log producer. That constructor + accepts, as an argument, the keywords that should be associated with + that producer. Keywords may be given either as a tuple of keyword + strings, or as a single space-separated string of keywords. + + + Whenever an attribute is *taken* out of a log producer instance, + for the first time that attribute is taken, a new log producer is + created. The keywords associated with that new producer are those + of the initial producer instance, to which is appended the name of + the attribute being taken. + +The last point is especially useful, as it allows using log producers +without further declarations, merely creating them *on-the-fly*. + +Creating a consumer +------------------- + +There are many ways for creating or denoting a log consumer: + + + A default consumer exists within the ``py.log`` facilities, which + has the effect of writing log messages on the Python standard output + stream. That consumer is associated at the very top of the producer + hierarchy, and as such, is called whenever no other consumer is + found. + + + The notation ``py.log.STDOUT`` accesses a log consumer which writes + log messages on the Python standard output stream. + + + The notation ``py.log.STDERR`` accesses a log consumer which writes + log messages on the Python standard error stream. + + + The ``py.log.File()`` constructor accepts, as argument, either a file + already opened in write mode or any similar file-like object, and + creates a log consumer able to write log messages onto that file. + + + The ``py.log.Path()`` constructor accepts a file name for its first + argument, and creates a log consumer able to write log messages into + that file. The constructor call accepts a few keyword parameters: + + + ``append``, which is ``False`` by default, may be used for + opening the file in append mode instead of write mode. + + + ``delayed_create``, which is ``False`` by default, maybe be used + for opening the file at the latest possible time. Consequently, + the file will not be created if it did not exist, and no actual + log message gets written to it. + + + ``buffering``, which is 1 by default, is used when opening the + file. Buffering can be turned off by specifying a 0 value. The + buffer size may also be selected through this argument. + + + Any user defined function may be used for a log consumer. Such a + function should accept a single argument, which is the message to + write, and do whatever is deemed appropriate by the programmer. + When the need arises, this may be an especially useful and flexible + feature. + + + The special value ``None`` means no consumer at all. This acts just + like if there was a consumer which would silently discard all log + messages sent to it. + +Associating producers and consumers +----------------------------------- + +Each log producer may have at most one log consumer associated with +it. A log producer gets associated with a log consumer through a +``py.log.setconsumer()`` call. That function accepts two arguments, +the first identifying a producer (a tuple of keyword strings or a single +space-separated string of keywords), the second specifying the precise +consumer to use for that producer. Until this function is called for a +producer, that producer does not have any explicit consumer associated +with it. + +Now, the hierarchy of log producers establishes which consumer gets used +whenever a producer has no explicit consumer. When a log producer +has no consumer explicitly associated with it, it dynamically and +recursively inherits the consumer of its parent node, that is, that node +being a bit closer to the root of the hierarchy. In other words, the +rightmost keywords of that producer are dropped until another producer +is found which has an explicit consumer. A nice side-effect is that, +by explicitly associating a consumer with a producer, all consumer-less +producers which appear under that producer, in the hierarchy tree, +automatically *inherits* that consumer. + +Writing log messages +-------------------- + +All log producer instances are also functions, and this is by calling +them that log messages are generated. Each call to a producer object +produces the text for one log entry, which in turn, is sent to the log +consumer for that producer. + +The log entry displays, after a prefix identifying the log producer +being used, all arguments given in the call, converted to strings and +space-separated. (This is meant by design to be fairly similar to what +the ``print`` statement does in Python). The prefix itself is made up +of a colon-separated list of keywords associated with the producer, the +whole being set within square brackets. + +Note that the consumer is responsible for adding the newline at the end +of the log entry. That final newline is not part of the text for the +log entry. + +.. Other details +.. ------------- +.. XXX: fill in details +.. + Should speak about pickle-ability of :code:`py.log`. +.. +.. + What is :code:`log.get` (in :file:`logger.py`)? diff --git a/tests/wpt/web-platform-tests/tools/py/doc/misc.txt b/tests/wpt/web-platform-tests/tools/py/doc/misc.txt new file mode 100644 index 00000000000..8c3c0b3f7a3 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/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 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 new file mode 100644 index 00000000000..837c1d19272 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/path.txt @@ -0,0 +1,260 @@ +======= +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/doc/style.css b/tests/wpt/web-platform-tests/tools/py/doc/style.css new file mode 100644 index 00000000000..1faf762c715 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/style.css @@ -0,0 +1,1044 @@ +body,body.editor,body.body { + font: 110% "Times New Roman", Arial, Verdana, Helvetica, serif; + background: White; + color: Black; +} + +a, a.reference { + text-decoration: none; +} +a[href]:hover { text-decoration: underline; } + +img { + border: none; + vertical-align: middle; +} + +p, div.text { + text-align: left; + line-height: 1.5em; + margin: 0.5em 0em 0em 0em; +} + + + +p a:active { + color: Red; + background-color: transparent; +} + +p img { + border: 0; + margin: 0; +} + +img.inlinephoto { + padding: 0; + padding-right: 1em; + padding-top: 0.7em; + float: left; +} + +hr { + clear: both; + height: 1px; + color: #8CACBB; + background-color: transparent; +} + + +ul { + line-height: 1.5em; + /*list-style-image: url("bullet.gif"); */ + margin-left: 1.5em; + padding:0; +} + +ol { + line-height: 1.5em; + margin-left: 1.5em; + padding:0; +} + +ul a, ol a { + text-decoration: underline; +} + +dl { +} + +dd { + line-height: 1.5em; + margin-bottom: 1em; +} + +blockquote { + font-family: Times, "Times New Roman", serif; + font-style: italic; + font-size: 120%; +} + +code { + color: Black; + /*background-color: #dee7ec;*/ + /*background-color: #cccccc;*/ +} + +pre { + padding: 1em; + border: 1px dotted #8cacbb; + color: Black; + /* + background-color: #dee7ec; + background-color: #cccccc; + background-color: #dee7ec; + */ + overflow: auto; +} + + +.netscape4 { + display: none; +} + +/* main page styles */ + +/*a[href]:hover { color: black; text-decoration: underline; } +a[href]:link { color: black; text-decoration: underline; } +a[href] { color: black; text-decoration: underline; } +*/ + +span.menu_selected { + color: black; + text-decoration: none; + padding-right: 0.3em; + background-color: #cccccc; +} + + +a.menu { + /*color: #3ba6ec; */ + font: 120% Verdana, Helvetica, Arial, sans-serif; + text-decoration: none; + padding-right: 0.3em; +} + +a.menu[href]:visited, a.menu[href]:link{ + /*color: #3ba6ec; */ + text-decoration: none; +} + +a.menu[href]:hover { + /*color: black;*/ +} + +div#pagetitle{ + /*border-spacing: 20px;*/ + font: 160% Verdana, Helvetica, Arial, sans-serif; + color: #3ba6ec; + vertical-align: middle; + left: 80 px; + padding-bottom: 0.3em; +} + +a.wikicurrent { + font: 100% Verdana, Helvetica, Arial, sans-serif; + color: #3ba6ec; + vertical-align: middle; +} + + +table.body { + border: 0; + /*padding: 0; + border-spacing: 0px; + border-collapse: separate; + */ +} + +td.page-header-left { + padding: 5px; + /*border-bottom: 1px solid #444444;*/ +} + +td.page-header-top { + padding: 0; + + /*border-bottom: 1px solid #444444;*/ +} + +td.sidebar { + padding: 1 0 0 1; +} + +td.sidebar p.classblock { + padding: 0 5 0 5; + margin: 1 1 1 1; + border: 1px solid #444444; + background-color: #eeeeee; +} + +td.sidebar p.userblock { + padding: 0 5 0 5; + margin: 1 1 1 1; + border: 1px solid #444444; + background-color: #eeeeff; +} + +td.content { + padding: 1 5 1 5; + vertical-align: top; + width: 100%; +} + +p.ok-message { + background-color: #22bb22; + padding: 5 5 5 5; + color: white; + font-weight: bold; +} +p.error-message { + background-color: #bb2222; + padding: 5 5 5 5; + color: white; + font-weight: bold; +} + +p:first-child { + margin: 0 ; + padding: 0; +} + +/* style for forms */ +table.form { + padding: 2; + border-spacing: 0px; + border-collapse: separate; +} + +table.form th { + color: #333388; + text-align: right; + vertical-align: top; + font-weight: normal; +} +table.form th.header { + font-weight: bold; + background-color: #eeeeff; + text-align: left; +} + +table.form th.required { + font-weight: bold; +} + +table.form td { + color: #333333; + empty-cells: show; + vertical-align: top; +} + +table.form td.optional { + font-weight: bold; + font-style: italic; +} + +table.form td.html { + color: #777777; +} + +/* style for lists */ +table.list { + border-spacing: 0px; + border-collapse: separate; + vertical-align: top; + padding-top: 0; + width: 100%; +} + +table.list th { + padding: 0 4 0 4; + color: #404070; + background-color: #eeeeff; + border-right: 1px solid #404070; + border-top: 1px solid #404070; + border-bottom: 1px solid #404070; + vertical-align: top; + empty-cells: show; +} +table.list th a[href]:hover { color: #404070 } +table.list th a[href]:link { color: #404070 } +table.list th a[href] { color: #404070 } +table.list th.group { + background-color: #f4f4ff; + text-align: center; + font-size: 120%; +} + +table.list td { + padding: 0 4 0 4; + border: 0 2 0 2; + border-right: 1px solid #404070; + color: #404070; + background-color: white; + vertical-align: top; + empty-cells: show; +} + +table.list tr.normal td { + background-color: white; + white-space: nowrap; +} + +table.list tr.alt td { + background-color: #efefef; + white-space: nowrap; +} + +table.list td:first-child { + border-left: 1px solid #404070; + border-right: 1px solid #404070; +} + +table.list th:first-child { + border-left: 1px solid #404070; + border-right: 1px solid #404070; +} + +table.list tr.navigation th { + text-align: right; +} +table.list tr.navigation th:first-child { + border-right: none; + text-align: left; +} + + +/* style for message displays */ +table.messages { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.messages th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.messages th { + font-weight: bold; + color: black; + text-align: left; + border-bottom: 1px solid #afafaf; +} + +table.messages td { + font-family: monospace; + background-color: #efefef; + border-bottom: 1px solid #afafaf; + color: black; + empty-cells: show; + border-right: 1px solid #afafaf; + vertical-align: top; + padding: 2 5 2 5; +} + +table.messages td:first-child { + border-left: 1px solid #afafaf; + border-right: 1px solid #afafaf; +} + +/* style for file displays */ +table.files { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.files th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.files th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} + +table.files td { + font-family: monospace; + empty-cells: show; +} + +/* style for history displays */ +table.history { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.history th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; + font-size: 100%; +} + +table.history th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; + font-size: 90%; +} + +table.history td { + font-size: 90%; + vertical-align: top; + empty-cells: show; +} + + +/* style for class list */ +table.classlist { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.classlist th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.classlist th { + font-weight: bold; + text-align: left; +} + + +/* style for class help display */ +table.classhelp { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.classhelp th { + font-weight: bold; + text-align: left; + color: #707040; +} + +table.classhelp td { + padding: 2 2 2 2; + border: 1px solid black; + text-align: left; + vertical-align: top; + empty-cells: show; +} + + +/* style for "other" displays */ +table.otherinfo { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.otherinfo th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.otherinfo th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} + +input { + border: 1px solid #8cacbb; + color: Black; + background-color: white; + vertical-align: middle; + margin-bottom: 1px; /* IE bug fix */ + padding: 0.1em; +} + +select { + border: 1px solid #8cacbb; + color: Black; + background-color: white; + vertical-align: middle; + margin-bottom: 1px; /* IE bug fix */ + padding: 0.1em; +} + + +a.nonexistent { + color: #FF2222; +} +a.nonexistent:visited { + color: #FF2222; +} +a.external { + color: #AA6600; +} + +/* +dl,ul,ol { + margin-top: 1pt; +} +tt,pre { + font-family: Lucida Console,Courier New,Courier,monotype; + font-size: 12pt; +} +pre.code { + margin-top: 8pt; + margin-bottom: 8pt; + background-color: #FFFFEE; + white-space:pre; + border-style:solid; + border-width:1pt; + border-color:#999999; + color:#111111; + padding:5px; + width:100%; +} +*/ +div.diffold { + background-color: #FFFF80; + border-style:none; + border-width:thin; + width:100%; +} +div.diffnew { + background-color: #80FF80; + border-style:none; + border-width:thin; + width:100%; +} +div.message { + margin-top: 6pt; + background-color: #E8FFE8; + border-style:solid; + border-width:1pt; + border-color:#999999; + color:#440000; + padding:5px; + width:100%; +} +strong.highlight { + background-color: #FFBBBB; +/* as usual, NetScape fucks up with innocent CSS + border-color: #FFAAAA; + border-style: solid; + border-width: 1pt; +*/ +} + +table.navibar { + background-color: #C8C8C8; + border-spacing: 3px; +} +td.navibar { + background-color: #E8E8E8; + vertical-align: top; + text-align: right; + padding: 0px; +} + +a#versioninfo { + color: blue; +} + +div#pagename { + font-size: 140%; + color: blue; + text-align: center; + font-weight: bold; + background-color: white; + padding: 0 ; +} + +a.wikiaction, input.wikiaction { + color: black; + text-decoration: None; + text-align: center; + color: black; + /*border: 1px solid #3ba6ec; */ + margin: 4px; + padding: 5; + padding-bottom: 0; + white-space: nowrap; +} + +a.wikiaction[href]:hover { + color: black; + text-decoration: none; + /*background-color: #dddddd; */ +} + + +div.legenditem { + padding-top: 0.5em; + padding-left: 0.3em; +} + +span.wikitoken { + background-color: #eeeeee; +} + + +div#contentspace h1:first-child, div.heading:first-child { + padding-top: 0; + margin-top: 0; +} +div#contentspace h2:first-child { + padding-top: 0; + margin-top: 0; +} + +/* heading and paragraph text */ + +div.heading, h1 { + font-family: Verdana, Helvetica, Arial, sans-serif; + background-color: #58b3ef; + background-color: #FFFFFF; + /*color: #4893cf;*/ + color: black; + padding-top: 1.0em; + padding-bottom:0.2em; + text-align: left; + margin-top: 0em; + /*margin-bottom:8pt;*/ + font-weight: bold; + font-size: 115%; + border-bottom: 1px solid #8CACBB; +} + +h2 { + border-bottom: 1px dotted #8CACBB; +} + + +h1, h2, h3, h4, h5, h6 { + color: Black; + clear: left; + font: 100% Verdana, Helvetica, Arial, sans-serif; + margin: 0; + padding-left: 0em; + padding-top: 1em; + padding-bottom: 0.2em; + /*border-bottom: 1px solid #8CACBB;*/ +} +/* h1,h2 { padding-top: 0; }*/ + + +h1 { font-size: 145%; } +h2 { font-size: 115%; } +h3 { font-size: 105%; } +h4 { font-size: 100%; } +h5 { font-size: 100%; } + +h1 a { text-decoration: None;} + +div.exception { + background-color: #bb2222; + padding: 5 5 5 5; + color: white; + font-weight: bold; +} +pre.exception { + font-size: 110%; + padding: 1em; + border: 1px solid #8cacbb; + color: Black; + background-color: #dee7ec; + background-color: #cccccc; +} + +/* defines for navgiation bar (documentation) */ + + +div.direntry { + padding-top: 0.3em; + padding-bottom: 0.3em; + margin-right: 1em; + font-weight: bold; + background-color: #dee7ec; + font-size: 110%; +} + +div.fileentry { + font-family: Verdana, Helvetica, Arial, sans-serif; + padding-bottom: 0.3em; + white-space: nowrap; + line-height: 150%; +} + +a.fileentry { + white-space: nowrap; +} + + +span.left { + text-align: left; +} +span.right { + text-align: right; +} + +div.navbar { + /*margin: 0;*/ + font-size: 80% /*smaller*/; + font-weight: bold; + text-align: left; + /* position: fixed; */ + top: 100pt; + left: 0pt; /* auto; */ + width: 120pt; + /* right: auto; + right: 0pt; 2em; */ +} + + +div.history a { + /* font-size: 70%; */ +} + +div.wikiactiontitle { + font-weight: bold; +} + +/* REST defines */ + +div.document { + margin: 0; +} + +h1.title { + margin: 0; + margin-bottom: 0.5em; +} + +td.toplist { + vertical-align: top; +} + +img#pyimg { + float: left; + padding-bottom: 1em; +} + +div#navspace { + position: absolute; + font-size: 100%; + width: 150px; + overflow: hidden; /* scroll; */ +} + + +div#errorline { + position: relative; + top: 5px; + float: right; +} + +div#contentspace { + position: absolute; + /* font: 120% "Times New Roman", serif;*/ + font: 110% Verdana, Helvetica, Arial, sans-serif; + left: 170px; + margin-right: 5px; +} + +div#menubar { +/* width: 400px; */ + float: left; +} + +/* for the documentation page */ +div#title{ + + font-size: 110%; + color: black; + + + /*background-color: #dee7ec; + #padding: 5pt; + #padding-bottom: 1em; + #color: black; + border-width: 1pt; + border-style: solid;*/ + +} + +div#docnavlist { + /*background-color: #dee7ec; */ + padding: 5pt; + padding-bottom: 2em; + color: black; + border-width: 1pt; + /*border-style: solid;*/ +} + + +/* text markup */ + +div.listtitle { + color: Black; + clear: left; + font: 120% Verdana, Helvetica, Arial, sans-serif; + margin: 0; + padding-left: 0em; + padding-top: 0em; + padding-bottom: 0.2em; + margin-right: 0.5em; + border-bottom: 1px solid #8CACBB; +} + +div.actionbox h3 { + padding-top: 0; + padding-right: 0.5em; + padding-left: 0.5em; + background-color: #fabf00; + text-align: center; + border: 1px solid black; /* 8cacbb; */ +} + +div.actionbox a { + display: block; + padding-bottom: 0.5em; + padding-top: 0.5em; + margin-left: 0.5em; +} + +div.actionbox a.history { + display: block; + padding-bottom: 0.5em; + padding-top: 0.5em; + margin-left: 0.5em; + font-size: 90%; +} + +div.actionbox { + margin-bottom: 2em; + padding-bottom: 1em; + overflow: hidden; /* scroll; */ +} + +/* taken from docutils (oh dear, a bit senseless) */ +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + + +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:date: $Date: 2003/01/22 22:26:48 $ +:version: $Revision: 1.29 $ +:copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ +/* +.first { + margin-top: 0 } + +.last { + margin-bottom: 0 } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option { + white-space: nowrap } + +span.option-argument { + font-style: italic } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +th.docinfo-name, th.field-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap } + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + font-size: 100% } + +tt { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } +*/ + +div.section { + margin-top: 1.0em ; +} diff --git a/tests/wpt/web-platform-tests/tools/py/doc/xml.txt b/tests/wpt/web-platform-tests/tools/py/doc/xml.txt new file mode 100644 index 00000000000..1022de6e912 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/doc/xml.txt @@ -0,0 +1,164 @@ +==================================================== +py.xml: simple pythonic xml/html file generation +==================================================== + +Motivation +========== + +There are a plethora of frameworks and libraries to generate +xml and html trees. However, many of them are large, have a +steep learning curve and are often hard to debug. Not to +speak of the fact that they are frameworks to begin with. + +.. _xist: http://www.livinglogic.de/Python/xist/index.html + +a pythonic object model , please +================================ + +The py lib offers a pythonic way to generate xml/html, based on +ideas from xist_ which `uses python class objects`_ to build +xml trees. However, xist_'s implementation is somewhat heavy +because it has additional goals like transformations and +supporting many namespaces. But its basic idea is very easy. + +.. _`uses python class objects`: http://www.livinglogic.de/Python/xist/Howto.html + +generating arbitrary xml structures +----------------------------------- + +With ``py.xml.Namespace`` you have the basis +to generate custom xml-fragments on the fly:: + + class ns(py.xml.Namespace): + "my custom xml namespace" + doc = ns.books( + ns.book( + ns.author("May Day"), + ns.title("python for java programmers"),), + ns.book( + ns.author("why"), + ns.title("Java for Python programmers"),), + publisher="N.N", + ) + print doc.unicode(indent=2).encode('utf8') + +will give you this representation:: + + + + May Day + python for java programmers + + why + Java for Python programmers + +In a sentence: positional arguments are child-tags and +keyword-arguments are attributes. + +On a side note, you'll see that the unicode-serializer +supports a nice indentation style which keeps your generated +html readable, basically through emulating python's white +space significance by putting closing-tags rightmost and +almost invisible at first glance :-) + +basic example for generating html +--------------------------------- + +Consider this example:: + + from py.xml import html # html namespace + + paras = "First Para", "Second para" + + doc = html.html( + html.head( + html.meta(name="Content-Type", value="text/html; charset=latin1")), + html.body( + [html.p(p) for p in paras])) + + print unicode(doc).encode('latin1') + +Again, tags are objects which contain tags and have attributes. +More exactly, Tags inherit from the list type and thus can be +manipulated as list objects. They additionally support a default +way to represent themselves as a serialized unicode object. + +If you happen to look at the py.xml implementation you'll +note that the tag/namespace implementation consumes some 50 lines +with another 50 lines for the unicode serialization code. + +CSS-styling your html Tags +-------------------------- + +One aspect where many of the huge python xml/html generation +frameworks utterly fail is a clean and convenient integration +of CSS styling. Often, developers are left alone with keeping +CSS style definitions in sync with some style files +represented as strings (often in a separate .css file). Not +only is this hard to debug but the missing abstractions make +it hard to modify the styling of your tags or to choose custom +style representations (inline, html.head or external). Add the +Browers usual tolerance of messyness and errors in Style +references and welcome to hell, known as the domain of +developing web applications :-) + +By contrast, consider this CSS styling example:: + + class my(html): + "my initial custom style" + class body(html.body): + style = html.Style(font_size = "120%") + + class h2(html.h2): + style = html.Style(background = "grey") + + class p(html.p): + style = html.Style(font_weight="bold") + + doc = my.html( + my.head(), + my.body( + my.h2("hello world"), + my.p("bold as bold can") + ) + ) + + print doc.unicode(indent=2) + +This will give you a small'n mean self contained +represenation by default:: + + + + +

hello world

+

bold as bold can

+ +Most importantly, note that the inline-styling is just an +implementation detail of the unicode serialization code. +You can easily modify the serialization to put your styling into the +``html.head`` or in a separate file and autogenerate CSS-class +names or ids. + +Hey, you could even write tests that you are using correct +styles suitable for specific browser requirements. Did i mention +that the ability to easily write tests for your generated +html and its serialization could help to develop _stable_ user +interfaces? + +More to come ... +---------------- + +For now, i don't think we should strive to offer much more +than the above. However, it is probably not hard to offer +*partial serialization* to allow generating maybe hundreds of +complex html documents per second. Basically we would allow +putting callables both as Tag content and as values of +attributes. A slightly more advanced Serialization would then +produce a list of unicode objects intermingled with callables. +At HTTP-Request time the callables would get called to +complete the probably request-specific serialization of +your Tags. Hum, it's probably harder to explain this than to +actually code it :-) + +.. _`py.test`: test/index.html diff --git a/tests/wpt/web-platform-tests/tools/py/py/__init__.py b/tests/wpt/web-platform-tests/tools/py/py/__init__.py new file mode 100644 index 00000000000..bdb9aa2181f --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/__init__.py @@ -0,0 +1,150 @@ +""" +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/__metainfo.py b/tests/wpt/web-platform-tests/tools/py/py/__metainfo.py new file mode 100644 index 00000000000..12581eb7afb --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/__metainfo.py @@ -0,0 +1,2 @@ +import py +pydir = py.path.local(py.__file__).dirpath() diff --git a/tests/wpt/web-platform-tests/tools/py/py/_apipkg.py b/tests/wpt/web-platform-tests/tools/py/py/_apipkg.py new file mode 100644 index 00000000000..a73b8f6d0bc --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_apipkg.py @@ -0,0 +1,181 @@ +""" +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 '' % (self.__name__, " ".join(l)) + return '' % (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 '' % (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/_builtin.py b/tests/wpt/web-platform-tests/tools/py/py/_builtin.py new file mode 100644 index 00000000000..52ee9d79cad --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_builtin.py @@ -0,0 +1,248 @@ +import sys + +try: + reversed = reversed +except NameError: + def reversed(sequence): + """reversed(sequence) -> reverse iterator over values of the sequence + + Return a reverse iterator + """ + if hasattr(sequence, '__reversed__'): + return sequence.__reversed__() + if not hasattr(sequence, '__getitem__'): + raise TypeError("argument to reversed() must be a sequence") + return reversed_iterator(sequence) + + class reversed_iterator(object): + + def __init__(self, seq): + self.seq = seq + self.remaining = len(seq) + + def __iter__(self): + return self + + def next(self): + i = self.remaining + if i > 0: + i -= 1 + item = self.seq[i] + self.remaining = i + return item + raise StopIteration + + def __length_hint__(self): + return self.remaining + +try: + any = any +except NameError: + def any(iterable): + for x in iterable: + if x: + return True + return False + +try: + all = all +except NameError: + def all(iterable): + for x in iterable: + if not x: + return False + return True + +try: + sorted = sorted +except NameError: + builtin_cmp = cmp # need to use cmp as keyword arg + + def sorted(iterable, cmp=None, key=None, reverse=0): + use_cmp = None + if key is not None: + if cmp is None: + def use_cmp(x, y): + return builtin_cmp(x[0], y[0]) + else: + def use_cmp(x, y): + return cmp(x[0], y[0]) + l = [(key(element), element) for element in iterable] + else: + if cmp is not None: + use_cmp = cmp + l = list(iterable) + if use_cmp is not None: + l.sort(use_cmp) + else: + l.sort() + if reverse: + l.reverse() + if key is not None: + return [element for (_, element) in l] + return l + +try: + set, frozenset = set, frozenset +except NameError: + from sets import set, frozenset + +# pass through +enumerate = enumerate + +try: + BaseException = BaseException +except NameError: + BaseException = Exception + +try: + GeneratorExit = GeneratorExit +except NameError: + class GeneratorExit(Exception): + """ This exception is never raised, it is there to make it possible to + write code compatible with CPython 2.5 even in lower CPython + versions.""" + pass + GeneratorExit.__module__ = 'exceptions' + +_sysex = (KeyboardInterrupt, SystemExit, MemoryError, GeneratorExit) + +try: + callable = callable +except NameError: + def callable(obj): + return hasattr(obj, "__call__") + +if sys.version_info >= (3, 0): + exec ("print_ = print ; exec_=exec") + import builtins + + # some backward compatibility helpers + _basestring = str + def _totext(obj, encoding=None, errors=None): + if isinstance(obj, bytes): + if errors is None: + obj = obj.decode(encoding) + else: + obj = obj.decode(encoding, errors) + elif not isinstance(obj, str): + obj = str(obj) + return obj + + def _isbytes(x): + return isinstance(x, bytes) + def _istext(x): + return isinstance(x, str) + + text = str + bytes = bytes + + + def _getimself(function): + return getattr(function, '__self__', None) + + def _getfuncdict(function): + return getattr(function, "__dict__", None) + + def _getcode(function): + return getattr(function, "__code__", None) + + def execfile(fn, globs=None, locs=None): + if globs is None: + back = sys._getframe(1) + globs = back.f_globals + locs = back.f_locals + del back + elif locs is None: + locs = globs + fp = open(fn, "r") + try: + source = fp.read() + finally: + fp.close() + co = compile(source, fn, "exec", dont_inherit=True) + exec_(co, globs, locs) + +else: + import __builtin__ as builtins + _totext = unicode + _basestring = basestring + text = unicode + bytes = str + execfile = execfile + callable = callable + def _isbytes(x): + return isinstance(x, str) + def _istext(x): + return isinstance(x, unicode) + + def _getimself(function): + return getattr(function, 'im_self', None) + + def _getfuncdict(function): + return getattr(function, "__dict__", None) + + def _getcode(function): + try: + return getattr(function, "__code__") + except AttributeError: + return getattr(function, "func_code", None) + + def print_(*args, **kwargs): + """ minimal backport of py3k print statement. """ + sep = ' ' + if 'sep' in kwargs: + sep = kwargs.pop('sep') + end = '\n' + if 'end' in kwargs: + end = kwargs.pop('end') + file = 'file' in kwargs and kwargs.pop('file') or sys.stdout + if kwargs: + args = ", ".join([str(x) for x in kwargs]) + raise TypeError("invalid keyword arguments: %s" % args) + at_start = True + for x in args: + if not at_start: + file.write(sep) + file.write(str(x)) + at_start = False + file.write(end) + + def exec_(obj, globals=None, locals=None): + """ minimal backport of py3k exec statement. """ + __tracebackhide__ = True + if globals is None: + frame = sys._getframe(1) + globals = frame.f_globals + if locals is None: + locals = frame.f_locals + elif locals is None: + locals = globals + exec2(obj, globals, locals) + +if sys.version_info >= (3, 0): + def _reraise(cls, val, tb): + __tracebackhide__ = True + assert hasattr(val, '__traceback__') + raise cls.with_traceback(val, tb) +else: + exec (""" +def _reraise(cls, val, tb): + __tracebackhide__ = True + raise cls, val, tb +def exec2(obj, globals, locals): + __tracebackhide__ = True + exec obj in globals, locals +""") + +def _tryimport(*names): + """ return the first successfully imported module. """ + assert names + for name in names: + try: + __import__(name) + except ImportError: + excinfo = sys.exc_info() + else: + return sys.modules[name] + _reraise(*excinfo) diff --git a/tests/wpt/web-platform-tests/tools/py/py/_code/__init__.py b/tests/wpt/web-platform-tests/tools/py/py/_code/__init__.py new file mode 100644 index 00000000000..f15acf85132 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_code/__init__.py @@ -0,0 +1 @@ +""" python inspection/code generation API """ 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 new file mode 100644 index 00000000000..afb1b31ff05 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_code/_assertionnew.py @@ -0,0 +1,339 @@ +""" +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, "", 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 new file mode 100644 index 00000000000..4e81fb3ef6e --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_code/_assertionold.py @@ -0,0 +1,555 @@ +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 = '' + self.__obj__.filename = '' + 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 = '' + 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 ' + 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 = '' + 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/_py2traceback.py b/tests/wpt/web-platform-tests/tools/py/py/_code/_py2traceback.py new file mode 100644 index 00000000000..d65e27cb730 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_code/_py2traceback.py @@ -0,0 +1,79 @@ +# 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 "" + lines.append(' File "%s", line %d\n' % (filename, lineno)) + if badline is not None: + lines.append(' %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 '' % type(value).__name__ 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 new file mode 100644 index 00000000000..4ce80c75b1c --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_code/assertion.py @@ -0,0 +1,94 @@ +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 "". + if source: + self.msg = reinterpret(source, f, should_fail=True) + else: + self.msg = "" + 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 new file mode 100644 index 00000000000..f14c562a296 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_code/code.py @@ -0,0 +1,787 @@ +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 "" %(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 "" % (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__ = ") + 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 new file mode 100644 index 00000000000..3a648e63579 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_code/source.py @@ -0,0 +1,419 @@ +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 new file mode 100644 index 00000000000..550fb521a04 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_error.py @@ -0,0 +1,88 @@ +""" +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 new file mode 100644 index 00000000000..92b50bd853a --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_iniconfig.py @@ -0,0 +1,162 @@ +""" 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/__init__.py b/tests/wpt/web-platform-tests/tools/py/py/_io/__init__.py new file mode 100644 index 00000000000..835f01f3ab9 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_io/__init__.py @@ -0,0 +1 @@ +""" input/output helping """ diff --git a/tests/wpt/web-platform-tests/tools/py/py/_io/capture.py b/tests/wpt/web-platform-tests/tools/py/py/_io/capture.py new file mode 100644 index 00000000000..bc157ed978f --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_io/capture.py @@ -0,0 +1,371 @@ +import os +import sys +import py +import tempfile + +try: + from io import StringIO +except ImportError: + from StringIO import StringIO + +if sys.version_info < (3,0): + class TextIO(StringIO): + def write(self, data): + if not isinstance(data, unicode): + data = unicode(data, getattr(self, '_encoding', 'UTF-8'), 'replace') + StringIO.write(self, data) +else: + TextIO = StringIO + +try: + from io import BytesIO +except ImportError: + class BytesIO(StringIO): + def write(self, data): + if isinstance(data, unicode): + raise TypeError("not a byte value: %r" %(data,)) + StringIO.write(self, data) + +patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'} + +class FDCapture: + """ Capture IO to/from a given os-level filedescriptor. """ + + def __init__(self, targetfd, tmpfile=None, now=True, patchsys=False): + """ save targetfd descriptor, and open a new + temporary file there. If no tmpfile is + specified a tempfile.Tempfile() will be opened + in text mode. + """ + self.targetfd = targetfd + if tmpfile is None and targetfd != 0: + f = tempfile.TemporaryFile('wb+') + tmpfile = dupfile(f, encoding="UTF-8") + f.close() + self.tmpfile = tmpfile + self._savefd = os.dup(self.targetfd) + if patchsys: + self._oldsys = getattr(sys, patchsysdict[targetfd]) + if now: + self.start() + + def start(self): + try: + os.fstat(self._savefd) + except OSError: + raise ValueError("saved filedescriptor not valid, " + "did you call start() twice?") + if self.targetfd == 0 and not self.tmpfile: + fd = os.open(devnullpath, os.O_RDONLY) + os.dup2(fd, 0) + os.close(fd) + if hasattr(self, '_oldsys'): + setattr(sys, patchsysdict[self.targetfd], DontReadFromInput()) + else: + os.dup2(self.tmpfile.fileno(), self.targetfd) + if hasattr(self, '_oldsys'): + setattr(sys, patchsysdict[self.targetfd], self.tmpfile) + + def done(self): + """ unpatch and clean up, returns the self.tmpfile (file object) + """ + os.dup2(self._savefd, self.targetfd) + os.close(self._savefd) + if self.targetfd != 0: + self.tmpfile.seek(0) + if hasattr(self, '_oldsys'): + setattr(sys, patchsysdict[self.targetfd], self._oldsys) + return self.tmpfile + + def writeorg(self, data): + """ write a string to the original file descriptor + """ + tempfp = tempfile.TemporaryFile() + try: + os.dup2(self._savefd, tempfp.fileno()) + tempfp.write(data) + finally: + tempfp.close() + + +def dupfile(f, mode=None, buffering=0, raising=False, encoding=None): + """ return a new open file object that's a duplicate of f + + mode is duplicated if not given, 'buffering' controls + buffer size (defaulting to no buffering) and 'raising' + defines whether an exception is raised when an incompatible + file object is passed in (if raising is False, the file + object itself will be returned) + """ + try: + fd = f.fileno() + mode = mode or f.mode + except AttributeError: + if raising: + raise + return f + newfd = os.dup(fd) + if sys.version_info >= (3,0): + if encoding is not None: + mode = mode.replace("b", "") + buffering = True + return os.fdopen(newfd, mode, buffering, encoding, closefd=True) + else: + f = os.fdopen(newfd, mode, buffering) + if encoding is not None: + return EncodedFile(f, encoding) + return f + +class EncodedFile(object): + def __init__(self, _stream, encoding): + self._stream = _stream + self.encoding = encoding + + def write(self, obj): + if isinstance(obj, unicode): + obj = obj.encode(self.encoding) + elif isinstance(obj, str): + pass + else: + obj = str(obj) + self._stream.write(obj) + + def writelines(self, linelist): + data = ''.join(linelist) + self.write(data) + + def __getattr__(self, name): + return getattr(self._stream, name) + +class Capture(object): + def call(cls, func, *args, **kwargs): + """ return a (res, out, err) tuple where + out and err represent the output/error output + during function execution. + call the given function with args/kwargs + and capture output/error during its execution. + """ + so = cls() + try: + res = func(*args, **kwargs) + finally: + out, err = so.reset() + return res, out, err + call = classmethod(call) + + def reset(self): + """ reset sys.stdout/stderr and return captured output as strings. """ + if hasattr(self, '_reset'): + raise ValueError("was already reset") + self._reset = True + outfile, errfile = self.done(save=False) + out, err = "", "" + if outfile and not outfile.closed: + out = outfile.read() + outfile.close() + if errfile and errfile != outfile and not errfile.closed: + err = errfile.read() + errfile.close() + return out, err + + def suspend(self): + """ return current snapshot captures, memorize tempfiles. """ + outerr = self.readouterr() + outfile, errfile = self.done() + return outerr + + +class StdCaptureFD(Capture): + """ This class allows to capture writes to FD1 and FD2 + and may connect a NULL file to FD0 (and prevent + reads from sys.stdin). If any of the 0,1,2 file descriptors + is invalid it will not be captured. + """ + def __init__(self, out=True, err=True, mixed=False, + in_=True, patchsys=True, now=True): + self._options = { + "out": out, + "err": err, + "mixed": mixed, + "in_": in_, + "patchsys": patchsys, + "now": now, + } + self._save() + if now: + self.startall() + + def _save(self): + in_ = self._options['in_'] + out = self._options['out'] + err = self._options['err'] + mixed = self._options['mixed'] + patchsys = self._options['patchsys'] + if in_: + try: + self.in_ = FDCapture(0, tmpfile=None, now=False, + patchsys=patchsys) + except OSError: + pass + if out: + tmpfile = None + if hasattr(out, 'write'): + tmpfile = out + try: + self.out = FDCapture(1, tmpfile=tmpfile, + now=False, patchsys=patchsys) + self._options['out'] = self.out.tmpfile + except OSError: + pass + if err: + if out and mixed: + tmpfile = self.out.tmpfile + elif hasattr(err, 'write'): + tmpfile = err + else: + tmpfile = None + try: + self.err = FDCapture(2, tmpfile=tmpfile, + now=False, patchsys=patchsys) + self._options['err'] = self.err.tmpfile + except OSError: + pass + + def startall(self): + if hasattr(self, 'in_'): + self.in_.start() + if hasattr(self, 'out'): + self.out.start() + if hasattr(self, 'err'): + self.err.start() + + def resume(self): + """ resume capturing with original temp files. """ + self.startall() + + def done(self, save=True): + """ return (outfile, errfile) and stop capturing. """ + outfile = errfile = None + if hasattr(self, 'out') and not self.out.tmpfile.closed: + outfile = self.out.done() + if hasattr(self, 'err') and not self.err.tmpfile.closed: + errfile = self.err.done() + if hasattr(self, 'in_'): + tmpfile = self.in_.done() + if save: + self._save() + return outfile, errfile + + def readouterr(self): + """ return snapshot value of stdout/stderr capturings. """ + if hasattr(self, "out"): + out = self._readsnapshot(self.out.tmpfile) + else: + out = "" + if hasattr(self, "err"): + err = self._readsnapshot(self.err.tmpfile) + else: + err = "" + return [out, err] + + def _readsnapshot(self, f): + f.seek(0) + res = f.read() + enc = getattr(f, "encoding", None) + if enc: + res = py.builtin._totext(res, enc, "replace") + f.truncate(0) + f.seek(0) + return res + + +class StdCapture(Capture): + """ This class allows to capture writes to sys.stdout|stderr "in-memory" + and will raise errors on tries to read from sys.stdin. It only + modifies sys.stdout|stderr|stdin attributes and does not + touch underlying File Descriptors (use StdCaptureFD for that). + """ + def __init__(self, out=True, err=True, in_=True, mixed=False, now=True): + self._oldout = sys.stdout + self._olderr = sys.stderr + self._oldin = sys.stdin + if out and not hasattr(out, 'file'): + out = TextIO() + self.out = out + if err: + if mixed: + err = out + elif not hasattr(err, 'write'): + err = TextIO() + self.err = err + self.in_ = in_ + if now: + self.startall() + + def startall(self): + if self.out: + sys.stdout = self.out + if self.err: + sys.stderr = self.err + if self.in_: + sys.stdin = self.in_ = DontReadFromInput() + + def done(self, save=True): + """ return (outfile, errfile) and stop capturing. """ + outfile = errfile = None + if self.out and not self.out.closed: + sys.stdout = self._oldout + outfile = self.out + outfile.seek(0) + if self.err and not self.err.closed: + sys.stderr = self._olderr + errfile = self.err + errfile.seek(0) + if self.in_: + sys.stdin = self._oldin + return outfile, errfile + + def resume(self): + """ resume capturing with original temp files. """ + self.startall() + + def readouterr(self): + """ return snapshot value of stdout/stderr capturings. """ + out = err = "" + if self.out: + out = self.out.getvalue() + self.out.truncate(0) + self.out.seek(0) + if self.err: + err = self.err.getvalue() + self.err.truncate(0) + self.err.seek(0) + return out, err + +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. + """ + 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 + +try: + devnullpath = os.devnull +except AttributeError: + if os.name == 'nt': + devnullpath = 'NUL' + else: + devnullpath = '/dev/null' diff --git a/tests/wpt/web-platform-tests/tools/py/py/_io/saferepr.py b/tests/wpt/web-platform-tests/tools/py/py/_io/saferepr.py new file mode 100644 index 00000000000..8518290efdd --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_io/saferepr.py @@ -0,0 +1,71 @@ +import py +import sys + +builtin_repr = repr + +reprlib = py.builtin._tryimport('repr', 'reprlib') + +class SafeRepr(reprlib.Repr): + """ subclass of repr.Repr that limits the resulting size of repr() + and includes information on exceptions raised during the call. + """ + def repr(self, x): + return self._callhelper(reprlib.Repr.repr, self, x) + + def repr_unicode(self, x, level): + # Strictly speaking wrong on narrow builds + def repr(u): + if "'" not in u: + return py.builtin._totext("'%s'") % u + elif '"' not in u: + return py.builtin._totext('"%s"') % u + else: + return py.builtin._totext("'%s'") % u.replace("'", r"\'") + s = repr(x[:self.maxstring]) + if len(s) > self.maxstring: + i = max(0, (self.maxstring-3)//2) + j = max(0, self.maxstring-3-i) + s = repr(x[:i] + x[len(x)-j:]) + s = s[:i] + '...' + s[len(s)-j:] + return s + + def repr_instance(self, x, level): + return self._callhelper(builtin_repr, x) + + def _callhelper(self, call, x, *args): + try: + # Try the vanilla repr and make sure that the result is a string + s = call(x, *args) + except py.builtin._sysex: + raise + except: + cls, e, tb = sys.exc_info() + exc_name = getattr(cls, '__name__', 'unknown') + try: + exc_info = str(e) + except py.builtin._sysex: + raise + except: + exc_info = 'unknown' + return '<[%s("%s") raised in repr()] %s object at 0x%x>' % ( + exc_name, exc_info, x.__class__.__name__, id(x)) + else: + if len(s) > self.maxsize: + i = max(0, (self.maxsize-3)//2) + j = max(0, self.maxsize-3-i) + s = s[:i] + '...' + s[len(s)-j:] + return s + +def saferepr(obj, maxsize=240): + """ return a size-limited safe repr-string for the given object. + Failing __repr__ functions of user instances will be represented + with a short exception info and 'saferepr' generally takes + care to never raise exceptions itself. This function is a wrapper + around the Repr/reprlib functionality of the standard 2.6 lib. + """ + # review exception handling + srepr = SafeRepr() + srepr.maxstring = maxsize + srepr.maxsize = maxsize + srepr.maxother = 160 + return srepr.repr(obj) 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 new file mode 100644 index 00000000000..cef1ff58097 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_io/terminalwriter.py @@ -0,0 +1,348 @@ +""" + +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/__init__.py b/tests/wpt/web-platform-tests/tools/py/py/_log/__init__.py new file mode 100644 index 00000000000..fad62e960d4 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_log/__init__.py @@ -0,0 +1,2 @@ +""" logging API ('producers' and 'consumers' connected via keywords) """ + 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 new file mode 100644 index 00000000000..ce47e8c754a --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_log/log.py @@ -0,0 +1,186 @@ +""" +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 "" % ":".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 new file mode 100644 index 00000000000..722e31e910d --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_log/warning.py @@ -0,0 +1,76 @@ +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 = "" + 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/__init__.py b/tests/wpt/web-platform-tests/tools/py/py/_path/__init__.py new file mode 100644 index 00000000000..51f3246f807 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_path/__init__.py @@ -0,0 +1 @@ +""" unified file system api """ diff --git a/tests/wpt/web-platform-tests/tools/py/py/_path/cacheutil.py b/tests/wpt/web-platform-tests/tools/py/py/_path/cacheutil.py new file mode 100644 index 00000000000..99225047502 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_path/cacheutil.py @@ -0,0 +1,114 @@ +""" +This module contains multithread-safe cache implementations. + +All Caches have + + getorbuild(key, builder) + delentry(key) + +methods and allow configuration when instantiating the cache class. +""" +from time import time as gettime + +class BasicCache(object): + def __init__(self, maxentries=128): + self.maxentries = maxentries + self.prunenum = int(maxentries - maxentries/8) + self._dict = {} + + def clear(self): + self._dict.clear() + + def _getentry(self, key): + return self._dict[key] + + def _putentry(self, key, entry): + self._prunelowestweight() + self._dict[key] = entry + + def delentry(self, key, raising=False): + try: + del self._dict[key] + except KeyError: + if raising: + raise + + def getorbuild(self, key, builder): + try: + entry = self._getentry(key) + except KeyError: + entry = self._build(key, builder) + self._putentry(key, entry) + return entry.value + + def _prunelowestweight(self): + """ prune out entries with lowest weight. """ + numentries = len(self._dict) + if numentries >= self.maxentries: + # evict according to entry's weight + items = [(entry.weight, key) + for key, entry in self._dict.items()] + items.sort() + index = numentries - self.prunenum + if index > 0: + for weight, key in items[:index]: + # in MT situations the element might be gone + self.delentry(key, raising=False) + +class BuildcostAccessCache(BasicCache): + """ A BuildTime/Access-counting cache implementation. + the weight of a value is computed as the product of + + num-accesses-of-a-value * time-to-build-the-value + + The values with the least such weights are evicted + if the cache maxentries threshold is superceded. + For implementation flexibility more than one object + might be evicted at a time. + """ + # time function to use for measuring build-times + + def _build(self, key, builder): + start = gettime() + val = builder() + end = gettime() + return WeightedCountingEntry(val, end-start) + + +class WeightedCountingEntry(object): + def __init__(self, value, oneweight): + self._value = value + self.weight = self._oneweight = oneweight + + def value(self): + self.weight += self._oneweight + return self._value + value = property(value) + +class AgingCache(BasicCache): + """ This cache prunes out cache entries that are too old. + """ + def __init__(self, maxentries=128, maxseconds=10.0): + super(AgingCache, self).__init__(maxentries) + self.maxseconds = maxseconds + + def _getentry(self, key): + entry = self._dict[key] + if entry.isexpired(): + self.delentry(key) + raise KeyError(key) + return entry + + def _build(self, key, builder): + val = builder() + entry = AgingEntry(val, gettime() + self.maxseconds) + return entry + +class AgingEntry(object): + def __init__(self, value, expirationtime): + self.value = value + self.weight = expirationtime + + def isexpired(self): + t = gettime() + return t >= self.weight 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 new file mode 100644 index 00000000000..d407434cb2a --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_path/common.py @@ -0,0 +1,403 @@ +""" +""" +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 new file mode 100644 index 00000000000..d569404ec21 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_path/local.py @@ -0,0 +1,911 @@ +""" +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 new file mode 100644 index 00000000000..78d71317ac0 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/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\d+) +(?P.+?) +(0? *(?P\d+))? ' + '*(?P\w+ +\d{2} +[\d:]+) +(?P.*)$') + 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 new file mode 100644 index 00000000000..00d3b4bbaf3 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/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 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 "" %(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 '' % ( + 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/py/py/_process/__init__.py new file mode 100644 index 00000000000..86c714ad1ae --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_process/__init__.py @@ -0,0 +1 @@ +""" high-level sub-process handling """ diff --git a/tests/wpt/web-platform-tests/tools/py/py/_process/cmdexec.py b/tests/wpt/web-platform-tests/tools/py/py/_process/cmdexec.py new file mode 100644 index 00000000000..f83a2494029 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_process/cmdexec.py @@ -0,0 +1,49 @@ +import sys +import subprocess +import py +from subprocess import Popen, PIPE + +def cmdexec(cmd): + """ return unicode output of executing 'cmd' in a separate process. + + raise cmdexec.Error exeception if the command failed. + the exception will provide an 'err' attribute containing + the error-output from the command. + if the subprocess module does not provide a proper encoding/unicode strings + sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'. + """ + process = subprocess.Popen(cmd, shell=True, + universal_newlines=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = process.communicate() + if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not + try: + default_encoding = sys.getdefaultencoding() # jython may not have it + except AttributeError: + default_encoding = sys.stdout.encoding or 'UTF-8' + out = unicode(out, process.stdout.encoding or default_encoding) + err = unicode(err, process.stderr.encoding or default_encoding) + status = process.poll() + if status: + raise ExecutionFailed(status, status, cmd, out, err) + return out + +class ExecutionFailed(py.error.Error): + def __init__(self, status, systemstatus, cmd, out, err): + Exception.__init__(self) + self.status = status + self.systemstatus = systemstatus + self.cmd = cmd + self.err = err + self.out = out + + def __str__(self): + return "ExecutionFailed: %d %s\n%s" %(self.status, self.cmd, self.err) + +# export the exception under the name 'py.process.cmdexec.Error' +cmdexec.Error = ExecutionFailed +try: + ExecutionFailed.__module__ = 'py.process.cmdexec' + ExecutionFailed.__name__ = 'Error' +except (AttributeError, TypeError): + pass diff --git a/tests/wpt/web-platform-tests/tools/py/py/_process/forkedfunc.py b/tests/wpt/web-platform-tests/tools/py/py/_process/forkedfunc.py new file mode 100644 index 00000000000..1c285306884 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_process/forkedfunc.py @@ -0,0 +1,120 @@ + +""" + ForkedFunc provides a way to run a function in a forked process + and get at its return value, stdout and stderr output as well + as signals and exitstatusus. +""" + +import py +import os +import sys +import marshal + + +def get_unbuffered_io(fd, filename): + f = open(str(filename), "w") + if fd != f.fileno(): + os.dup2(f.fileno(), fd) + class AutoFlush: + def write(self, data): + f.write(data) + f.flush() + def __getattr__(self, name): + return getattr(f, name) + return AutoFlush() + + +class ForkedFunc: + EXITSTATUS_EXCEPTION = 3 + + + def __init__(self, fun, args=None, kwargs=None, nice_level=0, + child_on_start=None, child_on_exit=None): + if args is None: + args = [] + if kwargs is None: + kwargs = {} + self.fun = fun + self.args = args + self.kwargs = kwargs + self.tempdir = tempdir = py.path.local.mkdtemp() + self.RETVAL = tempdir.ensure('retval') + self.STDOUT = tempdir.ensure('stdout') + self.STDERR = tempdir.ensure('stderr') + + pid = os.fork() + if pid: # in parent process + self.pid = pid + else: # in child process + self.pid = None + self._child(nice_level, child_on_start, child_on_exit) + + def _child(self, nice_level, child_on_start, child_on_exit): + # right now we need to call a function, but first we need to + # map all IO that might happen + sys.stdout = stdout = get_unbuffered_io(1, self.STDOUT) + sys.stderr = stderr = get_unbuffered_io(2, self.STDERR) + retvalf = self.RETVAL.open("wb") + EXITSTATUS = 0 + try: + if nice_level: + os.nice(nice_level) + try: + if child_on_start is not None: + child_on_start() + retval = self.fun(*self.args, **self.kwargs) + retvalf.write(marshal.dumps(retval)) + if child_on_exit is not None: + child_on_exit() + except: + excinfo = py.code.ExceptionInfo() + stderr.write(str(excinfo._getreprcrash())) + EXITSTATUS = self.EXITSTATUS_EXCEPTION + finally: + stdout.close() + stderr.close() + retvalf.close() + os.close(1) + os.close(2) + os._exit(EXITSTATUS) + + def waitfinish(self, waiter=os.waitpid): + pid, systemstatus = waiter(self.pid, 0) + if systemstatus: + if os.WIFSIGNALED(systemstatus): + exitstatus = os.WTERMSIG(systemstatus) + 128 + else: + exitstatus = os.WEXITSTATUS(systemstatus) + else: + exitstatus = 0 + signal = systemstatus & 0x7f + if not exitstatus and not signal: + retval = self.RETVAL.open('rb') + try: + retval_data = retval.read() + finally: + retval.close() + retval = marshal.loads(retval_data) + else: + retval = None + stdout = self.STDOUT.read() + stderr = self.STDERR.read() + self._removetemp() + return Result(exitstatus, signal, retval, stdout, stderr) + + def _removetemp(self): + if self.tempdir.check(): + self.tempdir.remove() + + def __del__(self): + if self.pid is not None: # only clean up in main process + self._removetemp() + + +class Result(object): + def __init__(self, exitstatus, signal, retval, stdout, stderr): + self.exitstatus = exitstatus + self.signal = signal + self.retval = retval + self.out = stdout + self.err = stderr diff --git a/tests/wpt/web-platform-tests/tools/py/py/_process/killproc.py b/tests/wpt/web-platform-tests/tools/py/py/_process/killproc.py new file mode 100644 index 00000000000..18e8310b5f6 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_process/killproc.py @@ -0,0 +1,23 @@ +import py +import os, sys + +if sys.platform == "win32" or getattr(os, '_name', '') == 'nt': + try: + import ctypes + except ImportError: + def dokill(pid): + py.process.cmdexec("taskkill /F /PID %d" %(pid,)) + else: + def dokill(pid): + PROCESS_TERMINATE = 1 + handle = ctypes.windll.kernel32.OpenProcess( + PROCESS_TERMINATE, False, pid) + ctypes.windll.kernel32.TerminateProcess(handle, -1) + ctypes.windll.kernel32.CloseHandle(handle) +else: + def dokill(pid): + os.kill(pid, 15) + +def kill(pid): + """ kill process by id. """ + dokill(pid) diff --git a/tests/wpt/web-platform-tests/tools/py/py/_std.py b/tests/wpt/web-platform-tests/tools/py/py/_std.py new file mode 100644 index 00000000000..97a9853323b --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_std.py @@ -0,0 +1,18 @@ +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 new file mode 100644 index 00000000000..2ffcaa14b8e --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/_xmlgen.py @@ -0,0 +1,253 @@ +""" +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('') % 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>') % (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('"'), u('<') : u('<'), u('>') : u('>'), + u('&') : u('&'), u("'") : u('''), + } + 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/py/py/test.py new file mode 100644 index 00000000000..aa5beb1789f --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/py/test.py @@ -0,0 +1,10 @@ +import sys +if __name__ == '__main__': + import pytest + sys.exit(pytest.main()) +else: + import sys, pytest + sys.modules['py.test'] = pytest + +# for more API entry points see the 'tests' definition +# in __init__.py diff --git a/tests/wpt/web-platform-tests/tools/py/setup.cfg b/tests/wpt/web-platform-tests/tools/py/setup.cfg new file mode 100644 index 00000000000..272e488f363 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/setup.cfg @@ -0,0 +1,5 @@ +[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 new file mode 100644 index 00000000000..06f0885cd71 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/setup.py @@ -0,0 +1,38 @@ +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 new file mode 100644 index 00000000000..e2154d0fc7a --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/code/test_assertion.py @@ -0,0 +1,308 @@ +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 '' + +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 "" + def myany(x): + return True + try: + assert not(myany(A() < 0)) + except AssertionError: + e = exvalue() + s = str(e) + assert " < 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/py/testing/code/test_code.py new file mode 100644 index 00000000000..28ec628b00d --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/code/test_code.py @@ -0,0 +1,159 @@ +import py +import sys + +def test_ne(): + code1 = py.code.Code(compile('foo = "bar"', '', 'exec')) + assert code1 == code1 + code2 = py.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 = py.code.Code(co_code) + assert str(code.path) == name + assert code.fullsource is None + +def test_code_with_class(): + class A: + pass + py.test.raises(TypeError, "py.code.Code(A)") + +if True: + def x(): + pass + +def test_code_fullsource(): + code = py.code.Code(x) + full = code.fullsource + assert 'test_code_fullsource()' in str(full) + +def test_code_source(): + code = py.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 = py.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 = py.code.Frame(f) + prop = f.code.__class__.fullsource + try: + f.code.__class__.fullsource = None + assert f.statement == py.code.Source("") + finally: + f.code.__class__.fullsource = prop + +def test_code_from_func(): + co = py.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) + py.code.patch_builtins() + assert cpy_builtin.AssertionError != Sub + assert cpy_builtin.compile != mycompile + py.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 = py.test.raises(Exception, f) + s = str(excinfo) + if sys.version_info[0] < 3: + u = unicode(excinfo) + +def test_code_getargs(): + def f1(x): + pass + c1 = py.code.Code(f1) + assert c1.getargs(var=True) == ('x',) + + def f2(x, *y): + pass + c2 = py.code.Code(f2) + assert c2.getargs(var=True) == ('x', 'y') + + def f3(x, **z): + pass + c3 = py.code.Code(f3) + assert c3.getargs(var=True) == ('x', 'z') + + def f4(x, *y, **z): + pass + c4 = py.code.Code(f4) + assert c4.getargs(var=True) == ('x', 'y', 'z') + + +def test_frame_getargs(): + def f1(x): + return sys._getframe(0) + fr1 = py.code.Frame(f1('a')) + assert fr1.getargs(var=True) == [('x', 'a')] + + def f2(x, *y): + return sys._getframe(0) + fr2 = py.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 = py.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 = py.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 = py.code.ExceptionInfo() + assert exci.getrepr() + + +class TestTracebackEntry: + + def test_getsource(self): + try: + if False: pass + else: assert False + except AssertionError: + exci = py.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/py/testing/code/test_excinfo.py b/tests/wpt/web-platform-tests/tools/py/testing/code/test_excinfo.py new file mode 100644 index 00000000000..65742c6f62e --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/code/test_excinfo.py @@ -0,0 +1,909 @@ +# -*- 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 == "" + +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 '':1 in ?\n ???\n" + else: + assert s == " File '':1 in \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__ = ' + 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 new file mode 100644 index 00000000000..830de2c95de --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/code/test_source.py @@ -0,0 +1,651 @@ +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, "", "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/conftest.py b/tests/wpt/web-platform-tests/tools/py/testing/conftest.py new file mode 100644 index 00000000000..0f956b3dd25 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/conftest.py @@ -0,0 +1,3 @@ + +pytest_plugins = "pytester", + diff --git a/tests/wpt/web-platform-tests/tools/py/testing/io_/__init__.py b/tests/wpt/web-platform-tests/tools/py/testing/io_/__init__.py new file mode 100644 index 00000000000..792d6005489 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/io_/__init__.py @@ -0,0 +1 @@ +# 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 new file mode 100644 index 00000000000..5745e12a1a1 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/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) + 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 new file mode 100644 index 00000000000..1ed9c4faf62 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/io_/test_saferepr.py @@ -0,0 +1,78 @@ +# -*- 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 new file mode 100644 index 00000000000..0a15541bd23 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/io_/test_terminalwriter.py @@ -0,0 +1,271 @@ + +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/__init__.py b/tests/wpt/web-platform-tests/tools/py/testing/log/__init__.py new file mode 100644 index 00000000000..e69de29bb2d 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 new file mode 100644 index 00000000000..b41bc3a5821 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/log/test_log.py @@ -0,0 +1,190 @@ +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 new file mode 100644 index 00000000000..8c89cf8adbb --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/log/test_warning.py @@ -0,0 +1,76 @@ +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 new file mode 100644 index 00000000000..4834fba12d0 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/path/common.py @@ -0,0 +1,470 @@ +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 new file mode 100644 index 00000000000..a9711b2ce30 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/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 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/repotest.dump b/tests/wpt/web-platform-tests/tools/py/testing/path/repotest.dump new file mode 100644 index 00000000000..c7819cad7a5 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/path/repotest.dump @@ -0,0 +1,228 @@ +SVN-fs-dump-format-version: 2 + +UUID: 876a30f4-1eed-0310-aeb7-ae314d1e5934 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2005-01-07T23:55:31.755989Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 118 +Content-length: 118 + +K 7 +svn:log +V 20 +testrepo setup rev 1 +K 10 +svn:author +V 3 +hpk +K 8 +svn:date +V 27 +2005-01-07T23:55:37.815386Z +PROPS-END + +Node-path: execfile +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 4 +Text-content-md5: d4b5bc61e16310f08c5d11866eba0a22 +Content-length: 14 + +PROPS-END +x=42 + +Node-path: otherdir +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: otherdir/__init__.py +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Content-length: 10 + +PROPS-END + + +Node-path: otherdir/a.py +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 30 +Text-content-md5: 247c7daeb2ee5dcab0aba7bd12bad665 +Content-length: 40 + +PROPS-END +from b import stuff as result + + +Node-path: otherdir/b.py +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 15 +Text-content-md5: c1b13503469a7711306d03a4b0721bc6 +Content-length: 25 + +PROPS-END +stuff="got it" + + +Node-path: otherdir/c.py +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 75 +Text-content-md5: 250cdb6b5df68536152c681f48297569 +Content-length: 85 + +PROPS-END +import py; py.magic.autopath() +import otherdir.a +value = otherdir.a.result + + +Node-path: otherdir/d.py +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 72 +Text-content-md5: 940c9c621e7b198e081459642c37f5a7 +Content-length: 82 + +PROPS-END +import py; py.magic.autopath() +from otherdir import a +value2 = a.result + + +Node-path: sampledir +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: sampledir/otherfile +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Content-length: 10 + +PROPS-END + + +Node-path: samplefile +Node-kind: file +Node-action: add +Prop-content-length: 40 +Text-content-length: 11 +Text-content-md5: 9225ac28b32156979ab6482b8bb5fb8c +Content-length: 51 + +K 13 +svn:eol-style +V 6 +native +PROPS-END +samplefile + + +Node-path: samplepickle +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 56 +Text-content-md5: 719d85c1329a33134bb98f56b756c545 +Content-length: 66 + +PROPS-END +(dp1 +S'answer' +p2 +I42 +sI1 +I2 +sS'hello' +p3 +S'world' +p4 +s. + +Revision-number: 2 +Prop-content-length: 108 +Content-length: 108 + +K 7 +svn:log +V 10 +second rev +K 10 +svn:author +V 3 +hpk +K 8 +svn:date +V 27 +2005-01-07T23:55:39.223202Z +PROPS-END + +Node-path: anotherfile +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 5 +Text-content-md5: 5d41402abc4b2a76b9719d911017c592 +Content-length: 15 + +PROPS-END +hello + +Revision-number: 3 +Prop-content-length: 106 +Content-length: 106 + +K 7 +svn:log +V 9 +third rev +K 10 +svn:author +V 3 +hpk +K 8 +svn:date +V 27 +2005-01-07T23:55:41.556642Z +PROPS-END + +Node-path: anotherfile +Node-kind: file +Node-action: change +Text-content-length: 5 +Text-content-md5: 7d793037a0760186574b0282f2f435e7 +Content-length: 5 + +world + diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/svntestbase.py b/tests/wpt/web-platform-tests/tools/py/testing/path/svntestbase.py new file mode 100644 index 00000000000..8d94a9ca649 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/path/svntestbase.py @@ -0,0 +1,31 @@ +import sys +import py +from py._path import svnwc as svncommon +from common import CommonFSTests + +class CommonSvnTests(CommonFSTests): + + def test_propget(self, path1): + url = path1.join("samplefile") + value = url.propget('svn:eol-style') + assert value == 'native' + + def test_proplist(self, path1): + url = path1.join("samplefile") + res = url.proplist() + assert res['svn:eol-style'] == 'native' + + def test_info(self, path1): + url = path1.join("samplefile") + res = url.info() + assert res.size > len("samplefile") and res.created_rev >= 0 + + def test_log_simple(self, path1): + url = path1.join("samplefile") + logentries = url.log() + for logentry in logentries: + assert logentry.rev == 1 + assert hasattr(logentry, 'author') + assert hasattr(logentry, 'date') + +#cache.repositories.put(svnrepourl, 1200, 0) 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 new file mode 100644 index 00000000000..0b5cd31332f --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/path/test_cacheutil.py @@ -0,0 +1,84 @@ +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 new file mode 100644 index 00000000000..bcf131fd2b7 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/path/test_local.py @@ -0,0 +1,860 @@ +# -*- 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 new file mode 100644 index 00000000000..b3f36656168 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnauth.py @@ -0,0 +1,454 @@ +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('''\ + + + +guido +2008-02-11T12:12:18.476481Z +Creating branch to work on auth support for py.path.svn*. + + + +''', '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_svnurl.py b/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnurl.py new file mode 100644 index 00000000000..15fbea5047d --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnurl.py @@ -0,0 +1,95 @@ +import py +from py._path.svnurl import InfoSvnCommand +import datetime +import time +from svntestbase import CommonSvnTests + +def pytest_funcarg__path1(request): + repo, repourl, wc = request.getfuncargvalue("repowc1") + return py.path.svnurl(repourl) + +class TestSvnURLCommandPath(CommonSvnTests): + @py.test.mark.xfail + def test_load(self, path1): + super(TestSvnURLCommandPath, self).test_load(path1) + + # the following two work on jython but not in local/svnwc + def test_listdir(self, path1): + super(TestSvnURLCommandPath, self).test_listdir(path1) + def test_visit_ignore(self, path1): + super(TestSvnURLCommandPath, self).test_visit_ignore(path1) + + def test_svnurl_needs_arg(self, path1): + py.test.raises(TypeError, "py.path.svnurl()") + + def test_svnurl_does_not_accept_None_either(self, path1): + py.test.raises(Exception, "py.path.svnurl(None)") + + def test_svnurl_characters_simple(self, path1): + py.path.svnurl("svn+ssh://hello/world") + + def test_svnurl_characters_at_user(self, path1): + py.path.svnurl("http://user@host.com/some/dir") + + def test_svnurl_characters_at_path(self, path1): + py.test.raises(ValueError, 'py.path.svnurl("http://host.com/foo@bar")') + + def test_svnurl_characters_colon_port(self, path1): + py.path.svnurl("http://host.com:8080/some/dir") + + def test_svnurl_characters_tilde_end(self, path1): + py.path.svnurl("http://host.com/some/file~") + + @py.test.mark.xfail("sys.platform == 'win32'") + def test_svnurl_characters_colon_path(self, path1): + # colons are allowed on win32, because they're part of the drive + # part of an absolute path... however, they shouldn't be allowed in + # other parts, I think + py.test.raises(ValueError, 'py.path.svnurl("http://host.com/foo:bar")') + + def test_export(self, path1, tmpdir): + tmpdir = tmpdir.join("empty") + p = path1.export(tmpdir) + assert p == tmpdir # XXX should return None + n1 = [x.basename for x in tmpdir.listdir()] + n2 = [x.basename for x in path1.listdir()] + n1.sort() + n2.sort() + assert n1 == n2 + assert not p.join('.svn').check() + rev = path1.mkdir("newdir") + tmpdir.remove() + assert not tmpdir.check() + path1.new(rev=1).export(tmpdir) + for p in tmpdir.listdir(): + assert p.basename in n2 + +class TestSvnInfoCommand: + + def test_svn_1_2(self): + line = " 2256 hpk 165 Nov 24 17:55 __init__.py" + info = InfoSvnCommand(line) + now = datetime.datetime.now() + assert info.last_author == 'hpk' + assert info.created_rev == 2256 + assert info.kind == 'file' + # we don't check for the year (2006), because that depends + # on the clock correctly being setup + assert time.gmtime(info.mtime)[1:6] == (11, 24, 17, 55, 0) + assert info.size == 165 + assert info.time == info.mtime * 1000000 + + def test_svn_1_3(self): + line =" 4784 hpk 2 Jun 01 2004 __init__.py" + info = InfoSvnCommand(line) + assert info.last_author == 'hpk' + assert info.kind == 'file' + + def test_svn_1_3_b(self): + line =" 74 autoadmi Oct 06 23:59 plonesolutions.com/" + info = InfoSvnCommand(line) + assert info.last_author == 'autoadmi' + assert info.kind == 'dir' + +def test_badchars(): + py.test.raises(ValueError, "py.path.svnurl('http://host/tmp/@@@:')") 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 new file mode 100644 index 00000000000..9e6b524acab --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnwc.py @@ -0,0 +1,549 @@ +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 = '''\ + + + + 2008-08-19T16:50:53.400198Z + + + + ''' + XMLWCStatus.fromstring(xml, path1) + + def test_status_wrong_xml(self, path1): + # testing for XML without author - this used to raise an exception + xml = '\n\n\n' + 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/py/testing/process/__init__.py new file mode 100644 index 00000000000..792d6005489 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/process/__init__.py @@ -0,0 +1 @@ +# 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 new file mode 100644 index 00000000000..b539e0af381 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/process/test_cmdexec.py @@ -0,0 +1,39 @@ +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 new file mode 100644 index 00000000000..d4f9f985e0f --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/process/test_forkedfunc.py @@ -0,0 +1,177 @@ +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 new file mode 100644 index 00000000000..57088e1db8c --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/process/test_killproc.py @@ -0,0 +1,16 @@ + +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/__init__.py b/tests/wpt/web-platform-tests/tools/py/testing/root/__init__.py new file mode 100644 index 00000000000..792d6005489 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/root/__init__.py @@ -0,0 +1 @@ +# diff --git a/tests/wpt/web-platform-tests/tools/py/testing/root/test_builtin.py b/tests/wpt/web-platform-tests/tools/py/testing/root/test_builtin.py new file mode 100644 index 00000000000..a6f1a3c7399 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/root/test_builtin.py @@ -0,0 +1,179 @@ +import sys +import types +import py +from py.builtin import set, frozenset, reversed, sorted + +def test_enumerate(): + l = [0,1,2] + for i,x in enumerate(l): + assert i == x + +def test_any(): + assert not py.builtin.any([0,False, None]) + assert py.builtin.any([0,False, None,1]) + +def test_all(): + assert not py.builtin.all([True, 1, False]) + assert py.builtin.all([True, 1, object]) + +def test_BaseException(): + assert issubclass(IndexError, py.builtin.BaseException) + assert issubclass(Exception, py.builtin.BaseException) + assert issubclass(KeyboardInterrupt, py.builtin.BaseException) + + class MyRandomClass(object): + pass + assert not issubclass(MyRandomClass, py.builtin.BaseException) + + assert py.builtin.BaseException.__module__ in ('exceptions', 'builtins') + assert Exception.__name__ == 'Exception' + + +def test_GeneratorExit(): + assert py.builtin.GeneratorExit.__module__ in ('exceptions', 'builtins') + assert issubclass(py.builtin.GeneratorExit, py.builtin.BaseException) + +def test_reversed(): + reversed = py.builtin.reversed + r = reversed("hello") + assert iter(r) is r + s = "".join(list(r)) + assert s == "olleh" + assert list(reversed(list(reversed("hello")))) == ['h','e','l','l','o'] + py.test.raises(TypeError, reversed, reversed("hello")) + +def test_simple(): + s = set([1, 2, 3, 4]) + assert s == set([3, 4, 2, 1]) + s1 = s.union(set([5, 6])) + assert 5 in s1 + assert 1 in s1 + +def test_frozenset(): + s = set([frozenset([0, 1]), frozenset([1, 0])]) + assert len(s) == 1 + +def test_sorted(): + if sorted == py.builtin.sorted: + return # don't test a real builtin + for s in [py.builtin.sorted]: + def test(): + assert s([3, 2, 1]) == [1, 2, 3] + assert s([1, 2, 3], reverse=True) == [3, 2, 1] + l = s([1, 2, 3, 4, 5, 6], key=lambda x: x % 2) + assert l == [2, 4, 6, 1, 3, 5] + l = s([1, 2, 3, 4], cmp=lambda x, y: -cmp(x, y)) + assert l == [4, 3, 2, 1] + l = s([1, 2, 3, 4], cmp=lambda x, y: -cmp(x, y), + key=lambda x: x % 2) + assert l == [1, 3, 2, 4] + + def compare(x, y): + assert type(x) == str + assert type(y) == str + return cmp(x, y) + data = 'The quick Brown fox Jumped over The lazy Dog'.split() + s(data, cmp=compare, key=str.lower) + yield test + + +def test_print_simple(): + from py.builtin import print_ + py.test.raises(TypeError, "print_(hello=3)") + f = py.io.TextIO() + print_("hello", "world", file=f) + s = f.getvalue() + assert s == "hello world\n" + + f = py.io.TextIO() + print_("hello", end="", file=f) + s = f.getvalue() + assert s == "hello" + + f = py.io.TextIO() + print_("xyz", "abc", sep="", end="", file=f) + s = f.getvalue() + assert s == "xyzabc" + + class X: + def __repr__(self): return "rep" + f = py.io.TextIO() + print_(X(), file=f) + assert f.getvalue() == "rep\n" + +def test_execfile(tmpdir): + test_file = tmpdir.join("test.py") + test_file.write("x = y\ndef f(): pass") + ns = {"y" : 42} + py.builtin.execfile(str(test_file), ns) + assert ns["x"] == 42 + assert py.code.getrawcode(ns["f"]).co_filename == str(test_file) + class A: + y = 3 + x = 4 + py.builtin.execfile(str(test_file)) + assert A.x == 3 + +def test_getfuncdict(): + def f(): + pass + f.x = 4 + assert py.builtin._getfuncdict(f)["x"] == 4 + assert py.builtin._getfuncdict(2) is None + +def test_callable(): + class A: pass + assert py.builtin.callable(test_callable) + assert py.builtin.callable(A) + assert py.builtin.callable(list) + assert py.builtin.callable(id) + assert not py.builtin.callable(4) + assert not py.builtin.callable("hi") + +def test_totext(): + py.builtin._totext("hello", "UTF-8") + +def test_bytes_text(): + if sys.version_info[0] < 3: + assert py.builtin.text == unicode + assert py.builtin.bytes == str + else: + assert py.builtin.text == str + assert py.builtin.bytes == bytes + +def test_totext_badutf8(): + # this was in printouts within the pytest testsuite + # totext would fail + if sys.version_info >= (3,): + errors = 'surrogateescape' + else: # old python has crappy error handlers + errors = 'replace' + py.builtin._totext("\xa6", "UTF-8", errors) + +def test_reraise(): + from py.builtin import _reraise + try: + raise Exception() + except Exception: + cls, val, tb = sys.exc_info() + excinfo = py.test.raises(Exception, "_reraise(cls, val, tb)") + +def test_exec(): + l = [] + py.builtin.exec_("l.append(1)") + assert l == [1] + d = {} + py.builtin.exec_("x=4", d) + assert d['x'] == 4 + +def test_tryimport(): + py.test.raises(ImportError, py.builtin._tryimport, 'xqwe123') + x = py.builtin._tryimport('asldkajsdl', 'py') + assert x == py + x = py.builtin._tryimport('asldkajsdl', 'py.path') + assert x == py.path + +def test_getcode(): + code = py.builtin._getcode(test_getcode) + assert isinstance(code, types.CodeType) + assert py.builtin._getcode(4) is None 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 new file mode 100644 index 00000000000..a34e0068d92 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/root/test_error.py @@ -0,0 +1,37 @@ + +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 new file mode 100644 index 00000000000..5f5954e9943 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/root/test_py_imports.py @@ -0,0 +1,68 @@ +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_std.py b/tests/wpt/web-platform-tests/tools/py/testing/root/test_std.py new file mode 100644 index 00000000000..143556a0557 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/root/test_std.py @@ -0,0 +1,13 @@ + +import py + +def test_os(): + import os + assert py.std.os is os + +def test_import_error_converts_to_attributeerror(): + py.test.raises(AttributeError, "py.std.xyzalskdj") + +def test_std_gets_it(): + for x in py.std.sys.modules: + assert x in py.std.__dict__ 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 new file mode 100644 index 00000000000..704d1492cb3 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/root/test_xmlgen.py @@ -0,0 +1,145 @@ + +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 == "world" + +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 == '' + +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) == '' + +def test_tag_with_raw_attr(): + x = html.object(data=raw('&')) + assert unicode(x) == '' + +def test_tag_nested(): + x = ns.hello(ns.world()) + unicode(x) # triggers parentifying + assert x[0].parent is x + u = unicode(x) + assert u == '' + +def test_list_nested(): + x = ns.hello([ns.world()]) #pass in a list here + u = unicode(x) + assert u == '' + +def test_tag_xmlname(): + class my(ns.hello): + xmlname = 'world' + u = unicode(my()) + assert u == '' + +def test_tag_with_text_entity(): + x = ns.hello('world & rest') + u = unicode(x) + assert u == "world & rest" + +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 == '' + +def test_raw(): + x = ns.some(py.xml.raw("

literal

")) + u = unicode(x) + assert u == "

literal

" + + +def test_html_name_stickyness(): + class my(html.p): + pass + x = my("hello") + assert unicode(x) == '

hello

' + +def test_stylenames(): + class my: + class body(html.body): + style = html.Style(font_size = "12pt") + u = unicode(my.body()) + assert u == '' + +def test_class_None(): + t = html.body(class_=None) + u = unicode(t) + assert u == '' + +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 == ('
  • hello
  • ' + '
  • world
  • ' + '
  • 42
  • ' + '
') + +def test_singleton(): + h = html.head(html.link(href="foo")) + assert unicode(h) == '' + + h = html.head(html.script(src="foo")) + assert unicode(h) == '' + +def test_inline(): + h = html.div(html.span('foo'), html.span('bar')) + assert (h.unicode(indent=2) == + '
foobar
') + +def test_object_tags(): + o = html.object(html.object()) + assert o.unicode(indent=0) == '' 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 new file mode 100644 index 00000000000..9a7f72c11b3 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/test_iniconfig.py @@ -0,0 +1,299 @@ +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: + username: + password: + + [other] + repository: http://example.com/pypi + username: + password: + ''')) + distutils, pypi, other = list(config) + assert distutils["index-servers"] == "pypi\nother" + assert pypi['repository'] == '' + assert pypi['username'] == '' + assert pypi['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 new file mode 100644 index 00000000000..8c0c79d6960 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/tox.ini @@ -0,0 +1,39 @@ +[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/webdriver/.gitignore b/tests/wpt/web-platform-tests/tools/webdriver/.gitignore new file mode 100644 index 00000000000..c99747ced28 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/webdriver/.gitignore @@ -0,0 +1 @@ +webdriver.egg-info/ diff --git a/tests/wpt/web-platform-tests/tools/webdriver/README.md b/tests/wpt/web-platform-tests/tools/webdriver/README.md new file mode 100644 index 00000000000..f5be793a8bb --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/webdriver/README.md @@ -0,0 +1,48 @@ +# WebDriver client for Python + +This package provides a WebDriver client compatible with + the [W3C browser automation specification](https://w3c.github.io/webdriver/webdriver-spec.html). + +The client is written with determining +implementation compliance to the specification in mind, +so that different remote end drivers +can determine whether they meet the recognised standard. +The client is used for the WebDriver specification tests +in the [Web Platform Tests](https://github.com/w3c/web-platform-tests). + +## Installation + +To install the package individually +in your virtualenv or system-wide:: + + % python setup.py install + +Or if you want to contribute patches:: + + % python setup.py develop + +If you are writing WebDriver specification tests for +[WPT](https://github.com/w3c/web-platform-tests), +there is no need to install the client manually +as it is picked up as a submodule to +[wpt-tools](https://github.com/w3c/wpt-tools) +that is checked out in `./tools`. + +## Usage + +```py +import webdriver + +session = webdriver.Session("127.0.0.1", "4444") +session.start() + +session.url = "https://mozilla.org" +print "The current URL is %s" % session.url + +session.end() +``` + +## Dependencies + +This client has the benefit of only using standard library dependencies. +No external PyPI dependencies are needed. diff --git a/tests/wpt/web-platform-tests/tools/webdriver/setup.py b/tests/wpt/web-platform-tests/tools/webdriver/setup.py new file mode 100644 index 00000000000..720fcf05cd2 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/webdriver/setup.py @@ -0,0 +1,18 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +from setuptools import setup, find_packages + +setup(name="webdriver", + version="1.0", + description="WebDriver client compatible with " + "the W3C browser automation specification.", + author="Mozilla Engineering Productivity", + author_email="tools@lists.mozilla.org", + license="MPL 2.0", + packages=find_packages(), + classifiers=["Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", + "Operating System :: OS Independent"]) diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/__init__.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/__init__.py index e69de29bb2d..c827f59f138 100644 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/__init__.py +++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/__init__.py @@ -0,0 +1,31 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +from client import Cookies, Element, Find, Session, Timeouts, Window +from error import ( + ElementNotSelectableException, + ElementNotVisibleException, + InvalidArgumentException, + InvalidCookieDomainException, + InvalidElementCoordinatesException, + InvalidElementStateException, + InvalidSelectorException, + InvalidSessionIdException, + JavascriptErrorException, + MoveTargetOutOfBoundsException, + NoSuchAlertException, + NoSuchElementException, + NoSuchFrameException, + NoSuchWindowException, + ScriptTimeoutException, + SessionNotCreatedException, + StaleElementReferenceException, + TimeoutException, + UnableToSetCookieException, + UnexpectedAlertOpenException, + UnknownCommandException, + UnknownErrorException, + UnknownMethodException, + UnsupportedOperationException, + WebDriverException) diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/alert.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/alert.py deleted file mode 100644 index 0dee3127d29..00000000000 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/alert.py +++ /dev/null @@ -1,26 +0,0 @@ -"""WebDriver alert handling.""" - -class Alert(object): - """Class that provides access to the WebDriver alert handling functions.""" - - def __init__(self, driver): - self._driver = driver - - def _execute(self, method, path, name, body=None): - return self._driver.execute(method, path, name, body) - - def dismiss(self): - """Dismiss the alert.""" - self._execute('POST', '/dismiss_alert', 'dismiss') - - def accept(self): - """Accept the alert.""" - self._execute('POST', '/accept_alert', 'accept') - - def get_text(self): - """Get the text displayed in the alert.""" - return self._execute('GET', '/alert_text', 'getText') - - def send_keys(self, keys): - """Type into the text input of the alert if available.""" - self._execute('POST', '/alert_text', 'sendKeys', { 'text': keys }) diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/capabilities.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/capabilities.py deleted file mode 100644 index 44bb1fd647d..00000000000 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/capabilities.py +++ /dev/null @@ -1,30 +0,0 @@ -"""Definition of various capability-related constants.""" - -class Capability: - """Standard capability names.""" - BROWSER_NAME = 'browserName' - BROWSER_VERSION = 'browserVersion' - PAGE_LOADING_STRATEGY = 'pageLoadingStrategy' - PLATFORM_NAME = 'platformName' - PLATFORM_VERSION = 'platformVersion' - SECURE_SSL = 'secureSsl' - TAKES_SCREENSHOT = 'takesScreenshot' - TAKE_ELEMENT_SCREENSHOT = 'takeElementScreenshot' - TOUCH_ENABLED = 'touchEnabled' - -class Platform: - """Standard OS names.""" - ANY = 'any' - ANDROID = 'android' - IOS = 'ios' - LINUX = 'linux' - MAC = 'mac' - UNIX = 'unix' - WINDOW = 'windows' - -class PageLoadingStrategy: - """Standard page loading strategies.""" - CONSERVATIVE = 'conservative' - NORMAL = 'normal' - EAGER = 'eager' - NONE = 'none' diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/client.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/client.py new file mode 100644 index 00000000000..49c7b280a9e --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/client.py @@ -0,0 +1,409 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import urlparse + +import transport + + +element_key = "element-6066-11e4-a52e-4f735466cecf" + + +def command(func): + def inner(self, *args, **kwargs): + if hasattr(self, "session"): + session = self.session + else: + session = self + + if session.session_id is None: + session.start() + assert session.session_id != None + + return func(self, *args, **kwargs) + + inner.__name__ = func.__name__ + inner.__doc__ = func.__doc__ + + return inner + + +class Timeouts(object): + def __init__(self, session): + self.session = session + self._script = 30 + self._load = 0 + self._implicit_wait = 0 + + def _set_timeouts(self, name, value): + body = {"type": name, + "ms": value * 1000} + return self.session.send_command("POST", "timeouts", body) + + @property + def script(self): + return self._script + + @script.setter + def script(self, value): + self._set_timeouts("script", value) + self._script = value + + @property + def load(self): + return self._load + + @load.setter + def set_load(self, value): + self._set_timeouts("page load", value) + self._script = value + + @property + def implicit_wait(self): + return self._implicit_wait + + @implicit_wait.setter + def implicit_wait(self, value): + self._set_timeouts("implicit wait", value) + self._implicit_wait = value + + +class Window(object): + def __init__(self, session): + self.session = session + + @property + @command + def size(self): + return self.session.send_command("GET", "window/size") + + @size.setter + @command + def size(self, (height, width)): + body = {"width": width, + "height": height} + + return self.session.send_command("POST", "window/size", body) + + @property + @command + def maximize(self): + return self.session.send_command("POST", "window/maximize") + + +class Find(object): + def __init__(self, session): + self.session = session + + @command + def css(self, selector, all=True): + return self._find_element("css selector", selector, all) + + def _find_element(self, strategy, selector, all): + route = "elements" if all else "element" + + body = {"using": strategy, + "value": selector} + + data = self.session.send_command("POST", route, body, key="value") + + if all: + rv = [self.session._element(item) for item in data] + else: + rv = self.session._element(data) + + return rv + + +class Cookies(object): + def __init__(self, session): + self.session = session + + def __getitem__(self, name): + self.session.send_command("GET", "cookie/%s" % name, {}, key="value") + + def __setitem__(self, name, value): + cookie = {"name": name, + "value": None} + + if isinstance(name, (str, unicode)): + cookie["value"] = value + elif hasattr(value, "value"): + cookie["value"] = value.value + self.session.send_command("POST", "cookie/%s" % name, {}, key="value") + + +class Session(object): + def __init__(self, host, port, url_prefix="", desired_capabilities=None, + required_capabilities=None, timeout=60, extension=None): + self.transport = transport.HTTPWireProtocol( + host, port, url_prefix, timeout=timeout) + self.desired_capabilities = desired_capabilities + self.required_capabilities = required_capabilities + self.session_id = None + self.timeouts = None + self.window = None + self.find = None + self._element_cache = {} + self.extension = None + self.extension_cls = extension + + def start(self): + if self.session_id is not None: + return + + body = {} + + caps = {} + if self.desired_capabilities is not None: + caps["desiredCapabilities"] = self.desired_capabilities + if self.required_capabilities is not None: + caps["requiredCapabilities"] = self.required_capabilities + body["capabilities"] = caps + + resp = self.transport.send("POST", "session", body=body) + self.session_id = resp["sessionId"] + + self.timeouts = Timeouts(self) + self.window = Window(self) + self.find = Find(self) + if self.extension_cls: + self.extension = self.extension_cls(self) + + return resp["value"] + + def end(self): + if self.session_id is None: + return + + url = "session/%s" % self.session_id + self.transport.send("DELETE", url) + + self.session_id = None + self.timeouts = None + self.window = None + self.find = None + self.extension = None + self.transport.disconnect() + + def __enter__(self): + resp = self.start() + if resp.error: + raise Exception(resp) + return self + + def __exit__(self, *args, **kwargs): + resp = self.end() + if resp.error: + raise Exception(resp) + + def send_command(self, method, url, body=None, key=None): + url = urlparse.urljoin("session/%s/" % self.session_id, url) + return self.transport.send(method, url, body, key=key) + + @property + @command + def url(self): + return self.send_command("GET", "url", key="value") + + @url.setter + @command + def url(self, url): + if urlparse.urlsplit(url).netloc is None: + return self.url(url) + body = {"url": url} + return self.send_command("POST", "url", body) + + @command + def back(self): + return self.send_command("POST", "back") + + @command + def forward(self): + return self.send_command("POST", "forward") + + @command + def refresh(self): + return self.send_command("POST", "refresh") + + @property + @command + def title(self): + return self.send_command("GET", "title", key="value") + + @property + @command + def window_handle(self): + return self.send_command("GET", "window_handle", key="value") + + @window_handle.setter + @command + def window_handle(self, handle): + body = {"handle": handle} + return self.send_command("POST", "window", body=body) + + def switch_frame(self, frame): + if frame == "parent": + url = "frame/parent" + body = None + else: + url = "frame" + if isinstance(frame, Element): + body = {"id": frame.json()} + else: + body = {"id": frame} + + return self.send_command("POST", url, body) + + @command + def close(self): + return self.send_command("DELETE", "window_handle") + + @property + @command + def handles(self): + return self.send_command("GET", "window_handles", key="value") + + @property + @command + def active_element(self): + data = self.send_command("GET", "element/active", key="value") + if data is not None: + return self._element(data) + + def _element(self, data): + elem_id = data[element_key] + assert elem_id + if elem_id in self._element_cache: + return self._element_cache[elem_id] + return Element(self, elem_id) + + @command + def cookies(self, name=None): + if name is None: + url = "cookie" + else: + url = "cookie/%s" % name + return self.send_command("GET", url, {}, key="value") + + @command + def set_cookie(self, name, value, path=None, domain=None, secure=None, expiry=None): + body = {"name": name, + "value": value} + if path is not None: + body["path"] = path + if domain is not None: + body["domain"] = domain + if secure is not None: + body["secure"] = secure + if expiry is not None: + body["expiry"] = expiry + self.send_command("POST", "cookie", {"cookie": body}) + + def delete_cookie(self, name=None): + if name is None: + url = "cookie" + else: + url = "cookie/%s" % name + self.send_command("DELETE", url, {}, key="value") + + #[...] + + @command + def execute_script(self, script, args=None): + if args is None: + args = [] + + body = { + "script": script, + "args": args + } + return self.send_command("POST", "execute", body, key="value") + + @command + def execute_async_script(self, script, args=None): + if args is None: + args = [] + + body = { + "script": script, + "args": args + } + return self.send_command("POST", "execute_async", body, key="value") + + #[...] + + @command + def screenshot(self): + return self.send_command("GET", "screenshot", key="value") + + +class Element(object): + def __init__(self, session, id): + self.session = session + self.id = id + assert id not in self.session._element_cache + self.session._element_cache[self.id] = self + + def json(self): + return {element_key: self.id} + + @property + def session_id(self): + return self.session.session_id + + def url(self, suffix): + return "element/%s/%s" % (self.id, suffix) + + @command + def find_element(self, strategy, selector): + body = {"using": strategy, + "value": selector} + + elem = self.session.send_command("POST", self.url("element"), body, key="value") + return self.session.element(elem) + + @command + def click(self): + self.session.send_command("POST", self.url("click"), {}) + + @command + def tap(self): + self.session.send_command("POST", self.url("tap"), {}) + + @command + def clear(self): + self.session.send_command("POST", self.url("clear"), {}) + + @command + def send_keys(self, keys): + if isinstance(keys, (str, unicode)): + keys = [char for char in keys] + + body = {"value": keys} + + return self.session.send_command("POST", self.url("value"), body) + + @property + @command + def text(self): + return self.session.send_command("GET", self.url("text")) + + @property + @command + def name(self): + return self.session.send_command("GET", self.url("name")) + + @command + def style(self, property_name): + return self.session.send_command("GET", self.url("css/%s" % property_name)) + + @property + @command + def rect(self): + return self.session.send_command("GET", self.url("rect")) + + @command + def attribute(self, name): + return self.session.send_command("GET", self.url("attribute/%s" % name)) diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/command.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/command.py deleted file mode 100644 index 4ea162fea12..00000000000 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/command.py +++ /dev/null @@ -1,111 +0,0 @@ -"""Dispatches requests to remote WebDriver endpoint.""" - -import exceptions - -import httplib -import json -import urlparse -import webelement - -class CommandExecutor(object): - """Dispatches requests to remote WebDriver endpoint.""" - - _HEADERS = { - "User-Agent": "Python WebDriver Local End", - "Content-Type": "application/json;charset=\"UTF-8\"", - "Accept": "application/json", - "Accept-Charset": "utf-8", - "Accept-Encoding": "identity", - "Connection": "close", - } - - def __init__(self, url, mode='strict'): - self._parsed_url = urlparse.urlparse(url) - self._conn = httplib.HTTPConnection(self._parsed_url.hostname, - self._parsed_url.port) - self._mode = mode - - def execute(self, - method, - path, - session_id, - name, - parameters=None, - object_hook=None): - """Execute a command against the WebDriver endpoint. - - Arguments: - method -- one of GET, POST, DELETE - path -- the path of the url endpoint (needs to include - session/ if needed) - session_id -- the sessionId to include in the JSON body - name -- name of the command that is being executed to include in - the JSON body - parameters -- the JSON body to send with the command. Only used if - method is POST - object_hook -- function used by json.loads to properly deserialize - objects in the request - """ - if self._mode == 'strict': - return self._execute_strict( - method, path, session_id, name, parameters, object_hook) - elif self._mode == 'compatibility': - return self._execute_compatibility( - method, path, session_id, name, parameters, object_hook) - else: - raise Exception("Unknown mode: " + self._mode) - - def _execute_compatibility(self, - method, - path, - session_id, - name, - parameters, - object_hook): - body = {'sessionId': session_id, 'name': name } - if parameters: - body.update(parameters) - - self._conn.request( - method, - self._parsed_url.path + path, - json.dumps(body, default = self._json_encode).encode('utf-8'), - self._HEADERS) - resp = self._conn.getresponse() - data = resp.read().decode('utf-8') - if data: - data = json.loads(data, object_hook = object_hook) - if data['status'] != 0: - raise exceptions.create_webdriver_exception_compatibility( - data['status'], data['value']['message']) - return data - if resp.status < 200 or resp.status > 299: - raise exceptions.create_webdriver_exception_compatibility( - resp.status, resp.reason) - - def _execute_strict(self, - method, - path, - session_id, - name, - parameters, - object_hook): - body = { - 'sessionId': session_id, - 'name': name, - 'parameters': parameters } - self._conn.request( - method, - self._parsed_url.path + path, - json.dumps(body, default = self._json_encode).encode('utf-8'), - self._HEADERS) - resp = self._conn.getresponse() - data = json.loads( - resp.read().decode('utf-8'), object_hook = object_hook) - if data['status'] != 'success': - raise exceptions.create_webdriver_exception_strict( - data['status'], data['value']) - return data - - def _json_encode(self, obj): - return obj.to_json() diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/driver.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/driver.py deleted file mode 100644 index 27d543ed22b..00000000000 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/driver.py +++ /dev/null @@ -1,199 +0,0 @@ -"""Entry point for WebDriver.""" - -import alert -import command -import searchcontext -import webelement - -import base64 - - -class WebDriver(searchcontext.SearchContext): - """Controls a web browser.""" - - def __init__(self, host, required, desired, mode='strict'): - args = { 'desiredCapabilities': desired } - if required: - args['requiredCapabilities'] = required - - self._executor = command.CommandExecutor(host, mode) - - resp = self._executor.execute( - 'POST', '/session', None, 'newSession', args) - self.capabilities = resp['value'] - self._session_id = resp['sessionId'] - self.mode = mode - - def execute(self, method, path, name, parameters= None): - """Execute a command against the current WebDriver session.""" - data = self._executor.execute( - method, - '/session/' + self._session_id + path, - self._session_id, - name, - parameters, - self._object_hook) - if data: - return data['value'] - - def get(self, url): - """Navigate to url.""" - self.execute('POST', '/url', 'get', { 'url': url }) - - def get_current_url(self): - """Get the current value of the location bar.""" - return self.execute('GET', '/url', 'getCurrentUrl') - - def go_back(self): - """Hit the browser back button.""" - self.execute('POST', '/back', 'goBack') - - def go_forward(self): - """Hit the browser forward button.""" - self.execute('POST', '/forward', 'goForward') - - def refresh(self): - """Refresh the current page in the browser.""" - self.execute('POST', '/refresh', 'refresh') - - def quit(self): - """Shutdown the current WebDriver session.""" - self.execute('DELETE', '', 'quit') - - def get_window_handle(self): - """Get the handle for the browser window/tab currently accepting - commands. - """ - return self.execute('GET', '/window_handle', 'getWindowHandle') - - def get_window_handles(self): - """Get handles for all open windows/tabs.""" - return self.execute('GET', '/window_handles', 'getWindowHandles') - - def close(self): - """Close the current tab or window. - - If this is the last tab or window, then this is the same as - calling quit. - """ - self.execute('DELETE', '/window', 'close') - - def maximize_window(self): - """Maximize the current window.""" - return self._window_command('POST', '/maximize', 'maximize') - - def get_window_size(self): - """Get the dimensions of the current window.""" - result = self._window_command('GET', '/size', 'getWindowSize') - return {'height': result['height'], 'width': result['width']} - - def set_window_size(self, height, width): - """Set the size of the current window.""" - self._window_command( - 'POST', - '/size', - 'setWindowSize', - { 'height': height, 'width': width}) - - def fullscreen_window(self): - """Make the current window fullscreen.""" - pass # implement when end point is defined - - def switch_to_window(self, name): - """Switch to the window with the given handle or name.""" - self.execute('POST', '/window', 'switchToWindow', { 'name': name }) - - def switch_to_frame(self, id): - """Switch to a frame. - - id can be either a WebElement or an integer. - """ - self.execute('POST', '/frame', 'switchToFrame', { 'id': id}) - - def switch_to_parent_frame(self): - """Move to the browsing context containing the currently selected frame. - - If in the top-level browsing context, this is a no-op. - """ - self.execute('POST', '/frame/parent', 'switchToParentFrame') - - def switch_to_alert(self): - """Return an Alert object to interact with a modal dialog.""" - alert_ = alert.Alert(self) - alert_.get_text() - return alert_ - - def execute_script(self, script, args=[]): - """Execute a Javascript script in the current browsing context.""" - return self.execute( - 'POST', - '/execute', - 'executeScript', - { 'script': script, 'args': args }) - - def execute_script_async(self, script, args=[]): - """Execute a Javascript script in the current browsing context.""" - return self.execute( - 'POST', - '/execute_async', - 'executeScriptAsync', - { 'script': script, 'args': args }) - - def take_screenshot(self, element=None): - """Take a screenshot. - - If element is not provided, the screenshot should be of the - current page, otherwise the screenshot should be of the given element. - """ - if self.mode == 'strict': - pass # implement when endpoint is defined - elif self.mode == 'compatibility': - if element: - pass # element screenshots are unsupported in compatibility - else: - return base64.standard_b64decode( - self.execute('GET', '/screenshot', 'takeScreenshot')) - - def add_cookie(self, cookie): - """Add a cookie to the browser.""" - self.execute('POST', '/cookie', 'addCookie', { 'cookie': cookie }) - - def get_cookie(self, name = None): - """Get the cookies accessible from the current page.""" - if self.mode == 'compatibility': - cookies = self.execute('GET', '/cookie', 'getCookie') - if name: - cookies_ = [] - for cookie in cookies: - if cookie['name'] == name: - cookies_.append(cookie) - return cookies_ - return cookies - elif self.mode == 'strict': - pass # implement when wire protocol for this has been defined - - def set_implicit_timeout(self, ms): - self._set_timeout('implicit', ms) - - def set_page_load_timeout(self, ms): - self._set_timeout('page load', ms) - - def set_script_timeout(self, ms): - self._set_timeout('script', ms) - - def _set_timeout(self, type, ms): - params = { 'type': type, 'ms': ms } - self.execute('POST', '/timeouts', 'timeouts', params) - - def _window_command(self, method, path, name, parameters = None): - if self.mode == 'compatibility': - return self.execute( - method, '/window/current' + path, name, parameters) - elif self.mode == 'strict': - pass # implement this when end-points are defined in doc - - def _object_hook(self, obj): - if 'ELEMENT' in obj: - return webelement.WebElement(self, obj['ELEMENT']) - return obj - diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py new file mode 100644 index 00000000000..dc168f3ef4d --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py @@ -0,0 +1,144 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + + +import collections + + +class WebDriverException(Exception): + http_status = None + status_code = None + + +class ElementNotSelectableException(WebDriverException): + http_status = 400 + status_code = "element not selectable" + + +class ElementNotVisibleException(WebDriverException): + http_status = 400 + status_code = "element not visible" + + +class InvalidArgumentException(WebDriverException): + http_status = 400 + status_code = "invalid argument" + + +class InvalidCookieDomainException(WebDriverException): + http_status = 400 + status_code = "invalid cookie domain" + + +class InvalidElementCoordinatesException(WebDriverException): + http_status = 400 + status_code = "invalid element coordinates" + + +class InvalidElementStateException(WebDriverException): + http_status = 400 + status_code = "invalid cookie domain" + + +class InvalidSelectorException(WebDriverException): + http_status = 400 + status_code = "invalid selector" + + +class InvalidSessionIdException(WebDriverException): + http_status = 404 + status_code = "invalid session id" + + +class JavascriptErrorException(WebDriverException): + http_status = 500 + status_code = "javascript error" + + +class MoveTargetOutOfBoundsException(WebDriverException): + http_status = 500 + status_code = "move target out of bounds" + + +class NoSuchAlertException(WebDriverException): + http_status = 400 + status_code = "no such alert" + + +class NoSuchElementException(WebDriverException): + http_status = 404 + status_code = "no such element" + + +class NoSuchFrameException(WebDriverException): + http_status = 400 + status_code = "no such frame" + + +class NoSuchWindowException(WebDriverException): + http_status = 400 + status_code = "no such window" + + +class ScriptTimeoutException(WebDriverException): + http_status = 408 + status_code = "script timeout" + + +class SessionNotCreatedException(WebDriverException): + http_status = 500 + status_code = "session not created" + + +class StaleElementReferenceException(WebDriverException): + http_status = 400 + status_code = "stale element reference" + + +class TimeoutException(WebDriverException): + http_status = 408 + status_code = "timeout" + + +class UnableToSetCookieException(WebDriverException): + http_status = 500 + status_code = "unable to set cookie" + + +class UnexpectedAlertOpenException(WebDriverException): + http_status = 500 + status_code = "unexpected alert open" + + +class UnknownErrorException(WebDriverException): + http_status = 500 + status_code = "unknown error" + + +class UnknownCommandException(WebDriverException): + http_status = 404 + status_code = "unknown command" + + +class UnknownMethodException(WebDriverException): + http_status = 405 + status_code = "unknown method" + + +class UnsupportedOperationException(WebDriverException): + http_status = 500 + status_code = "unsupported operation" + + +def get(status_code): + """Gets exception from `status_code`, falling back to + ``WebDriverException`` if it is not found. + """ + return _errors.get(status_code, WebDriverException) + + +_errors = collections.defaultdict() +for item in locals().values(): + if type(item) == type and issubclass(item, WebDriverException): + _errors[item.status_code] = item diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/exceptions.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/exceptions.py deleted file mode 100644 index 33f63ea5811..00000000000 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/exceptions.py +++ /dev/null @@ -1,166 +0,0 @@ -"""Definition of WebDriverException classes.""" - -def create_webdriver_exception_strict(status_code, message): - """Create the appropriate WebDriverException given the status_code.""" - if status_code in _exceptions_strict: - return _exceptions_strict[status_code](message) - return UnknownStatusCodeException("[%s] %s" % (status_code, message)) - -def create_webdriver_exception_compatibility(status_code, message): - """Create the appropriate WebDriverException given the status_code.""" - if status_code in _exceptions_compatibility: - return _exceptions_compatibility[status_code](message) - return UnknownStatusCodeException("[%s] %s" % (status_code, message)) - -class WebDriverException(Exception): - """Base class for all WebDriverExceptions.""" - -class UnableToSetCookieException(WebDriverException): - """A request to set a cookie's value could not be satisfied.""" - -class InvalidElementStateException(WebDriverException): - """An element command could not be completed because the element is - in an invalid state (e.g. attempting to click an element that is no - longer attached to the DOM). - """ - -class NoSuchElementException(WebDriverException): - """An element could not be located on the page using the given - search parameters. - """ - -class TimeoutException(WebDriverException): - """An operation did not complete before its timeout expired.""" - -class ElementNotSelectableException(InvalidElementStateException): - """An attempt was made to select an element that cannot be selected.""" - -class ElementNotVisibleException(InvalidElementStateException): - """An element command could not be completed because the element is - not visible on the page. - """ - -class ImeEngineActivationFailedException(WebDriverException): - """An IME engine could not be started.""" - -class ImeNotAvailableException(ImeEngineActivationFailedException): - """IME was not available.""" - -class InvalidCookieDomainException(UnableToSetCookieException): - """An illegal attempt was made to set a cookie under a different - domain than the current page. - """ - -class InvalidElementCoordinatesException(WebDriverException): - """The coordinates provided to an interactions operation are invalid.""" - -class InvalidSelectorException(NoSuchElementException): - """Argument was an invalid selector (e.g. XPath/CSS).""" - -class JavascriptErrorException(WebDriverException): - """An error occurred while executing user supplied JavaScript.""" - -class MoveTargetOutOfBoundsException(InvalidElementStateException): - """The target for mouse interaction is not in the browser's viewport - and cannot be brought into that viewport. - """ - -class NoSuchAlertException(WebDriverException): - """An attempt was made to operate on a modal dialog when one was not open.""" - -class NoSuchFrameException(WebDriverException): - """A request to switch to a frame could not be satisfied because - the frame could not be found.""" - -class NoSuchWindowException(WebDriverException): - """A request to switch to a different window could not be satisfied - because the window could not be found. - """ - -class ScriptTimeoutException(TimeoutException): - """A script did not complete before its timeout expired.""" - -class SessionNotCreatedException(WebDriverException): - """A new session could not be created.""" - -class StaleElementReferenceException(InvalidElementStateException): - """An element command failed because the referenced element is no - longer attached to the DOM. - """ - -class UnexpectedAlertOpenException(WebDriverException): - """A modal dialog was open, blocking this operation.""" - -class UnknownCommandException(WebDriverException): - """A command could not be executed because the remote end is not - aware of it. - """ - -class UnknownErrorException(WebDriverException): - """An unknown error occurred in the remote end while processing - the command. - """ - -class UnsupportedOperationException(WebDriverException): - """Indicates that a command that should have executed properly - cannot be supported for some reason. - """ - -class UnknownStatusCodeException(WebDriverException): - """Exception for all other status codes.""" - -_exceptions_strict = { - "element not selectable": ElementNotSelectableException, - "element not visible": ElementNotVisibleException, - "ime engine activation failed": ImeEngineActivationFailedException, - "ime not available": ImeNotAvailableException, - "invalid cookie domain": InvalidCookieDomainException, - "invalid element coordinates": InvalidElementCoordinatesException, - "invalid element state": InvalidElementStateException, - "invalid selector": InvalidSelectorException, - "javascript error": JavascriptErrorException, - "move target out of bounds": MoveTargetOutOfBoundsException, - "no such alert": NoSuchAlertException, - "no such element": NoSuchElementException, - "no such frame": NoSuchFrameException, - "no such window": NoSuchWindowException, - "script timeout": ScriptTimeoutException, - "session not created": SessionNotCreatedException, - "stale element reference": StaleElementReferenceException, - "success": None, - "timeout": TimeoutException, - "unable to set cookie": UnableToSetCookieException, - "unexpected alert open": UnexpectedAlertOpenException, - "unknown command": UnknownCommandException, - "unknown error": UnknownErrorException, - "unsupported operation": UnsupportedOperationException, -} - -_exceptions_compatibility = { - 15: ElementNotSelectableException, - 11: ElementNotVisibleException, - 31: ImeEngineActivationFailedException, - 30: ImeNotAvailableException, - 24: InvalidCookieDomainException, - 29: InvalidElementCoordinatesException, - 12: InvalidElementStateException, - 19: InvalidSelectorException, - 32: InvalidSelectorException, - 17: JavascriptErrorException, - 34: MoveTargetOutOfBoundsException, - 27: NoSuchAlertException, - 7: NoSuchElementException, - 8: NoSuchFrameException, - 23: NoSuchWindowException, - 28: ScriptTimeoutException, - 6: SessionNotCreatedException, - 33: SessionNotCreatedException, - 10: StaleElementReferenceException, - 0: None, # success - 21: TimeoutException, - 25: UnableToSetCookieException, - 26: UnexpectedAlertOpenException, - 9: UnknownCommandException, - 13: UnknownErrorException, - # "unsupported operation": UnsupportedOperationException -} diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/keys.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/keys.py deleted file mode 100644 index 9c6d93df821..00000000000 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/keys.py +++ /dev/null @@ -1,68 +0,0 @@ -"""Constants for special keys.""" - -class Keys: - """Constants for special keys.""" - NULL = '\uE000' - CANCEL = '\uE001' - HELP = '\uE002' - BACK_SPACE = '\uE003' - TAB = '\uE004' - CLEAR = '\uE005' - RETURN = '\uE006' - ENTER = '\uE007' - SHIFT = '\uE008' - LEFT_SHIFT = '\uE008' - CONTROL = '\uE009' - LEFT_CONTROL = '\uE009' - ALT = '\uE00A' - LEFT_ALT = '\uE00A' - PAUSE = '\uE00B' - ESCAPE = '\uE00C' - SPACE = '\uE00D' - PAGE_UP = '\uE00E' - PAGE_DOWN = '\uE00F' - END = '\uE010' - HOME = '\uE011' - LEFT = '\uE012' - ARROW_LEFT = '\uE012' - UP = '\uE013' - ARROW_UP = '\uE013' - RIGHT = '\uE014' - ARROW_RIGHT = '\uE014' - DOWN = '\uE015' - ARROW_DOWN = '\uE015' - INSERT = '\uE016' - DELETE = '\uE017' - SEMICOLON = '\uE018' - EQUALS = '\uE019' - NUMPAD0 = '\uE01A' - NUMPAD1 = '\uE01B' - NUMPAD2 = '\uE01C' - NUMPAD3 = '\uE01D' - NUMPAD4 = '\uE01E' - NUMPAD5 = '\uE01F' - NUMPAD6 = '\uE020' - NUMPAD7 = '\uE021' - NUMPAD8 = '\uE022' - NUMPAD9 = '\uE023' - MULTIPLY = '\uE024' - ADD = '\uE025' - SEPARATOR = '\uE026' - SUBTRACT = '\uE027' - DECIMAL = '\uE028' - DIVIDE = '\uE029' - F1 = '\uE031' - F2 = '\uE032' - F3 = '\uE033' - F4 = '\uE034' - F5 = '\uE035' - F6 = '\uE036' - F7 = '\uE037' - F8 = '\uE038' - F9 = '\uE039' - F10 = '\uE03A' - F11 = '\uE03B' - F12 = '\uE03C' - META = '\uE03D' - COMMAND = '\uE03D' - ZENKAKU_HANKAKU = '\uE040' diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/searchcontext.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/searchcontext.py deleted file mode 100644 index 061fa027db1..00000000000 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/searchcontext.py +++ /dev/null @@ -1,54 +0,0 @@ -"""WebDriver element location functionality.""" - -class SearchContext(object): - """Abstract class that provides the core element location functionality.""" - - def find_element_by_css(self, selector): - """Find the first element matching a css selector.""" - return self._find_element('css selector', selector) - - def find_elements_by_css(self, selector): - """Find all elements matching a css selector.""" - return self._find_elements('css selector', selector) - - def find_element_by_link_text(self, text): - """Find the first link with the given text.""" - return self._find_element('link text', text) - - def find_elements_by_link_text(self, text): - """Find all links with the given text.""" - return self._find_elements('link text', text) - - def find_element_by_partial_link_text(self, text): - """Find the first link containing the given text.""" - return self._find_element('partial link text', text) - - def find_elements_by_partial_link_text(self, text): - """Find all links containing the given text.""" - return self._find_elements('partial link text', text) - - def find_element_by_xpath(self, xpath): - """Find the first element matching the xpath.""" - return self._find_element('xpath', xpath) - - def find_elements_by_xpath(self, xpath): - """Find all elements matching the xpath.""" - return self._find_elements('xpath', xpath) - - def _find_element(self, strategy, value): - return self.execute('POST', - '/element', - 'findElement', - self._get_locator(strategy, value)) - - def _find_elements(self, strategy, value): - return self.execute('POST', - '/elements', - 'findElements', - self._get_locator(strategy, value)) - - def _get_locator(self, strategy, value): - if self.mode == 'strict': - return {'strategy': strategy, 'value': value} - elif self.mode == 'compatibility': - return {'using': strategy, 'value': value} diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/servo.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/servo.py new file mode 100644 index 00000000000..fd1539f7bc7 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/servo.py @@ -0,0 +1,22 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +class ServoExtensionCommands(object): + def __init__(self, session): + self.session = session + + @command + def get_prefs(self, *prefs): + body = {"prefs": list(prefs)} + return self.session.send_command("POST", "servo/prefs/get", body) + + @command + def set_prefs(self, prefs): + body = {"prefs": prefs} + return self.session.send_command("POST", "servo/prefs/set", body) + + @command + def reset_prefs(self, *prefs): + body = {"prefs": list(prefs)} + return self.session.send_command("POST", "servo/prefs/reset", body) diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/transport.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/transport.py new file mode 100644 index 00000000000..d4b0adfda05 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/transport.py @@ -0,0 +1,117 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + + +import errno +import httplib +import json +import socket +import time +import urlparse + +import error + + +HTTP_TIMEOUT = 5 + + +class HTTPWireProtocol(object): + """Transports messages (commands and responses) over the WebDriver + wire protocol. + """ + + def __init__(self, host, port, url_prefix="/", timeout=HTTP_TIMEOUT): + """Construct interface for communicating with the remote server. + + :param url: URL of remote WebDriver server. + :param wait: Duration to wait for remote to appear. + """ + + self.host = host + self.port = port + self.path_prefix = url_prefix + + self._timeout = timeout + self._connection = None + + def connect(self): + wait_for_port(self.host, self.port, self._timeout) + self._connection = httplib.HTTPConnection( + self.host, self.port, timeout=self._timeout) + + def disconnect(self): + if self._connection: + self._connection.close() + self._connection = None + + def url(self, suffix): + return urlparse.urljoin(self.path_prefix, suffix) + + def send(self, method, url, body=None, headers=None, key=None): + """Send a command to the remote. + + :param method: "POST" or "GET". + :param body: Body of the request. Defaults to an empty dictionary + if ``method`` is "POST". + :param headers: Additional headers to include in the request. + :param key: Extract this key from the dictionary returned from + the remote. + """ + + if not self._connection: + self.connect() + + if body is None and method == "POST": + body = {} + + if isinstance(body, dict): + body = json.dumps(body) + + if isinstance(body, unicode): + body = body.encode("utf-8") + + if headers is None: + headers = {} + + url = self.path_prefix + url + self._connection.request(method, url, body, headers) + + resp = self._connection.getresponse() + resp_body = resp.read() + + try: + data = json.loads(resp_body) + except: + raise IOError("Could not parse response body as JSON: %s" % body) + + if resp.status != 200: + cls = error.get(data.get("error")) + raise cls(data.get("message")) + + if key is not None: + data = data[key] + if not data: + data = None + + return data + + +def wait_for_port(host, port, timeout=HTTP_TIMEOUT): + """Wait for a given host/port to be available.""" + starttime = time.time() + poll_interval = 0.1 + while time.time() - starttime < timeout: + sock = None + try: + sock = socket.socket() + sock.connect((host, port)) + return True + except socket.error as e: + if e[0] != errno.ECONNREFUSED: + raise + finally: + if sock: + sock.close() + time.sleep(poll_interval) + return False diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/wait.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/wait.py deleted file mode 100644 index e93c42d1d72..00000000000 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/wait.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2011 Software Freedom Conservancy. -# -# 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. - -"""Waiting functionality.""" - -import time -from exceptions import NoSuchElementException -from exceptions import TimeoutException - -POLL_FREQUENCY = 0.5 # How long to sleep inbetween calls to the method -IGNORED_EXCEPTIONS = [NoSuchElementException] # list of exceptions ignored during calls to the method - -class WebDriverWait(object): - - def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None): - """Constructor, takes a WebDriver instance and timeout in seconds. - - :Args: - - driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote) - - timeout - Number of seconds before timing out - - poll_frequency - sleep interval between calls - By default, it is 0.5 second. - - ignored_exceptions - iterable structure of exception classes ignored during calls. - By default, it contains NoSuchElementException only. - - Example: - from selenium.webdriver.support.ui import WebDriverWait \n - element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n - is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n - until_not(lambda x: x.find_element_by_id("someId").is_displayed()) - """ - self._driver = driver - self._timeout = timeout - self._poll = poll_frequency - # avoid the divide by zero - if self._poll == 0: - self._poll = POLL_FREQUENCY - exceptions = IGNORED_EXCEPTIONS - if ignored_exceptions is not None: - try: - exceptions.extend(iter(ignored_exceptions)) - except TypeError: # ignored_exceptions is not iterable - exceptions.append(ignored_exceptions) - self._ignored_exceptions = tuple(exceptions) - - def until(self, method, message=''): - """Calls the method provided with the driver as an argument until the \ - return value is not False.""" - end_time = time.time() + self._timeout - while(True): - try: - value = method(self._driver) - if value: - return value - except self._ignored_exceptions: - pass - time.sleep(self._poll) - if(time.time() > end_time): - break - raise TimeoutException(message) - - def until_not(self, method, message=''): - """Calls the method provided with the driver as an argument until the \ - return value is False.""" - end_time = time.time() + self._timeout - while(True): - try: - value = method(self._driver) - if not value: - return value - except self._ignored_exceptions: - return True - time.sleep(self._poll) - if(time.time() > end_time): - break - raise TimeoutException(message) diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/webelement.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/webelement.py deleted file mode 100644 index 83e27f23116..00000000000 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/webelement.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Element-level WebDriver operations.""" - -import searchcontext - -class WebElement(searchcontext.SearchContext): - """Corresponds to a DOM element in the current page.""" - - def __init__(self, driver, id): - self._driver = driver - self._id = id - # Set value of mode used by SearchContext - self.mode = driver.mode - - def execute(self, method, path, name, body=None): - """Execute a command against this WebElement.""" - return self._driver.execute( - method, '/element/%s%s' % (self._id, path), name, body) - - def is_displayed(self): - """Is this element displayed?""" - return self.execute('GET', '/displayed', 'isDisplayed') - - def is_selected(self): - """Is this checkbox, radio button, or option selected?""" - return self.execute('GET', '/selected', 'isSelected') - - def get_attribute(self, name): - """Get the value of an element property or attribute.""" - return self.execute('GET', '/attribute/%s' % name, 'getElementAttribute') - - @property - def text(self): - """Get the visible text for this element.""" - return self.execute('GET', '/text', 'text') - - @property - def tag_name(self): - """Get the tag name for this element""" - return self.execute('GET', '/name', 'getElementTagName') - - def click(self): - """Click on this element.""" - return self.execute('POST', '/click', 'click') - - def clear(self): - """Clear the contents of the this text input.""" - self.execute('POST', '/clear', 'clear') - - def send_keys(self, keys): - """Send keys to this text input or body element.""" - if isinstance(keys, str): - keys = [keys] - self.execute('POST', '/value', 'sendKeys', {'value': keys}) - - def to_json(self): - return {'ELEMENT': self.id} diff --git a/tests/wpt/web-platform-tests/url/OWNERS b/tests/wpt/web-platform-tests/url/OWNERS index fe4257cdb03..562d1ccf8e1 100644 --- a/tests/wpt/web-platform-tests/url/OWNERS +++ b/tests/wpt/web-platform-tests/url/OWNERS @@ -7,3 +7,4 @@ @xiaojunwu @smola @domenic +@Sebmaster diff --git a/tests/wpt/web-platform-tests/url/historical.html b/tests/wpt/web-platform-tests/url/historical.html index 41f359d3d67..17fdb97294b 100644 --- a/tests/wpt/web-platform-tests/url/historical.html +++ b/tests/wpt/web-platform-tests/url/historical.html @@ -18,4 +18,12 @@ objects.forEach(function(o) { o[1] + " should not have a searchParams attribute"); }, "searchParams on " + o[1]); }); + +test(function() { + var url = new URL("./foo", "http://www.example.org"); + assert_equals(url.href, "http://www.example.org/foo"); + assert_throws(new TypeError(), function() { + url.href = "./bar"; + }); +}, "Setting URL's href attribute and base URLs"); diff --git a/tests/wpt/web-platform-tests/url/historical.worker.js b/tests/wpt/web-platform-tests/url/historical.worker.js index 4fcba6c90ee..d90915a38a0 100644 --- a/tests/wpt/web-platform-tests/url/historical.worker.js +++ b/tests/wpt/web-platform-tests/url/historical.worker.js @@ -5,4 +5,12 @@ test(function() { "location object should not have a searchParams attribute"); }, "searchParams on location object"); +test(function() { + var url = new URL("./foo", "http://www.example.org"); + assert_equals(url.href, "http://www.example.org/foo"); + assert_throws(new TypeError(), function() { + url.href = "./bar"; + }); +}, "Setting URL's href attribute and base URLs"); + done(); diff --git a/tests/wpt/web-platform-tests/url/url-constructor.html b/tests/wpt/web-platform-tests/url/url-constructor.html index a7503310397..80eb943aa16 100644 --- a/tests/wpt/web-platform-tests/url/url-constructor.html +++ b/tests/wpt/web-platform-tests/url/url-constructor.html @@ -5,20 +5,22 @@
diff --git a/tests/wpt/web-platform-tests/url/urltestdata.json b/tests/wpt/web-platform-tests/url/urltestdata.json index 7d9b9090fb2..322f69ec893 100644 --- a/tests/wpt/web-platform-tests/url/urltestdata.json +++ b/tests/wpt/web-platform-tests/url/urltestdata.json @@ -4224,5 +4224,38 @@ "pathname": "/path", "search": "?query", "hash": "#frag" + }, + "# Stringification of URL.searchParams", + { + "input": "?a=b&c=d", + "base": "http://example.org/foo/bar", + "href": "http://example.org/foo/bar?a=b&c=d", + "origin": "http://example.org", + "protocol": "http:", + "username": "", + "password": "", + "host": "example.org", + "hostname": "example.org", + "port": "", + "pathname": "/foo/bar", + "search": "?a=b&c=d", + "searchParams": "a=b&c=d", + "hash": "" + }, + { + "input": "??a=b&c=d", + "base": "http://example.org/foo/bar", + "href": "http://example.org/foo/bar??a=b&c=d", + "origin": "http://example.org", + "protocol": "http:", + "username": "", + "password": "", + "host": "example.org", + "hostname": "example.org", + "port": "", + "pathname": "/foo/bar", + "search": "??a=b&c=d", + "searchParams": "%3Fa=b&c=d", + "hash": "" } ] diff --git a/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/delay.html b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/delay.html new file mode 100644 index 00000000000..82761cf85b6 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/delay.html @@ -0,0 +1,62 @@ + + +delay tests + + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/direction.html b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/direction.html new file mode 100644 index 00000000000..454f13604c9 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/direction.html @@ -0,0 +1,28 @@ + + +direction tests + + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/getAnimations.html b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/getAnimations.html index ffbfd94c18b..d4d9e32b5fa 100644 --- a/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/getAnimations.html +++ b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/getAnimations.html @@ -51,6 +51,19 @@ test(function(t) { '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 ] }, diff --git a/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle.html b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle.html index d49e07e39f8..e562783c88e 100644 --- a/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle.html +++ b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle.html @@ -24,6 +24,19 @@ test(function(t) { 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 ] }, @@ -103,5 +116,61 @@ test(function(t) { '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"'); + diff --git a/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/iterations.html b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/iterations.html new file mode 100644 index 00000000000..f313d4bff48 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-animations/animation-effect-timing/iterations.html @@ -0,0 +1,57 @@ + + +iterations tests + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-after.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-after.html deleted file mode 100644 index 93d79e03804..00000000000 --- a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-after.html +++ /dev/null @@ -1,419 +0,0 @@ - - -AnimationNode after() method tests - - - - - - - - - - -
- - diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-before.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-before.html deleted file mode 100644 index 714f1e4d152..00000000000 --- a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-before.html +++ /dev/null @@ -1,418 +0,0 @@ - - -AnimationNode before() method tests - - - - - - - - - - -
- - diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html deleted file mode 100644 index a1cd7e94878..00000000000 --- a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html +++ /dev/null @@ -1,503 +0,0 @@ - - -AnimationNode nextSibling attribute tests - - - - - - - - - -
- - diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-parent.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-parent.html deleted file mode 100644 index 6e2ec65f914..00000000000 --- a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-parent.html +++ /dev/null @@ -1,53 +0,0 @@ - - -AnimationNode parent attribute tests - - - - - - - - -
- - diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html deleted file mode 100644 index 60ed9e372aa..00000000000 --- a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html +++ /dev/null @@ -1,511 +0,0 @@ - - -AnimationNode previousSibling attribute tests - - - - - - - - - -
- - diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-remove.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-remove.html deleted file mode 100644 index 5ded75c1bfd..00000000000 --- a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-remove.html +++ /dev/null @@ -1,239 +0,0 @@ - - -AnimationNode remove() method tests - - - - - - - - - -
- - diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-replace.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-replace.html deleted file mode 100644 index a4bbbe77313..00000000000 --- a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-replace.html +++ /dev/null @@ -1,444 +0,0 @@ - - -AnimationNode replace() method tests - - - - - - - - - - -
- - diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/idlharness.html b/tests/wpt/web-platform-tests/web-animations/animation-node/idlharness.html deleted file mode 100644 index bfa23b22204..00000000000 --- a/tests/wpt/web-platform-tests/web-animations/animation-node/idlharness.html +++ /dev/null @@ -1,54 +0,0 @@ - - -AnimationNode IDL tests - - - - - - - -
-
- - - - diff --git a/tests/wpt/web-platform-tests/web-animations/animation/cancel.html b/tests/wpt/web-platform-tests/web-animations/animation/cancel.html new file mode 100644 index 00000000000..992e41676e7 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-animations/animation/cancel.html @@ -0,0 +1,61 @@ + + +Animation.cancel() + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/web-animations/animation/finish.html b/tests/wpt/web-platform-tests/web-animations/animation/finish.html new file mode 100644 index 00000000000..35bd7b0d0b0 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-animations/animation/finish.html @@ -0,0 +1,210 @@ + + +Animation.finish() + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/web-animations/animation/play.html b/tests/wpt/web-platform-tests/web-animations/animation/play.html new file mode 100644 index 00000000000..4fca2548cf8 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-animations/animation/play.html @@ -0,0 +1,35 @@ + + +Animation.play() + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/web-animations/animation/playState.html b/tests/wpt/web-platform-tests/web-animations/animation/playState.html new file mode 100644 index 00000000000..670452da9f1 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-animations/animation/playState.html @@ -0,0 +1,54 @@ + + +Animation.playState + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/web-animations/animation/playbackRate.html b/tests/wpt/web-platform-tests/web-animations/animation/playbackRate.html new file mode 100644 index 00000000000..fcb73535e27 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-animations/animation/playbackRate.html @@ -0,0 +1,89 @@ + + +Animation.playbackRate + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/web-animations/keyframe-effect/constructor.html b/tests/wpt/web-platform-tests/web-animations/keyframe-effect/constructor.html index 55720daffd8..50cee72ac47 100644 --- a/tests/wpt/web-platform-tests/web-animations/keyframe-effect/constructor.html +++ b/tests/wpt/web-platform-tests/web-animations/keyframe-effect/constructor.html @@ -61,13 +61,8 @@ test(function(t) { // [specified easing value, expected easing value] var gEasingValueTests = [ - ["unrecognised", "linear"], ["linear", "linear"], ["ease-in-out", "ease-in-out"], - ["initial", "linear"], - ["inherit", "linear"], - ["var(--x)", "linear"], - ["ease-in-out, ease-out", "linear"], ["Ease\\2d in-out", "ease-in-out"], ["ease /**/", "ease"], ]; @@ -113,56 +108,57 @@ test(function(t) { }, "easing values are parsed correctly when passed to the " + "KeyframeEffectReadOnly constructor in KeyframeTimingOptions"); -var gGoodCompositeValueTests = [ +var gGoodKeyframeCompositeValueTests = [ + "replace", "add", "accumulate", undefined +]; + +var gGoodOptionsCompositeValueTests = [ "replace", "add", "accumulate" ]; var gBadCompositeValueTests = [ - "unrecognised", "replace ", "Replace" + "unrecognised", "replace ", "Replace", null ]; test(function(t) { - gGoodCompositeValueTests.forEach(function(composite) { - var effect = new KeyframeEffectReadOnly(target, { - left: ["10px", "20px"], - composite: composite - }); + var getFrame = function(composite) { + return { left: [ "10px", "20px" ], composite: composite }; + }; + gGoodKeyframeCompositeValueTests.forEach(function(composite) { + var effect = new KeyframeEffectReadOnly(target, getFrame(composite)); assert_equals(effect.getFrames()[0].composite, composite, "resulting composite for '" + composite + "'"); }); gBadCompositeValueTests.forEach(function(composite) { assert_throws(new TypeError, function() { - new KeyframeEffectReadOnly(target, { - left: ["10px", "20px"], - composite: composite - }); + new KeyframeEffectReadOnly(target, getFrame(composite)); }); }); }, "composite values are parsed correctly when passed to the " + "KeyframeEffectReadOnly constructor in PropertyIndexedKeyframes"); test(function(t) { - gGoodCompositeValueTests.forEach(function(composite) { - var effect = new KeyframeEffectReadOnly(target, [ + var getFrames = function(composite) { + return [ { offset: 0, left: "10px", composite: composite }, { offset: 1, left: "20px" } - ]); + ]; + }; + gGoodKeyframeCompositeValueTests.forEach(function(composite) { + var effect = new KeyframeEffectReadOnly(target, getFrames(composite)); assert_equals(effect.getFrames()[0].composite, composite, "resulting composite for '" + composite + "'"); }); gBadCompositeValueTests.forEach(function(composite) { assert_throws(new TypeError, function() { - new KeyframeEffectReadOnly(target, [ - { offset: 0, left: "10px", composite: composite }, - { offset: 1, left: "20px" } - ]); + new KeyframeEffectReadOnly(target, getFrames(composite)); }); }); }, "composite values are parsed correctly when passed to the " + "KeyframeEffectReadOnly constructor in Keyframe"); test(function(t) { - gGoodCompositeValueTests.forEach(function(composite) { + gGoodOptionsCompositeValueTests.forEach(function(composite) { var effect = new KeyframeEffectReadOnly(target, { left: ["10px", "20px"] }, { composite: composite }); @@ -182,77 +178,77 @@ test(function(t) { var gPropertyIndexedKeyframesTests = [ { desc: "a one property two value PropertyIndexedKeyframes specification", input: { left: ["10px", "20px"] }, - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] }, { desc: "a one shorthand property two value PropertyIndexedKeyframes specification", input: { margin: ["10px", "10px 20px 30px 40px"] }, - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "10px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear", marginTop: "10px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] }, { desc: "a two property (one shorthand and one of its longhand components) two value PropertyIndexedKeyframes specification", input: { marginTop: ["50px", "60px"], margin: ["10px", "10px 20px 30px 40px"] }, - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "50px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "60px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "50px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear", marginTop: "60px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] }, { desc: "a two property two value PropertyIndexedKeyframes specification", input: { left: ["10px", "20px"], top: ["30px", "40px"] }, - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px", top: "30px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px", top: "40px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] }, { desc: "a two property PropertyIndexedKeyframes specification with different numbers of values", input: { left: ["10px", "20px", "30px"], top: ["40px", "50px"] }, - output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px", top: "40px" }, - { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "20px" }, - { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "30px", top: "50px" }] }, + output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px", top: "40px" }, + { offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" }, + { offset: 1.0, computedOffset: 1.0, easing: "linear", left: "30px", top: "50px" }] }, { desc: "a PropertyIndexedKeyframes specification with an invalid value", input: { left: ["10px", "20px", "30px", "40px", "50px"], top: ["15px", "25px", "invalid", "45px", "55px"] }, - output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px", top: "15px" }, - { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "20px", top: "25px" }, - { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "30px" }, - { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "40px", top: "45px" }, - { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "50px", top: "55px" }] }, + output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "15px" }, + { offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px", top: "25px" }, + { offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" }, + { offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px", top: "45px" }, + { offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px", top: "55px" }] }, { desc: "a one property two value PropertyIndexedKeyframes specification that needs to stringify its values", input: { opacity: [0, 1] }, - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", opacity: "0" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", opacity: "1" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" }, + { offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] }, { desc: "a one property one value PropertyIndexedKeyframes specification", input: { left: ["10px"] }, - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "10px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] }, { desc: "a one property one non-array value PropertyIndexedKeyframes specification", input: { left: "10px" }, - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "10px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] }, { desc: "a one property two value PropertyIndexedKeyframes specification where the first value is invalid", input: { left: ["invalid", "10px"] }, - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "10px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] }, { desc: "a one property two value PropertyIndexedKeyframes specification where the second value is invalid", input: { left: ["10px", "invalid"] }, - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear" }] }, { desc: "a two property PropertyIndexedKeyframes specification where one property is missing from the first Keyframe", input: [{ offset: 0, left: "10px" }, { offset: 1, left: "20px", top: "30px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px", top: "30px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "30px" }] }, { desc: "a two property PropertyIndexedKeyframes specification where one property is missing from the last Keyframe", input: [{ offset: 0, left: "10px", top: "20px" }, { offset: 1, left: "30px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" , top: "20px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "30px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" , top: "20px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "30px" }] }, { desc: "a PropertyIndexedKeyframes specification with repeated values at offset 0 with different easings", input: [{ offset: 0.0, left: "100px", easing: "ease" }, { offset: 0.0, left: "200px", easing: "ease" }, { offset: 0.5, left: "300px", easing: "linear" }, { offset: 1.0, left: "400px", easing: "ease-out" }, { offset: 1.0, left: "500px", easing: "step-end" }], - output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease", composite: "replace", left: "100px" }, - { offset: 0.0, computedOffset: 0.0, easing: "ease", composite: "replace", left: "200px" }, - { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "300px" }, - { offset: 1.0, computedOffset: 1.0, easing: "ease-out", composite: "replace", left: "400px" }, - { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "500px" }] }, + output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease", left: "100px" }, + { offset: 0.0, computedOffset: 0.0, easing: "ease", left: "200px" }, + { offset: 0.5, computedOffset: 0.5, easing: "linear", left: "300px" }, + { offset: 1.0, computedOffset: 1.0, easing: "ease-out", left: "400px" }, + { offset: 1.0, computedOffset: 1.0, easing: "linear", left: "500px" }] }, ]; gPropertyIndexedKeyframesTests.forEach(function(subtest) { @@ -278,7 +274,7 @@ test(function(t) { { p: "left", v: "20px" }, { p: "offset", v: "0" }, { p: "easing", v: "linear" }, - { p: "composite", v: null }].forEach(function(e) { + { p: "composite", v: "replace" }].forEach(function(e) { Object.defineProperty(kf1, e.p, { enumerable: true, get: function() { actualOrder.push(e.p); return e.v; } @@ -293,33 +289,33 @@ var gKeyframeSequenceTests = [ { desc: "a one property two Keyframe sequence", input: [{ offset: 0, left: "10px" }, { offset: 1, left: "20px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] }, { desc: "a two property two Keyframe sequence", input: [{ offset: 0, left: "10px", top: "30px" }, { offset: 1, left: "20px", top: "40px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px", top: "30px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px", top: "40px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] }, { desc: "a one shorthand property two Keyframe sequence", input: [{ offset: 0, margin: "10px" }, { offset: 1, margin: "20px 30px 40px 50px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "20px", marginRight: "30px", marginBottom: "40px", marginLeft: "50px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear", marginTop: "20px", marginRight: "30px", marginBottom: "40px", marginLeft: "50px" }] }, { desc: "a two property (a shorthand and one of its component longhands) two Keyframe sequence", input: [{ offset: 0, margin: "10px", marginTop: "20px" }, { offset: 1, marginTop: "70px", margin: "30px 40px 50px 60px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "20px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "70px", marginRight: "40px", marginBottom: "50px", marginLeft: "60px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "20px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear", marginTop: "70px", marginRight: "40px", marginBottom: "50px", marginLeft: "60px" }] }, { desc: "a Keyframe sequence with duplicate values for a given interior offset", input: [{ offset: 0.0, left: "10px" }, { offset: 0.5, left: "20px" }, { offset: 0.5, left: "30px" }, { offset: 0.5, left: "40px" }, { offset: 1.0, left: "50px" }], - output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px" }, - { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "20px" }, - { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "40px" }, - { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px" }] }, + output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px" }, + { offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" }, + { offset: 0.5, computedOffset: 0.5, easing: "linear", left: "40px" }, + { offset: 1.0, computedOffset: 1.0, easing: "linear", left: "50px" }] }, { desc: "a Keyframe sequence with duplicate values for offsets 0 and 1", input: [{ offset: 0, left: "10px" }, { offset: 0, left: "20px" }, @@ -327,50 +323,50 @@ var gKeyframeSequenceTests = [ { offset: 1, left: "40px" }, { offset: 1, left: "50px" }, { offset: 1, left: "60px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" }, - { offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "30px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "40px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "60px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" }, + { offset: 0, computedOffset: 0, easing: "linear", left: "30px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "40px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "60px" }] }, { desc: "a two property four Keyframe sequence", input: [{ offset: 0, left: "10px" }, { offset: 0, top: "20px" }, { offset: 1, top: "30px" }, { offset: 1, left: "40px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px", top: "20px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "40px", top: "30px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "20px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "40px", top: "30px" }] }, { desc: "a one property Keyframe sequence with some omitted offsets", input: [{ offset: 0.00, left: "10px" }, { offset: 0.25, left: "20px" }, { left: "30px" }, { left: "40px" }, { offset: 1.00, left: "50px" }], - output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px" }, - { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "20px" }, - { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "30px" }, - { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "40px" }, - { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "50px" }] }, + output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" }, + { offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" }, + { offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" }, + { offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" }, + { offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] }, { desc: "a two property Keyframe sequence with some omitted offsets", input: [{ offset: 0.00, left: "10px", top: "20px" }, { offset: 0.25, left: "30px" }, { left: "40px" }, { left: "50px", top: "60px" }, { offset: 1.00, left: "70px", top: "80px" }], - output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px", top: "20px" }, - { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "30px" }, - { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "40px" }, - { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "50px", top: "60px" }, - { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "70px", top: "80px" }] }, + output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "20px" }, + { offset: 0.25, computedOffset: 0.25, easing: "linear", left: "30px" }, + { offset: 0.50, computedOffset: 0.50, easing: "linear", left: "40px" }, + { offset: 0.75, computedOffset: 0.75, easing: "linear", left: "50px", top: "60px" }, + { offset: 1.00, computedOffset: 1.00, easing: "linear", left: "70px", top: "80px" }] }, { desc: "a one property Keyframe sequence with all omitted offsets", input: [{ left: "10px" }, { left: "20px" }, { left: "30px" }, { left: "40px" }, { left: "50px" }], - output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px" }, - { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "20px" }, - { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "30px" }, - { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "40px" }, - { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "50px" }] }, + output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" }, + { offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" }, + { offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" }, + { offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" }, + { offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] }, { desc: "a Keyframe sequence with different easing values, but the same easing value for a given offset", input: [{ offset: 0.0, easing: "ease", left: "10px"}, { offset: 0.0, easing: "ease", top: "20px"}, @@ -378,9 +374,12 @@ var gKeyframeSequenceTests = [ { offset: 0.5, easing: "linear", top: "40px" }, { offset: 1.0, easing: "step-end", left: "50px" }, { offset: 1.0, easing: "step-end", top: "60px" }], - output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease", composite: "replace", left: "10px", top: "20px" }, - { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "30px", top: "40px" }, - { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px", top: "60px" }] }, + output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease", + left: "10px", top: "20px" }, + { offset: 0.5, computedOffset: 0.5, easing: "linear", + left: "30px", top: "40px" }, + { offset: 1.0, computedOffset: 1.0, easing: "linear", + left: "50px", top: "60px" }] }, { desc: "a Keyframe sequence with different composite values, but the same composite value for a given offset", input: [{ offset: 0.0, composite: "replace", left: "10px" }, { offset: 0.0, composite: "replace", top: "20px" }, @@ -394,27 +393,27 @@ var gKeyframeSequenceTests = [ { desc: "a one property two Keyframe sequence that needs to stringify its values", input: [{ offset: 0, opacity: 0 }, { offset: 1, opacity: 1 }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", opacity: "0" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", opacity: "1" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" }, + { offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] }, { desc: "a Keyframe sequence where shorthand precedes longhand", input: [{ offset: 0, margin: "10px", marginRight: "20px" }, { offset: 1, margin: "30px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] }, { desc: "a Keyframe sequence where longhand precedes shorthand", input: [{ offset: 0, marginRight: "20px", margin: "10px" }, { offset: 1, margin: "30px" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] }, + output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" }, + { offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] }, { desc: "a Keyframe sequence where lesser shorthand precedes greater shorthand", input: [{ offset: 0, borderLeft: "1px solid rgb(1, 2, 3)", border: "2px dotted rgb(4, 5, 6)" }, { offset: 1, border: "3px dashed rgb(7, 8, 9)" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", + output: [{ offset: 0, computedOffset: 0, easing: "linear", borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px", borderLeftColor: "rgb(1, 2, 3)", borderLeftWidth: "1px", borderRightColor: "rgb(4, 5, 6)", borderRightWidth: "2px", borderTopColor: "rgb(4, 5, 6)", borderTopWidth: "2px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", + { offset: 1, computedOffset: 1, easing: "linear", borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px", borderLeftColor: "rgb(7, 8, 9)", borderLeftWidth: "3px", borderRightColor: "rgb(7, 8, 9)", borderRightWidth: "3px", @@ -422,12 +421,12 @@ var gKeyframeSequenceTests = [ { desc: "a Keyframe sequence where greater shorthand precedes lesser shorthand", input: [{ offset: 0, border: "2px dotted rgb(4, 5, 6)", borderLeft: "1px solid rgb(1, 2, 3)" }, { offset: 1, border: "3px dashed rgb(7, 8, 9)" }], - output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", + output: [{ offset: 0, computedOffset: 0, easing: "linear", borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px", borderLeftColor: "rgb(1, 2, 3)", borderLeftWidth: "1px", borderRightColor: "rgb(4, 5, 6)", borderRightWidth: "2px", borderTopColor: "rgb(4, 5, 6)", borderTopWidth: "2px" }, - { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", + { offset: 1, computedOffset: 1, easing: "linear", borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px", borderLeftColor: "rgb(7, 8, 9)", borderLeftWidth: "3px", borderRightColor: "rgb(7, 8, 9)", borderRightWidth: "3px", @@ -448,6 +447,29 @@ gKeyframeSequenceTests.forEach(function(subtest) { " roundtrips"); }); +var gInvalidEasingInKeyframeSequenceTests = [ + { desc: "a blank easing", + input: [{ easing: "" }] }, + { desc: "an unrecognized easing", + input: [{ easing: "unrecognized" }] }, + { desc: "an 'initial' easing", + input: [{ easing: "initial" }] }, + { desc: "an 'inherit' easing", + input: [{ easing: "inherit" }] }, + { desc: "a variable easing", + input: [{ easing: "var(--x)" }] }, + { desc: "a multi-value easing", + input: [{ easing: "ease-in-out, ease-out" }] } +]; + +gInvalidEasingInKeyframeSequenceTests.forEach(function(subtest) { + test(function(t) { + assert_throws(new TypeError, function() { + new KeyframeEffectReadOnly(target, subtest.input); + }); + }, "Invalid easing [" + subtest.desc + "] in KeyframeSequence " + + "should be thrown"); +}); test(function(t) { var effect = new KeyframeEffectReadOnly(target, @@ -501,15 +523,6 @@ var gKeyframeEffectOptionTests = [ { desc: "an Infinity iterations", input: { iterations: Infinity }, expected: { iterations: Infinity } }, - { desc: "a negative Infinity iterations", - input: { iterations: -Infinity }, - expected: { iterations: -Infinity } }, - { desc: "a NaN iterations", - input: { iterations: NaN }, - expected: { iterations: NaN } }, - { desc: "a negative iterations", - input: { iterations: -1 }, - expected: { iterations: -1 } }, { desc: "an auto fill", input: { fill: "auto" }, expected: { fill: "auto" } }, @@ -566,6 +579,33 @@ var gInvalidKeyframeEffectOptionTests = [ expected: { name: "TypeError" } }, { desc: "a string duration", input: { duration: "merrychristmas" }, + expected: { name: "TypeError" } }, + { desc: "a negative Infinity iterations", + input: { iterations: -Infinity}, + expected: { name: "TypeError" } }, + { desc: "a NaN iterations", + input: { iterations: NaN }, + expected: { name: "TypeError" } }, + { desc: "a negative iterations", + input: { iterations: -1 }, + expected: { name: "TypeError" } }, + { desc: "a blank easing", + input: { easing: "" }, + expected: { name: "TypeError" } }, + { desc: "an unrecognized easing", + input: { easing: "unrecognised" }, + expected: { name: "TypeError" } }, + { desc: "an 'initial' easing", + input: { easing: "initial" }, + expected: { name: "TypeError" } }, + { desc: "an 'inherit' easing", + input: { easing: "inherit" }, + expected: { name: "TypeError" } }, + { desc: "a variable easing", + input: { easing: "var(--x)" }, + expected: { name: "TypeError" } }, + { desc: "a multi-value easing", + input: { easing: "ease-in-out, ease-out" }, expected: { name: "TypeError" } } ]; @@ -573,7 +613,7 @@ gInvalidKeyframeEffectOptionTests.forEach(function(stest) { test(function(t) { assert_throws(stest.expected, function() { new KeyframeEffectReadOnly(target, - {left: ["10px", "20px"]}, + { left: ["10px", "20px"] }, stest.input); }); }, "Invalid KeyframeEffectReadOnly option by " + stest.desc); diff --git a/tests/wpt/web-platform-tests/web-animations/keyframe-effect/effect-easing.html b/tests/wpt/web-platform-tests/web-animations/keyframe-effect/effect-easing.html index b3c39ad4f3b..2ecd028ce9b 100644 --- a/tests/wpt/web-platform-tests/web-animations/keyframe-effect/effect-easing.html +++ b/tests/wpt/web-platform-tests/web-animations/keyframe-effect/effect-easing.html @@ -434,5 +434,287 @@ test(function(t) { 'the lower boundary is infinity with keyframe easing producing ' + 'negative values'); +var gStepTimingFunctionTests = [ + { + description: 'Test bounds point of step-start easing', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + delay: 1000, + duration: 1000, + fill: 'both', + easing: 'steps(2, start)' + }, + conditions: [ + { currentTime: 0, progress: 0 }, + { currentTime: 999, progress: 0 }, + { currentTime: 1000, progress: 0.5 }, + { currentTime: 1499, progress: 0.5 }, + { currentTime: 1500, progress: 1 }, + { currentTime: 2000, progress: 1 } + ] + }, + { + description: 'Test bounds point of step-start easing with compositor', + keyframe: [ { opacity: 0 }, + { opacity: 1 } ], + effect: { + delay: 1000, + duration: 1000, + fill: 'both', + easing: 'steps(2, start)' + }, + conditions: [ + { currentTime: 0, progress: 0 }, + { currentTime: 999, progress: 0 }, + { currentTime: 1000, progress: 0.5 }, + { currentTime: 1499, progress: 0.5 }, + { currentTime: 1500, progress: 1 }, + { currentTime: 2000, progress: 1 } + ] + }, + { + description: 'Test bounds point of step-start easing with reverse direction', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + delay: 1000, + duration: 1000, + fill: 'both', + direction: 'reverse', + easing: 'steps(2, start)' + }, + conditions: [ + { currentTime: 0, progress: 1 }, + { currentTime: 1001, progress: 1 }, + { currentTime: 1500, progress: 1 }, + { currentTime: 1501, progress: 0.5 }, + { currentTime: 2000, progress: 0 }, + { currentTime: 2500, progress: 0 } + ] + }, + { + description: 'Test bounds point of step-start easing ' + + 'with iterationStart not at a transition point', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + delay: 1000, + duration: 1000, + fill: 'both', + iterationStart: 0.25, + easing: 'steps(2, start)' + }, + conditions: [ + { currentTime: 0, progress: 0.5 }, + { currentTime: 999, progress: 0.5 }, + { currentTime: 1000, progress: 0.5 }, + { currentTime: 1249, progress: 0.5 }, + { currentTime: 1250, progress: 1 }, + { currentTime: 1749, progress: 1 }, + { currentTime: 1750, progress: 0.5 }, + { currentTime: 2000, progress: 0.5 }, + { currentTime: 2500, progress: 0.5 }, + ] + }, + { + description: 'Test bounds point of step-start easing ' + + 'with iterationStart and delay', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + delay: 1000, + duration: 1000, + fill: 'both', + iterationStart: 0.5, + easing: 'steps(2, start)' + }, + conditions: [ + { currentTime: 0, progress: 0.5 }, + { currentTime: 999, progress: 0.5 }, + { currentTime: 1000, progress: 1 }, + { currentTime: 1499, progress: 1 }, + { currentTime: 1500, progress: 0.5 }, + { currentTime: 2000, progress: 1 } + ] + }, + { + description: 'Test bounds point of step-start easing ' + + 'with iterationStart and reverse direction', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + delay: 1000, + duration: 1000, + fill: 'both', + iterationStart: 0.5, + direction: 'reverse', + easing: 'steps(2, start)' + }, + conditions: [ + { currentTime: 0, progress: 1 }, + { currentTime: 1000, progress: 1 }, + { currentTime: 1001, progress: 0.5 }, + { currentTime: 1499, progress: 0.5 }, + { currentTime: 1500, progress: 1 }, + { currentTime: 1999, progress: 1 }, + { currentTime: 2000, progress: 0.5 }, + { currentTime: 2500, progress: 0.5 } + ] + }, + { + description: 'Test bounds point of step(4, start) easing ' + + 'with iterationStart 0.75 and delay', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + duration: 1000, + fill: 'both', + delay: 1000, + iterationStart: 0.75, + easing: 'steps(4, start)' + }, + conditions: [ + { currentTime: 0, progress: 0.75 }, + { currentTime: 999, progress: 0.75 }, + { currentTime: 1000, progress: 1 }, + { currentTime: 2000, progress: 1 }, + { currentTime: 2500, progress: 1 } + ] + }, + { + description: 'Test bounds point of step-start easing ' + + 'with alternate direction', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + duration: 1000, + fill: 'both', + delay: 1000, + iterations: 2, + iterationStart: 1.5, + direction: 'alternate', + easing: 'steps(2, start)' + }, + conditions: [ + { currentTime: 0, progress: 1 }, + { currentTime: 1000, progress: 1 }, + { currentTime: 1001, progress: 0.5 }, + { currentTime: 2999, progress: 1 }, + { currentTime: 3000, progress: 0.5 }, + { currentTime: 3500, progress: 0.5 } + ] + }, + { + description: 'Test bounds point of step-start easing ' + + 'with alternate-reverse direction', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + duration: 1000, + fill: 'both', + delay: 1000, + iterations: 2, + iterationStart: 0.5, + direction: 'alternate-reverse', + easing: 'steps(2, start)' + }, + conditions: [ + { currentTime: 0, progress: 1 }, + { currentTime: 1000, progress: 1 }, + { currentTime: 1001, progress: 0.5 }, + { currentTime: 2999, progress: 1 }, + { currentTime: 3000, progress: 0.5 }, + { currentTime: 3500, progress: 0.5 } + ] + }, + { + description: 'Test bounds point of step-start easing in keyframe', + keyframe: [ { width: '0px', easing: 'steps(2, start)' }, + { width: '100px' } ], + effect: { + delay: 1000, + duration: 1000, + fill: 'both', + }, + conditions: [ + { currentTime: 0, progress: 0, width: '0px' }, + { currentTime: 999, progress: 0, width: '0px' }, + { currentTime: 1000, progress: 0, width: '50px' }, + { currentTime: 1499, progress: 0.499, width: '50px' }, + { currentTime: 1500, progress: 0.5, width: '100px' }, + { currentTime: 2000, progress: 1, width: '100px' }, + { currentTime: 2500, progress: 1, width: '100px' } + ] + }, + { + description: 'Test bounds point of step-end easing ' + + 'with iterationStart and delay', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + duration: 1000, + fill: 'both', + delay: 1000, + iterationStart: 0.5, + easing: 'steps(2, end)' + }, + conditions: [ + { currentTime: 0, progress: 0 }, + { currentTime: 999, progress: 0 }, + { currentTime: 1000, progress: 0.5 }, + { currentTime: 1499, progress: 0.5 }, + { currentTime: 1500, progress: 0 }, + { currentTime: 1999, progress: 0 }, + { currentTime: 2000, progress: 0.5 }, + { currentTime: 2500, progress: 0.5 } + ] + }, + { + description: 'Test bounds point of step-end easing ' + + 'with iterationStart not at a transition point', + keyframe: [ { width: '0px' }, + { width: '100px' } ], + effect: { + delay: 1000, + duration: 1000, + fill: 'both', + iterationStart: 0.75, + easing: 'steps(2, end)' + }, + conditions: [ + { currentTime: 0, progress: 0.5 }, + { currentTime: 999, progress: 0.5 }, + { currentTime: 1000, progress: 0.5 }, + { currentTime: 1249, progress: 0.5 }, + { currentTime: 1250, progress: 0 }, + { currentTime: 1749, progress: 0 }, + { currentTime: 1750, progress: 0.5 }, + { currentTime: 2000, progress: 0.5 }, + { currentTime: 2500, progress: 0.5 }, + ] + } +] + +gStepTimingFunctionTests.forEach(function(options) { + test(function(t) { + var target = createDiv(t); + var animation = target.animate(options.keyframe, options.effect); + options.conditions.forEach(function(condition) { + animation.currentTime = condition.currentTime; + if (typeof condition.progress !== 'undefined') { + assert_equals(animation.effect.getComputedTiming().progress, + condition.progress, + 'Progress at ' + animation.currentTime + 'ms'); + } + if (typeof condition.width !== 'undefined') { + assert_equals(getComputedStyle(target).width, + condition.width, + 'Progress at ' + animation.currentTime + 'ms'); + } + }); + }, options.description); +}); + diff --git a/tests/wpt/web-platform-tests/web-animations/keyframe-effect/getComputedTiming.html b/tests/wpt/web-platform-tests/web-animations/keyframe-effect/getComputedTiming.html index 9ea723f9e72..d1b59cfd91a 100644 --- a/tests/wpt/web-platform-tests/web-animations/keyframe-effect/getComputedTiming.html +++ b/tests/wpt/web-platform-tests/web-animations/keyframe-effect/getComputedTiming.html @@ -62,15 +62,6 @@ var gGetComputedTimingTests = [ { desc: "an Infinity iterations", input: { iterations: Infinity }, expected: { iterations: Infinity } }, - { desc: "a negative Infinity iterations", - input: { iterations: -Infinity}, - expected: { iterations: 1 } }, - { desc: "a NaN iterations", - input: { iterations: NaN }, - expected: { iterations: 1 } }, - { desc: "a negative iterations", - input: { iterations: -1 }, - expected: { iterations: 1 } }, { desc: "an auto fill", input: { fill: "auto" }, expected: { fill: "none" } }, @@ -152,10 +143,7 @@ var gActiveDurationTests = [ expected: Infinity }, { desc: "an infinite duration and zero iteration count", input: { duration: Infinity, iterations: 0 }, - expected: 0 }, - { desc: "a non-zero duration and invalid iteration count", - input: { duration: 1000, iterations: "cabbage" }, - expected: 1000 } + expected: 0 } ]; gActiveDurationTests.forEach(function(stest) { diff --git a/tests/wpt/web-platform-tests/web-animations/testcommon.js b/tests/wpt/web-platform-tests/web-animations/testcommon.js index e7179cc1883..ab54202f10e 100644 --- a/tests/wpt/web-platform-tests/web-animations/testcommon.js +++ b/tests/wpt/web-platform-tests/web-animations/testcommon.js @@ -9,29 +9,7 @@ policies and contribution forms [3]. */ "use strict"; - -var ANIMATION_END_TIME = 1000; -var ANIMATION_TOP_DEFAULT = 300; -var ANIMATION_TOP_0 = 10; -var ANIMATION_TOP_0_5 = 100; -var ANIMATION_TOP_1 = 200; - -var KEYFRAMES = [ { - top : ANIMATION_TOP_0 + 'px', - offset : 0 -}, { - top : ANIMATION_TOP_0_5 + 'px', - offset : 1 / 2 -}, { - top : ANIMATION_TOP_1 + 'px', - offset : 1 -} ]; - -// creates new animation for given target -function newAnimation(animationTarget) { - animationTarget.style.top = ANIMATION_TOP_DEFAULT + 'px'; - return new Animation(animationTarget, KEYFRAMES, ANIMATION_END_TIME); -} +var MS_PER_SEC = 1000; // creates div element, appends it to the document body and // removes the created element during test cleanup @@ -91,11 +69,6 @@ function createPseudo(test, type) { return anim.effect.target; } -// Returns the type name of given object -function type(object) { - return Object.prototype.toString.call(object).slice(8, -1); -} - // Convert px unit value to a Number function pxToNum(str) { return Number(String(str).match(/^(-?[\d.]+)px$/)[1]); diff --git a/tests/wpt/web-platform-tests/webgl/OWNERS b/tests/wpt/web-platform-tests/webgl/OWNERS index fd31fb27543..0ed929edad3 100644 --- a/tests/wpt/web-platform-tests/webgl/OWNERS +++ b/tests/wpt/web-platform-tests/webgl/OWNERS @@ -1 +1,2 @@ @Ms2ger +@emilio diff --git a/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/context/resources/context-release-child-with-worker.html b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/context/resources/context-release-child-with-worker.html new file mode 100644 index 00000000000..f61e66a8e8f --- /dev/null +++ b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/context/resources/context-release-child-with-worker.html @@ -0,0 +1,78 @@ + + + + + + + Simple WebGL context with Worker + + + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/context/resources/context-release-upon-reload-child.html b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/context/resources/context-release-upon-reload-child.html new file mode 100644 index 00000000000..95ad1653f21 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/context/resources/context-release-upon-reload-child.html @@ -0,0 +1,77 @@ + + + + + + + Simple WebGL context + + + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/extensions/oes-vertex-array-object.html b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/extensions/oes-vertex-array-object.html index 38b606f3fd4..e138382a02d 100644 --- a/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/extensions/oes-vertex-array-object.html +++ b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/extensions/oes-vertex-array-object.html @@ -534,8 +534,10 @@ function runDeleteTests() { for (var ii = 0; ii < colorBuffers.length; ++ii) { gl.deleteBuffer(colorBuffers[ii]); gl.deleteBuffer(elementBuffers[ii]); + ext.bindVertexArrayOES(vaos[ii]); + var boundBuffer = gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING); // The buffers should still be valid at this point, since it was attached to the VAO - if(!gl.isBuffer(colorBuffers[ii])) { + if(boundBuffer != colorBuffers[ii]) { testFailed("buffer removed even though it is still attached to a VAO"); } } diff --git a/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/more/functions/texImage2DBadArgs.html b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/more/functions/texImage2DBadArgs.html index 9c59421f01e..bf5b71279bb 100644 --- a/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/more/functions/texImage2DBadArgs.html +++ b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/conformance/more/functions/texImage2DBadArgs.html @@ -63,7 +63,7 @@ Tests.testTexImage2D = function(gl) { assertGLError(gl, gl.INVALID_ENUM, "bad target", function(){ gl.texImage2D(gl.FLOAT, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, null); }); - assertGLError(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE], "bad internal format/format", function(){ + assertGLErrorIn(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE], "bad internal format/format", function(){ gl.texImage2D(gl.TEXTURE_2D, 0, gl.FLOAT, 1,1,0,gl.FLOAT,gl.UNSIGNED_BYTE, null); }); assertGLError(gl, gl.INVALID_VALUE, "border > 0", function(){ diff --git a/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/resources/js-test-pre.js b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/resources/js-test-pre.js index 4b902f96f25..6067e0d4608 100644 --- a/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/resources/js-test-pre.js +++ b/tests/wpt/web-platform-tests/webgl/conformance-1.0.3/resources/js-test-pre.js @@ -71,16 +71,25 @@ function nonKhronosFrameworkNotifyDone() { } } -var WPT_TEST_ID = 0; -function reportTestResultsToHarness(success, msg) { - if (window.parent.webglTestHarness) { - window.parent.webglTestHarness.reportResults(window.location.pathname, success, msg); - } else if (window.test) { // WPT test harness - test(function () { - assert_true(success, msg); - }, "WebGL test #" + (WPT_TEST_ID++) + ": " + msg); +(function() { + var WPT_TEST_ID = 0; + + // Store the current WPT test harness `test` function + // if found, since it's overriden by some tests. + var wpt_test = window.test; + var wpt_assert_true = window.assert_true; + + + window.reportTestResultsToHarness = function reportTestResultsToHarness(success, msg) { + if (window.parent.webglTestHarness) { + window.parent.webglTestHarness.reportResults(window.location.pathname, success, msg); + } else if (wpt_test) { // WPT test harness + wpt_test(function () { + wpt_assert_true(success, msg); + }, "WebGL test #" + (WPT_TEST_ID++) + ": " + msg); + } } -} +}()) function notifyFinishedToHarness() { if (window.parent.webglTestHarness) { diff --git a/tests/wpt/web-platform-tests/webgl/tools/import-conformance-tests.py b/tests/wpt/web-platform-tests/webgl/tools/import-conformance-tests.py index 0082e3c7dbf..8ac41a93d24 100755 --- a/tests/wpt/web-platform-tests/webgl/tools/import-conformance-tests.py +++ b/tests/wpt/web-platform-tests/webgl/tools/import-conformance-tests.py @@ -81,7 +81,7 @@ def main(): else: directory = tempfile.mkdtemp() print("Cloning WebGL repository into temporary directory {}".format(directory)) - subprocess.check_call(["git", "clone", KHRONOS_REPO_URL, directory]) + subprocess.check_call(["git", "clone", KHRONOS_REPO_URL, directory, "--depth", "1"]) suite_dir = os.path.join(directory, "conformance-suites", version) print("Test suite directory: {}".format(suite_dir)) @@ -109,6 +109,9 @@ def main(): # Remove html files that are not tests for dirpath, dirnames, filenames in os.walk(destination): + if '/resources' in dirpath: + continue # Most of the files under resources directories are used + for f in filenames: if not f.endswith('.html'): continue diff --git a/tests/wpt/web-platform-tests/webgl/tools/js-test-pre.patch b/tests/wpt/web-platform-tests/webgl/tools/js-test-pre.patch index 9c0f7897c33..1e8a4c9581d 100644 --- a/tests/wpt/web-platform-tests/webgl/tools/js-test-pre.patch +++ b/tests/wpt/web-platform-tests/webgl/tools/js-test-pre.patch @@ -1,21 +1,36 @@ ---- resources/js-test-pre.js 2015-06-18 23:26:41.217622000 +0200 -+++ ../conformance-1.0.3/resources/js-test-pre.js 2015-12-30 19:20:27.852467185 +0100 -@@ -71,9 +71,14 @@ +--- js-test-pre.orig.js 2016-04-08 22:35:15.629226767 +0200 ++++ js-test-pre.js 2016-04-08 22:43:11.906092062 +0200 +@@ -71,11 +71,25 @@ } } -+var WPT_TEST_ID = 0; - function reportTestResultsToHarness(success, msg) { +-function reportTestResultsToHarness(success, msg) { +- if (window.parent.webglTestHarness) { +- window.parent.webglTestHarness.reportResults(window.location.pathname, success, msg); ++(function() { ++ var WPT_TEST_ID = 0; ++ ++ // Store the current WPT test harness `test` function ++ // if found, since it's overriden by some tests. ++ var wpt_test = window.test; ++ var wpt_assert_true = window.assert_true; ++ ++ ++ window.reportTestResultsToHarness = function reportTestResultsToHarness(success, msg) { ++ if (window.parent.webglTestHarness) { ++ window.parent.webglTestHarness.reportResults(window.location.pathname, success, msg); ++ } else if (wpt_test) { // WPT test harness ++ wpt_test(function () { ++ wpt_assert_true(success, msg); ++ }, "WebGL test #" + (WPT_TEST_ID++) + ": " + msg); ++ } + } +-} ++}()) + + function notifyFinishedToHarness() { if (window.parent.webglTestHarness) { - window.parent.webglTestHarness.reportResults(window.location.pathname, success, msg); -+ } else if (window.test) { // WPT test harness -+ test(function () { -+ assert_true(success, msg); -+ }, "WebGL test #" + (WPT_TEST_ID++) + ": " + msg); - } - } - -@@ -92,7 +97,7 @@ +@@ -92,7 +106,7 @@ window.console.log(msg); } @@ -24,7 +39,7 @@ function enableJSTestPreVerboseLogging() { -@@ -105,31 +110,18 @@ +@@ -105,31 +119,18 @@ if (msg === undefined) { msg = document.title; } @@ -58,7 +73,7 @@ } } -@@ -143,7 +135,7 @@ +@@ -143,7 +144,7 @@ reportTestResultsToHarness(true, msg); _addSpan('PASS ' + escapeHTML(msg) + ''); if (_jsTestPreVerboseLogging) { diff --git a/tests/wpt/web-platform-tests/webstorage/event_setattribute.js b/tests/wpt/web-platform-tests/webstorage/event_setattribute.js index 9d8e328fcaf..8070938baf2 100644 --- a/tests/wpt/web-platform-tests/webstorage/event_setattribute.js +++ b/tests/wpt/web-platform-tests/webstorage/event_setattribute.js @@ -10,6 +10,9 @@ testStorages(function(storageString) { function step0(msg) { iframe.onload = t.step_func(step1); + // Null out the existing handler eventTestHarness.js set up; + // otherwise this test won't be testing much of anything useful. + iframe.contentWindow.onstorage = null; iframe.src = "resources/event_setattribute_handler.html"; } diff --git a/tests/wpt/web-platform-tests/webstorage/resources/event_setattribute_handler.html b/tests/wpt/web-platform-tests/webstorage/resources/event_setattribute_handler.html index f5d6f8a06ff..b9e2f040216 100644 --- a/tests/wpt/web-platform-tests/webstorage/resources/event_setattribute_handler.html +++ b/tests/wpt/web-platform-tests/webstorage/resources/event_setattribute_handler.html @@ -8,7 +8,7 @@ function handleStorageEvent(e) { window.parent.storageEventList.push(e); } -document.body.setAttribute("onstorage", "handleStorageEvent(window.event);"); +document.body.setAttribute("onstorage", "handleStorageEvent(event);");