diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json index d15626d6f53e..bf46bb649377 100644 --- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -145,6 +145,12 @@ {} ] ], + "accelerometer/Accelerometer_onerror-manual.https.html": [ + [ + "/accelerometer/Accelerometer_onerror-manual.https.html", + {} + ] + ], "ambient-light/AmbientLightSensor_onerror-manual.https.html": [ [ "/ambient-light/AmbientLightSensor_onerror-manual.https.html", @@ -235,12 +241,6 @@ {} ] ], - "auxclick/auxclick_event-manual.html": [ - [ - "/auxclick/auxclick_event-manual.html", - {} - ] - ], "battery-status/battery-charging-manual.html": [ [ "/battery-status/battery-charging-manual.html", @@ -1039,6 +1039,240 @@ {} ] ], + "dpub-aam/doc-abstract-manual.html": [ + [ + "/dpub-aam/doc-abstract-manual.html", + {} + ] + ], + "dpub-aam/doc-acknowledgments-manual.html": [ + [ + "/dpub-aam/doc-acknowledgments-manual.html", + {} + ] + ], + "dpub-aam/doc-afterword-manual.html": [ + [ + "/dpub-aam/doc-afterword-manual.html", + {} + ] + ], + "dpub-aam/doc-appendix-manual.html": [ + [ + "/dpub-aam/doc-appendix-manual.html", + {} + ] + ], + "dpub-aam/doc-backlink-manual.html": [ + [ + "/dpub-aam/doc-backlink-manual.html", + {} + ] + ], + "dpub-aam/doc-biblioentry-manual.html": [ + [ + "/dpub-aam/doc-biblioentry-manual.html", + {} + ] + ], + "dpub-aam/doc-bibliography-manual.html": [ + [ + "/dpub-aam/doc-bibliography-manual.html", + {} + ] + ], + "dpub-aam/doc-biblioref-manual.html": [ + [ + "/dpub-aam/doc-biblioref-manual.html", + {} + ] + ], + "dpub-aam/doc-chapter-manual.html": [ + [ + "/dpub-aam/doc-chapter-manual.html", + {} + ] + ], + "dpub-aam/doc-colophon-manual.html": [ + [ + "/dpub-aam/doc-colophon-manual.html", + {} + ] + ], + "dpub-aam/doc-conclusion-manual.html": [ + [ + "/dpub-aam/doc-conclusion-manual.html", + {} + ] + ], + "dpub-aam/doc-cover-manual.html": [ + [ + "/dpub-aam/doc-cover-manual.html", + {} + ] + ], + "dpub-aam/doc-credit-manual.html": [ + [ + "/dpub-aam/doc-credit-manual.html", + {} + ] + ], + "dpub-aam/doc-credits-manual.html": [ + [ + "/dpub-aam/doc-credits-manual.html", + {} + ] + ], + "dpub-aam/doc-dedication-manual.html": [ + [ + "/dpub-aam/doc-dedication-manual.html", + {} + ] + ], + "dpub-aam/doc-endnote-manual.html": [ + [ + "/dpub-aam/doc-endnote-manual.html", + {} + ] + ], + "dpub-aam/doc-endnotes-manual.html": [ + [ + "/dpub-aam/doc-endnotes-manual.html", + {} + ] + ], + "dpub-aam/doc-epigraph-manual.html": [ + [ + "/dpub-aam/doc-epigraph-manual.html", + {} + ] + ], + "dpub-aam/doc-epilogue-manual.html": [ + [ + "/dpub-aam/doc-epilogue-manual.html", + {} + ] + ], + "dpub-aam/doc-errata-manual.html": [ + [ + "/dpub-aam/doc-errata-manual.html", + {} + ] + ], + "dpub-aam/doc-example-manual.html": [ + [ + "/dpub-aam/doc-example-manual.html", + {} + ] + ], + "dpub-aam/doc-footnote-manual.html": [ + [ + "/dpub-aam/doc-footnote-manual.html", + {} + ] + ], + "dpub-aam/doc-foreword-manual.html": [ + [ + "/dpub-aam/doc-foreword-manual.html", + {} + ] + ], + "dpub-aam/doc-glossary-manual.html": [ + [ + "/dpub-aam/doc-glossary-manual.html", + {} + ] + ], + "dpub-aam/doc-glossref-manual.html": [ + [ + "/dpub-aam/doc-glossref-manual.html", + {} + ] + ], + "dpub-aam/doc-index-manual.html": [ + [ + "/dpub-aam/doc-index-manual.html", + {} + ] + ], + "dpub-aam/doc-introduction-manual.html": [ + [ + "/dpub-aam/doc-introduction-manual.html", + {} + ] + ], + "dpub-aam/doc-noteref-manual.html": [ + [ + "/dpub-aam/doc-noteref-manual.html", + {} + ] + ], + "dpub-aam/doc-notice-manual.html": [ + [ + "/dpub-aam/doc-notice-manual.html", + {} + ] + ], + "dpub-aam/doc-pagebreak-manual.html": [ + [ + "/dpub-aam/doc-pagebreak-manual.html", + {} + ] + ], + "dpub-aam/doc-pagelist-manual.html": [ + [ + "/dpub-aam/doc-pagelist-manual.html", + {} + ] + ], + "dpub-aam/doc-part-manual.html": [ + [ + "/dpub-aam/doc-part-manual.html", + {} + ] + ], + "dpub-aam/doc-preface-manual.html": [ + [ + "/dpub-aam/doc-preface-manual.html", + {} + ] + ], + "dpub-aam/doc-prologue-manual.html": [ + [ + "/dpub-aam/doc-prologue-manual.html", + {} + ] + ], + "dpub-aam/doc-pullquote-manual.html": [ + [ + "/dpub-aam/doc-pullquote-manual.html", + {} + ] + ], + "dpub-aam/doc-qna-manual.html": [ + [ + "/dpub-aam/doc-qna-manual.html", + {} + ] + ], + "dpub-aam/doc-subtitle-manual.html": [ + [ + "/dpub-aam/doc-subtitle-manual.html", + {} + ] + ], + "dpub-aam/doc-tip-manual.html": [ + [ + "/dpub-aam/doc-tip-manual.html", + {} + ] + ], + "dpub-aam/doc-toc-manual.html": [ + [ + "/dpub-aam/doc-toc-manual.html", + {} + ] + ], "dpub-aria/inuse-manual.html": [ [ "/dpub-aria/inuse-manual.html", @@ -1291,6 +1525,12 @@ {} ] ], + "gyroscope/Gyroscope_onerror-manual.https.html": [ + [ + "/gyroscope/Gyroscope_onerror-manual.https.html", + {} + ] + ], "html-longdesc/data-uri-image-data-uri-description-manual.html": [ [ "/html-longdesc/data-uri-image-data-uri-description-manual.html", @@ -1447,21 +1687,33 @@ {} ] ], - "html-media-capture/capture_image-manual.html": [ - [ - "/html-media-capture/capture_image-manual.html", - {} - ] - ], "html-media-capture/capture_image_cancel-manual.html": [ [ "/html-media-capture/capture_image_cancel-manual.html", {} ] ], - "html-media-capture/capture_video-manual.html": [ + "html-media-capture/capture_image_environment-manual.html": [ [ - "/html-media-capture/capture_video-manual.html", + "/html-media-capture/capture_image_environment-manual.html", + {} + ] + ], + "html-media-capture/capture_image_invalid-manual.html": [ + [ + "/html-media-capture/capture_image_invalid-manual.html", + {} + ] + ], + "html-media-capture/capture_image_missing-manual.html": [ + [ + "/html-media-capture/capture_image_missing-manual.html", + {} + ] + ], + "html-media-capture/capture_image_user-manual.html": [ + [ + "/html-media-capture/capture_image_user-manual.html", {} ] ], @@ -1471,6 +1723,30 @@ {} ] ], + "html-media-capture/capture_video_environment-manual.html": [ + [ + "/html-media-capture/capture_video_environment-manual.html", + {} + ] + ], + "html-media-capture/capture_video_invalid-manual.html": [ + [ + "/html-media-capture/capture_video_invalid-manual.html", + {} + ] + ], + "html-media-capture/capture_video_missing-manual.html": [ + [ + "/html-media-capture/capture_video_missing-manual.html", + {} + ] + ], + "html-media-capture/capture_video_user-manual.html": [ + [ + "/html-media-capture/capture_video_user-manual.html", + {} + ] + ], "html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_1-manual.html": [ [ "/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_1-manual.html", @@ -2401,6 +2677,12 @@ {} ] ], + "magnetometer/Magnetometer_onerror-manual.https.html": [ + [ + "/magnetometer/Magnetometer_onerror-manual.https.html", + {} + ] + ], "mathml/relations/html5-tree/href-manual.html": [ [ "/mathml/relations/html5-tree/href-manual.html", @@ -3337,6 +3619,36 @@ {} ] ], + "presentation-api/receiving-ua/PresentationConnectionList_onconnectionavailable-manual.https.html": [ + [ + "/presentation-api/receiving-ua/PresentationConnectionList_onconnectionavailable-manual.https.html", + {} + ] + ], + "presentation-api/receiving-ua/PresentationConnection_onclose-manual.https.html": [ + [ + "/presentation-api/receiving-ua/PresentationConnection_onclose-manual.https.html", + {} + ] + ], + "presentation-api/receiving-ua/PresentationConnection_onmessage-manual.https.html": [ + [ + "/presentation-api/receiving-ua/PresentationConnection_onmessage-manual.https.html", + {} + ] + ], + "presentation-api/receiving-ua/PresentationConnection_send-manual.https.html": [ + [ + "/presentation-api/receiving-ua/PresentationConnection_send-manual.https.html", + {} + ] + ], + "presentation-api/receiving-ua/PresentationConnection_terminate-manual.https.html": [ + [ + "/presentation-api/receiving-ua/PresentationConnection_terminate-manual.https.html", + {} + ] + ], "presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html": [ [ "/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html", @@ -6523,6 +6835,12 @@ {} ] ], + "uievents/auxclick/auxclick_event-manual.html": [ + [ + "/uievents/auxclick/auxclick_event-manual.html", + {} + ] + ], "uievents/interface/click-event-manual.htm": [ [ "/uievents/interface/click-event-manual.htm", @@ -6559,6 +6877,12 @@ {} ] ], + "uievents/mouse/mouseevent_move_button-manual.html": [ + [ + "/uievents/mouse/mouseevent_move_button-manual.html", + {} + ] + ], "uievents/order-of-events/focus-events/focus-contained-manual.html": [ [ "/uievents/order-of-events/focus-events/focus-contained-manual.html", @@ -6691,6 +7015,1344 @@ {} ] ], + "wai-aria/alertdialog_modal_false-manual.html": [ + [ + "/wai-aria/alertdialog_modal_false-manual.html", + {} + ] + ], + "wai-aria/alertdialog_modal_true-manual.html": [ + [ + "/wai-aria/alertdialog_modal_true-manual.html", + {} + ] + ], + "wai-aria/application_activedescendant-manual.html": [ + [ + "/wai-aria/application_activedescendant-manual.html", + {} + ] + ], + "wai-aria/application_activedescendant_value_changes-manual.html": [ + [ + "/wai-aria/application_activedescendant_value_changes-manual.html", + {} + ] + ], + "wai-aria/aria-current_not_declared-manual.html": [ + [ + "/wai-aria/aria-current_not_declared-manual.html", + {} + ] + ], + "wai-aria/aria-current_with_value_changes-manual.html": [ + [ + "/wai-aria/aria-current_with_value_changes-manual.html", + {} + ] + ], + "wai-aria/aria-current_with_value_date-manual.html": [ + [ + "/wai-aria/aria-current_with_value_date-manual.html", + {} + ] + ], + "wai-aria/aria-current_with_value_location-manual.html": [ + [ + "/wai-aria/aria-current_with_value_location-manual.html", + {} + ] + ], + "wai-aria/aria-current_with_value_page-manual.html": [ + [ + "/wai-aria/aria-current_with_value_page-manual.html", + {} + ] + ], + "wai-aria/aria-current_with_value_step-manual.html": [ + [ + "/wai-aria/aria-current_with_value_step-manual.html", + {} + ] + ], + "wai-aria/aria-current_with_value_time-manual.html": [ + [ + "/wai-aria/aria-current_with_value_time-manual.html", + {} + ] + ], + "wai-aria/aria-current_with_value_true-manual.html": [ + [ + "/wai-aria/aria-current_with_value_true-manual.html", + {} + ] + ], + "wai-aria/aria-current_with_value_unspecified-manual.html": [ + [ + "/wai-aria/aria-current_with_value_unspecified-manual.html", + {} + ] + ], + "wai-aria/aria-details_pointing_to_details_element-manual.html": [ + [ + "/wai-aria/aria-details_pointing_to_details_element-manual.html", + {} + ] + ], + "wai-aria/aria-details_pointing_to_div_element-manual.html": [ + [ + "/wai-aria/aria-details_pointing_to_div_element-manual.html", + {} + ] + ], + "wai-aria/article_in_feed_posinset_and_setsize-manual.html": [ + [ + "/wai-aria/article_in_feed_posinset_and_setsize-manual.html", + {} + ] + ], + "wai-aria/article_in_feed_setsize_-1-manual.html": [ + [ + "/wai-aria/article_in_feed_setsize_-1-manual.html", + {} + ] + ], + "wai-aria/article_not_in_feed_posinset_and_setsize-manual.html": [ + [ + "/wai-aria/article_not_in_feed_posinset_and_setsize-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_dialog-manual.html": [ + [ + "/wai-aria/button_haspopup_dialog-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_emptystring-manual.html": [ + [ + "/wai-aria/button_haspopup_emptystring-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_false-manual.html": [ + [ + "/wai-aria/button_haspopup_false-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_foo-manual.html": [ + [ + "/wai-aria/button_haspopup_foo-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_grid-manual.html": [ + [ + "/wai-aria/button_haspopup_grid-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_listbox-manual.html": [ + [ + "/wai-aria/button_haspopup_listbox-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_menu-manual.html": [ + [ + "/wai-aria/button_haspopup_menu-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_tree-manual.html": [ + [ + "/wai-aria/button_haspopup_tree-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_true-manual.html": [ + [ + "/wai-aria/button_haspopup_true-manual.html", + {} + ] + ], + "wai-aria/button_haspopup_unspecified-manual.html": [ + [ + "/wai-aria/button_haspopup_unspecified-manual.html", + {} + ] + ], + "wai-aria/button_roledescription_empty-manual.html": [ + [ + "/wai-aria/button_roledescription_empty-manual.html", + {} + ] + ], + "wai-aria/button_roledescription_valid-manual.html": [ + [ + "/wai-aria/button_roledescription_valid-manual.html", + {} + ] + ], + "wai-aria/button_roledescription_whitespace_only-manual.html": [ + [ + "/wai-aria/button_roledescription_whitespace_only-manual.html", + {} + ] + ], + "wai-aria/cell-manual.html": [ + [ + "/wai-aria/cell-manual.html", + {} + ] + ], + "wai-aria/cell_aria-colspan_2_on_div-manual.html": [ + [ + "/wai-aria/cell_aria-colspan_2_on_div-manual.html", + {} + ] + ], + "wai-aria/cell_aria-colspan_2_on_td_html_colspan_3-manual.html": [ + [ + "/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3-manual.html", + {} + ] + ], + "wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_headers_and_border-manual.html": [ + [ + "/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_headers_and_border-manual.html", + {} + ] + ], + "wai-aria/cell_aria-colspan_2_on_td_with_html_colspan_not_specified-manual.html": [ + [ + "/wai-aria/cell_aria-colspan_2_on_td_with_html_colspan_not_specified-manual.html", + {} + ] + ], + "wai-aria/cell_aria-rowspan_2_on_div-manual.html": [ + [ + "/wai-aria/cell_aria-rowspan_2_on_div-manual.html", + {} + ] + ], + "wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3-manual.html": [ + [ + "/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3-manual.html", + {} + ] + ], + "wai-aria/cell_aria-rowspan_2_on_td_with_html_rowspan_not_specified-manual.html": [ + [ + "/wai-aria/cell_aria-rowspan_2_on_td_with_html_rowspan_not_specified-manual.html", + {} + ] + ], + "wai-aria/cell_colindex_4-manual.html": [ + [ + "/wai-aria/cell_colindex_4-manual.html", + {} + ] + ], + "wai-aria/cell_rowindex_4-manual.html": [ + [ + "/wai-aria/cell_rowindex_4-manual.html", + {} + ] + ], + "wai-aria/checkbox_readonly_false-manual.html": [ + [ + "/wai-aria/checkbox_readonly_false-manual.html", + {} + ] + ], + "wai-aria/checkbox_readonly_true-manual.html": [ + [ + "/wai-aria/checkbox_readonly_true-manual.html", + {} + ] + ], + "wai-aria/checkbox_readonly_unspecified-manual.html": [ + [ + "/wai-aria/checkbox_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/columnheader_aria-colspan_2_on_div-manual.html": [ + [ + "/wai-aria/columnheader_aria-colspan_2_on_div-manual.html", + {} + ] + ], + "wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3-manual.html": [ + [ + "/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3-manual.html", + {} + ] + ], + "wai-aria/columnheader_aria-colspan_2_on_th_with_html_colspan_not_specified-manual.html": [ + [ + "/wai-aria/columnheader_aria-colspan_2_on_th_with_html_colspan_not_specified-manual.html", + {} + ] + ], + "wai-aria/columnheader_aria-rowspan_2_on_div-manual.html": [ + [ + "/wai-aria/columnheader_aria-rowspan_2_on_div-manual.html", + {} + ] + ], + "wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3-manual.html": [ + [ + "/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3-manual.html", + {} + ] + ], + "wai-aria/columnheader_aria-rowspan_2_on_th_with_html_rowspan_not_specified-manual.html": [ + [ + "/wai-aria/columnheader_aria-rowspan_2_on_th_with_html_rowspan_not_specified-manual.html", + {} + ] + ], + "wai-aria/columnheader_colindex_4-manual.html": [ + [ + "/wai-aria/columnheader_colindex_4-manual.html", + {} + ] + ], + "wai-aria/columnheader_rowindex_4-manual.html": [ + [ + "/wai-aria/columnheader_rowindex_4-manual.html", + {} + ] + ], + "wai-aria/columnheader_selected_false_not_automatically_propagated-manual.html": [ + [ + "/wai-aria/columnheader_selected_false_not_automatically_propagated-manual.html", + {} + ] + ], + "wai-aria/columnheader_selected_true_not_automatically_propagated-manual.html": [ + [ + "/wai-aria/columnheader_selected_true_not_automatically_propagated-manual.html", + {} + ] + ], + "wai-aria/combobox_controls_an_invalid_id-manual.html": [ + [ + "/wai-aria/combobox_controls_an_invalid_id-manual.html", + {} + ] + ], + "wai-aria/combobox_haspopup_dialog-manual.html": [ + [ + "/wai-aria/combobox_haspopup_dialog-manual.html", + {} + ] + ], + "wai-aria/combobox_haspopup_false-manual.html": [ + [ + "/wai-aria/combobox_haspopup_false-manual.html", + {} + ] + ], + "wai-aria/combobox_haspopup_grid-manual.html": [ + [ + "/wai-aria/combobox_haspopup_grid-manual.html", + {} + ] + ], + "wai-aria/combobox_haspopup_listbox-manual.html": [ + [ + "/wai-aria/combobox_haspopup_listbox-manual.html", + {} + ] + ], + "wai-aria/combobox_haspopup_menu-manual.html": [ + [ + "/wai-aria/combobox_haspopup_menu-manual.html", + {} + ] + ], + "wai-aria/combobox_haspopup_tree-manual.html": [ + [ + "/wai-aria/combobox_haspopup_tree-manual.html", + {} + ] + ], + "wai-aria/combobox_haspopup_true-manual.html": [ + [ + "/wai-aria/combobox_haspopup_true-manual.html", + {} + ] + ], + "wai-aria/combobox_haspopup_unspecified-manual.html": [ + [ + "/wai-aria/combobox_haspopup_unspecified-manual.html", + {} + ] + ], + "wai-aria/combobox_orientation_horizontal-manual.html": [ + [ + "/wai-aria/combobox_orientation_horizontal-manual.html", + {} + ] + ], + "wai-aria/combobox_orientation_unspecified-manual.html": [ + [ + "/wai-aria/combobox_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/combobox_orientation_vertical-manual.html": [ + [ + "/wai-aria/combobox_orientation_vertical-manual.html", + {} + ] + ], + "wai-aria/combobox_readonly_false-manual.html": [ + [ + "/wai-aria/combobox_readonly_false-manual.html", + {} + ] + ], + "wai-aria/combobox_readonly_true-manual.html": [ + [ + "/wai-aria/combobox_readonly_true-manual.html", + {} + ] + ], + "wai-aria/combobox_readonly_unspecified-manual.html": [ + [ + "/wai-aria/combobox_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/dialog_modal_false-manual.html": [ + [ + "/wai-aria/dialog_modal_false-manual.html", + {} + ] + ], + "wai-aria/dialog_modal_true-manual.html": [ + [ + "/wai-aria/dialog_modal_true-manual.html", + {} + ] + ], + "wai-aria/dialog_modal_unspecified-manual.html": [ + [ + "/wai-aria/dialog_modal_unspecified-manual.html", + {} + ] + ], + "wai-aria/div_element_without_role_roledescription_valid-manual.html": [ + [ + "/wai-aria/div_element_without_role_roledescription_valid-manual.html", + {} + ] + ], + "wai-aria/errormessage_object_in_invalid_state-manual.html": [ + [ + "/wai-aria/errormessage_object_in_invalid_state-manual.html", + {} + ] + ], + "wai-aria/errormessage_object_in_valid_state-manual.html": [ + [ + "/wai-aria/errormessage_object_in_valid_state-manual.html", + {} + ] + ], + "wai-aria/feed-manual.html": [ + [ + "/wai-aria/feed-manual.html", + {} + ] + ], + "wai-aria/figure-manual.html": [ + [ + "/wai-aria/figure-manual.html", + {} + ] + ], + "wai-aria/grid_aria-readonly_false_automatically_propagated-manual.html": [ + [ + "/wai-aria/grid_aria-readonly_false_automatically_propagated-manual.html", + {} + ] + ], + "wai-aria/grid_aria-readonly_true_automatically_propagated-manual.html": [ + [ + "/wai-aria/grid_aria-readonly_true_automatically_propagated-manual.html", + {} + ] + ], + "wai-aria/grid_busy_false-manual.html": [ + [ + "/wai-aria/grid_busy_false-manual.html", + {} + ] + ], + "wai-aria/grid_busy_true-manual.html": [ + [ + "/wai-aria/grid_busy_true-manual.html", + {} + ] + ], + "wai-aria/grid_busy_value_changes-manual.html": [ + [ + "/wai-aria/grid_busy_value_changes-manual.html", + {} + ] + ], + "wai-aria/grid_colcount_8-manual.html": [ + [ + "/wai-aria/grid_colcount_8-manual.html", + {} + ] + ], + "wai-aria/grid_columnheader_readonly_false-manual.html": [ + [ + "/wai-aria/grid_columnheader_readonly_false-manual.html", + {} + ] + ], + "wai-aria/grid_columnheader_readonly_true-manual.html": [ + [ + "/wai-aria/grid_columnheader_readonly_true-manual.html", + {} + ] + ], + "wai-aria/grid_columnheader_readonly_unspecified-manual.html": [ + [ + "/wai-aria/grid_columnheader_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/grid_columnheader_required_false-manual.html": [ + [ + "/wai-aria/grid_columnheader_required_false-manual.html", + {} + ] + ], + "wai-aria/grid_columnheader_required_true-manual.html": [ + [ + "/wai-aria/grid_columnheader_required_true-manual.html", + {} + ] + ], + "wai-aria/grid_columnheader_required_unspecified-manual.html": [ + [ + "/wai-aria/grid_columnheader_required_unspecified-manual.html", + {} + ] + ], + "wai-aria/grid_rowcount_3-manual.html": [ + [ + "/wai-aria/grid_rowcount_3-manual.html", + {} + ] + ], + "wai-aria/grid_rowheader_readonly_false-manual.html": [ + [ + "/wai-aria/grid_rowheader_readonly_false-manual.html", + {} + ] + ], + "wai-aria/grid_rowheader_readonly_true-manual.html": [ + [ + "/wai-aria/grid_rowheader_readonly_true-manual.html", + {} + ] + ], + "wai-aria/grid_rowheader_readonly_unspecified-manual.html": [ + [ + "/wai-aria/grid_rowheader_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/grid_rowheader_required_false-manual.html": [ + [ + "/wai-aria/grid_rowheader_required_false-manual.html", + {} + ] + ], + "wai-aria/grid_rowheader_required_true-manual.html": [ + [ + "/wai-aria/grid_rowheader_required_true-manual.html", + {} + ] + ], + "wai-aria/grid_rowheader_required_unspecified-manual.html": [ + [ + "/wai-aria/grid_rowheader_required_unspecified-manual.html", + {} + ] + ], + "wai-aria/gridcell_aria-colspan_2_on_div-manual.html": [ + [ + "/wai-aria/gridcell_aria-colspan_2_on_div-manual.html", + {} + ] + ], + "wai-aria/gridcell_aria-rowspan_2_on_div-manual.html": [ + [ + "/wai-aria/gridcell_aria-rowspan_2_on_div-manual.html", + {} + ] + ], + "wai-aria/gridcell_colindex_4-manual.html": [ + [ + "/wai-aria/gridcell_colindex_4-manual.html", + {} + ] + ], + "wai-aria/gridcell_rowindex_4-manual.html": [ + [ + "/wai-aria/gridcell_rowindex_4-manual.html", + {} + ] + ], + "wai-aria/group_hidden_undefined_element_not_rendered-manual.html": [ + [ + "/wai-aria/group_hidden_undefined_element_not_rendered-manual.html", + {} + ] + ], + "wai-aria/group_hidden_undefined_element_rendered-manual.html": [ + [ + "/wai-aria/group_hidden_undefined_element_rendered-manual.html", + {} + ] + ], + "wai-aria/heading_level_unspecified-manual.html": [ + [ + "/wai-aria/heading_level_unspecified-manual.html", + {} + ] + ], + "wai-aria/keyshortcuts_multiple_shortcuts-manual.html": [ + [ + "/wai-aria/keyshortcuts_multiple_shortcuts-manual.html", + {} + ] + ], + "wai-aria/keyshortcuts_one_shortcut-manual.html": [ + [ + "/wai-aria/keyshortcuts_one_shortcut-manual.html", + {} + ] + ], + "wai-aria/listbox_busy_false-manual.html": [ + [ + "/wai-aria/listbox_busy_false-manual.html", + {} + ] + ], + "wai-aria/listbox_busy_true-manual.html": [ + [ + "/wai-aria/listbox_busy_true-manual.html", + {} + ] + ], + "wai-aria/listbox_orientation_horizontal-manual.html": [ + [ + "/wai-aria/listbox_orientation_horizontal-manual.html", + {} + ] + ], + "wai-aria/listbox_orientation_unspecified-manual.html": [ + [ + "/wai-aria/listbox_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/listbox_orientation_vertical-manual.html": [ + [ + "/wai-aria/listbox_orientation_vertical-manual.html", + {} + ] + ], + "wai-aria/listbox_readonly_false-manual.html": [ + [ + "/wai-aria/listbox_readonly_false-manual.html", + {} + ] + ], + "wai-aria/listbox_readonly_true-manual.html": [ + [ + "/wai-aria/listbox_readonly_true-manual.html", + {} + ] + ], + "wai-aria/listbox_readonly_unspecified-manual.html": [ + [ + "/wai-aria/listbox_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/listitem_setsize_-1-manual.html": [ + [ + "/wai-aria/listitem_setsize_-1-manual.html", + {} + ] + ], + "wai-aria/menu_orientation_horizontal-manual.html": [ + [ + "/wai-aria/menu_orientation_horizontal-manual.html", + {} + ] + ], + "wai-aria/menu_orientation_unspecified-manual.html": [ + [ + "/wai-aria/menu_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/menu_orientation_vertical-manual.html": [ + [ + "/wai-aria/menu_orientation_vertical-manual.html", + {} + ] + ], + "wai-aria/menubar_busy_false-manual.html": [ + [ + "/wai-aria/menubar_busy_false-manual.html", + {} + ] + ], + "wai-aria/menubar_busy_true-manual.html": [ + [ + "/wai-aria/menubar_busy_true-manual.html", + {} + ] + ], + "wai-aria/menubar_orientation_horizontal-manual.html": [ + [ + "/wai-aria/menubar_orientation_horizontal-manual.html", + {} + ] + ], + "wai-aria/menubar_orientation_unspecified-manual.html": [ + [ + "/wai-aria/menubar_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/menubar_orientation_vertical-manual.html": [ + [ + "/wai-aria/menubar_orientation_vertical-manual.html", + {} + ] + ], + "wai-aria/menuitem_posinset_and_setsize-manual.html": [ + [ + "/wai-aria/menuitem_posinset_and_setsize-manual.html", + {} + ] + ], + "wai-aria/menuitemcheckbox_posinset_and_setsize-manual.html": [ + [ + "/wai-aria/menuitemcheckbox_posinset_and_setsize-manual.html", + {} + ] + ], + "wai-aria/menuitemcheckbox_readonly_false-manual.html": [ + [ + "/wai-aria/menuitemcheckbox_readonly_false-manual.html", + {} + ] + ], + "wai-aria/menuitemcheckbox_readonly_true-manual.html": [ + [ + "/wai-aria/menuitemcheckbox_readonly_true-manual.html", + {} + ] + ], + "wai-aria/menuitemcheckbox_readonly_unspecified-manual.html": [ + [ + "/wai-aria/menuitemcheckbox_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/menuitemradio_posinset_and_setsize-manual.html": [ + [ + "/wai-aria/menuitemradio_posinset_and_setsize-manual.html", + {} + ] + ], + "wai-aria/menuitemradio_readonly_false-manual.html": [ + [ + "/wai-aria/menuitemradio_readonly_false-manual.html", + {} + ] + ], + "wai-aria/menuitemradio_readonly_true-manual.html": [ + [ + "/wai-aria/menuitemradio_readonly_true-manual.html", + {} + ] + ], + "wai-aria/menuitemradio_readonly_unspecified-manual.html": [ + [ + "/wai-aria/menuitemradio_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/none-manual.html": [ + [ + "/wai-aria/none-manual.html", + {} + ] + ], + "wai-aria/option_selected_false-manual.html": [ + [ + "/wai-aria/option_selected_false-manual.html", + {} + ] + ], + "wai-aria/option_selected_true-manual.html": [ + [ + "/wai-aria/option_selected_true-manual.html", + {} + ] + ], + "wai-aria/option_selected_undefined-manual.html": [ + [ + "/wai-aria/option_selected_undefined-manual.html", + {} + ] + ], + "wai-aria/option_selected_value_changes-manual.html": [ + [ + "/wai-aria/option_selected_value_changes-manual.html", + {} + ] + ], + "wai-aria/radiogroup_orientation_horizontal-manual.html": [ + [ + "/wai-aria/radiogroup_orientation_horizontal-manual.html", + {} + ] + ], + "wai-aria/radiogroup_orientation_unspecified-manual.html": [ + [ + "/wai-aria/radiogroup_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/radiogroup_orientation_vertical-manual.html": [ + [ + "/wai-aria/radiogroup_orientation_vertical-manual.html", + {} + ] + ], + "wai-aria/radiogroup_readonly_false-manual.html": [ + [ + "/wai-aria/radiogroup_readonly_false-manual.html", + {} + ] + ], + "wai-aria/radiogroup_readonly_true-manual.html": [ + [ + "/wai-aria/radiogroup_readonly_true-manual.html", + {} + ] + ], + "wai-aria/radiogroup_readonly_unspecified-manual.html": [ + [ + "/wai-aria/radiogroup_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/region_with_name-manual.html": [ + [ + "/wai-aria/region_with_name-manual.html", + {} + ] + ], + "wai-aria/region_without_name-manual.html": [ + [ + "/wai-aria/region_without_name-manual.html", + {} + ] + ], + "wai-aria/row_colindex_4-manual.html": [ + [ + "/wai-aria/row_colindex_4-manual.html", + {} + ] + ], + "wai-aria/row_rowindex_4-manual.html": [ + [ + "/wai-aria/row_rowindex_4-manual.html", + {} + ] + ], + "wai-aria/rowheader_aria-colspan_2_on_div-manual.html": [ + [ + "/wai-aria/rowheader_aria-colspan_2_on_div-manual.html", + {} + ] + ], + "wai-aria/rowheader_aria-rowspan_2_on_div-manual.html": [ + [ + "/wai-aria/rowheader_aria-rowspan_2_on_div-manual.html", + {} + ] + ], + "wai-aria/rowheader_colindex_4-manual.html": [ + [ + "/wai-aria/rowheader_colindex_4-manual.html", + {} + ] + ], + "wai-aria/rowheader_rowindex_4-manual.html": [ + [ + "/wai-aria/rowheader_rowindex_4-manual.html", + {} + ] + ], + "wai-aria/rowheader_selected_false_not_automatically_propagated-manual.html": [ + [ + "/wai-aria/rowheader_selected_false_not_automatically_propagated-manual.html", + {} + ] + ], + "wai-aria/rowheader_selected_true_not_automatically_propagated-manual.html": [ + [ + "/wai-aria/rowheader_selected_true_not_automatically_propagated-manual.html", + {} + ] + ], + "wai-aria/scrollbar_all_values_unspecified-manual.html": [ + [ + "/wai-aria/scrollbar_all_values_unspecified-manual.html", + {} + ] + ], + "wai-aria/scrollbar_only_valuenow_unspecified-manual.html": [ + [ + "/wai-aria/scrollbar_only_valuenow_unspecified-manual.html", + {} + ] + ], + "wai-aria/scrollbar_orientation_unspecified-manual.html": [ + [ + "/wai-aria/scrollbar_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/searchbox-manual.html": [ + [ + "/wai-aria/searchbox-manual.html", + {} + ] + ], + "wai-aria/searchbox_activedescendant-manual.html": [ + [ + "/wai-aria/searchbox_activedescendant-manual.html", + {} + ] + ], + "wai-aria/searchbox_activedescendant_value_changes-manual.html": [ + [ + "/wai-aria/searchbox_activedescendant_value_changes-manual.html", + {} + ] + ], + "wai-aria/searchbox_autocomplete_both-manual.html": [ + [ + "/wai-aria/searchbox_autocomplete_both-manual.html", + {} + ] + ], + "wai-aria/searchbox_autocomplete_inline-manual.html": [ + [ + "/wai-aria/searchbox_autocomplete_inline-manual.html", + {} + ] + ], + "wai-aria/searchbox_autocomplete_list-manual.html": [ + [ + "/wai-aria/searchbox_autocomplete_list-manual.html", + {} + ] + ], + "wai-aria/searchbox_autocomplete_none-manual.html": [ + [ + "/wai-aria/searchbox_autocomplete_none-manual.html", + {} + ] + ], + "wai-aria/searchbox_autocomplete_unspecified-manual.html": [ + [ + "/wai-aria/searchbox_autocomplete_unspecified-manual.html", + {} + ] + ], + "wai-aria/searchbox_multiline_false-manual.html": [ + [ + "/wai-aria/searchbox_multiline_false-manual.html", + {} + ] + ], + "wai-aria/searchbox_multiline_true-manual.html": [ + [ + "/wai-aria/searchbox_multiline_true-manual.html", + {} + ] + ], + "wai-aria/searchbox_multiline_unspecified-manual.html": [ + [ + "/wai-aria/searchbox_multiline_unspecified-manual.html", + {} + ] + ], + "wai-aria/searchbox_placeholder-manual.html": [ + [ + "/wai-aria/searchbox_placeholder-manual.html", + {} + ] + ], + "wai-aria/searchbox_readonly_false-manual.html": [ + [ + "/wai-aria/searchbox_readonly_false-manual.html", + {} + ] + ], + "wai-aria/searchbox_readonly_true-manual.html": [ + [ + "/wai-aria/searchbox_readonly_true-manual.html", + {} + ] + ], + "wai-aria/searchbox_readonly_unspecified-manual.html": [ + [ + "/wai-aria/searchbox_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/searchbox_required_false-manual.html": [ + [ + "/wai-aria/searchbox_required_false-manual.html", + {} + ] + ], + "wai-aria/searchbox_required_true-manual.html": [ + [ + "/wai-aria/searchbox_required_true-manual.html", + {} + ] + ], + "wai-aria/searchbox_required_unspecified-manual.html": [ + [ + "/wai-aria/searchbox_required_unspecified-manual.html", + {} + ] + ], + "wai-aria/separator_focusable_all_values_unspecified-manual.html": [ + [ + "/wai-aria/separator_focusable_all_values_unspecified-manual.html", + {} + ] + ], + "wai-aria/separator_focusable_only_valuenow_unspecified-manual.html": [ + [ + "/wai-aria/separator_focusable_only_valuenow_unspecified-manual.html", + {} + ] + ], + "wai-aria/separator_focusable_valuetext-manual.html": [ + [ + "/wai-aria/separator_focusable_valuetext-manual.html", + {} + ] + ], + "wai-aria/separator_orientation_unspecified-manual.html": [ + [ + "/wai-aria/separator_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/separator_unfocusable_all_values_unspecified-manual.html": [ + [ + "/wai-aria/separator_unfocusable_all_values_unspecified-manual.html", + {} + ] + ], + "wai-aria/separator_unfocusable_valuetext-manual.html": [ + [ + "/wai-aria/separator_unfocusable_valuetext-manual.html", + {} + ] + ], + "wai-aria/slider_all_values_unspecified-manual.html": [ + [ + "/wai-aria/slider_all_values_unspecified-manual.html", + {} + ] + ], + "wai-aria/slider_only_valuenow_unspecified-manual.html": [ + [ + "/wai-aria/slider_only_valuenow_unspecified-manual.html", + {} + ] + ], + "wai-aria/slider_orientation_unspecified-manual.html": [ + [ + "/wai-aria/slider_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/slider_readonly_false-manual.html": [ + [ + "/wai-aria/slider_readonly_false-manual.html", + {} + ] + ], + "wai-aria/slider_readonly_true-manual.html": [ + [ + "/wai-aria/slider_readonly_true-manual.html", + {} + ] + ], + "wai-aria/slider_readonly_unspecified-manual.html": [ + [ + "/wai-aria/slider_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/spinbutton_all_values_unspecified-manual.html": [ + [ + "/wai-aria/spinbutton_all_values_unspecified-manual.html", + {} + ] + ], + "wai-aria/spinbutton_only_aria-valuenow_unspecified-manual.html": [ + [ + "/wai-aria/spinbutton_only_aria-valuenow_unspecified-manual.html", + {} + ] + ], + "wai-aria/spinbutton_readonly_false-manual.html": [ + [ + "/wai-aria/spinbutton_readonly_false-manual.html", + {} + ] + ], + "wai-aria/spinbutton_readonly_true-manual.html": [ + [ + "/wai-aria/spinbutton_readonly_true-manual.html", + {} + ] + ], + "wai-aria/spinbutton_readonly_unspecified-manual.html": [ + [ + "/wai-aria/spinbutton_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/switch_checked_false-manual.html": [ + [ + "/wai-aria/switch_checked_false-manual.html", + {} + ] + ], + "wai-aria/switch_checked_mixed-manual.html": [ + [ + "/wai-aria/switch_checked_mixed-manual.html", + {} + ] + ], + "wai-aria/switch_checked_true-manual.html": [ + [ + "/wai-aria/switch_checked_true-manual.html", + {} + ] + ], + "wai-aria/switch_checked_undefined-manual.html": [ + [ + "/wai-aria/switch_checked_undefined-manual.html", + {} + ] + ], + "wai-aria/switch_checked_value_changes-manual.html": [ + [ + "/wai-aria/switch_checked_value_changes-manual.html", + {} + ] + ], + "wai-aria/switch_readonly_false-manual.html": [ + [ + "/wai-aria/switch_readonly_false-manual.html", + {} + ] + ], + "wai-aria/switch_readonly_true-manual.html": [ + [ + "/wai-aria/switch_readonly_true-manual.html", + {} + ] + ], + "wai-aria/switch_readonly_unspecified-manual.html": [ + [ + "/wai-aria/switch_readonly_unspecified-manual.html", + {} + ] + ], + "wai-aria/tab_posinset_and_setsize-manual.html": [ + [ + "/wai-aria/tab_posinset_and_setsize-manual.html", + {} + ] + ], + "wai-aria/table_colcount_-1-manual.html": [ + [ + "/wai-aria/table_colcount_-1-manual.html", + {} + ] + ], + "wai-aria/table_colcount_8-manual.html": [ + [ + "/wai-aria/table_colcount_8-manual.html", + {} + ] + ], + "wai-aria/table_rowcount_-1-manual.html": [ + [ + "/wai-aria/table_rowcount_-1-manual.html", + {} + ] + ], + "wai-aria/table_rowcount_3-manual.html": [ + [ + "/wai-aria/table_rowcount_3-manual.html", + {} + ] + ], + "wai-aria/tablist_orientation_horizontal-manual.html": [ + [ + "/wai-aria/tablist_orientation_horizontal-manual.html", + {} + ] + ], + "wai-aria/tablist_orientation_unspecified-manual.html": [ + [ + "/wai-aria/tablist_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/tablist_orientation_vertical-manual.html": [ + [ + "/wai-aria/tablist_orientation_vertical-manual.html", + {} + ] + ], + "wai-aria/term_role-manual.html": [ + [ + "/wai-aria/term_role-manual.html", + {} + ] + ], + "wai-aria/textbox_placeholder-manual.html": [ + [ + "/wai-aria/textbox_placeholder-manual.html", + {} + ] + ], + "wai-aria/toolbar_orientation_horizontal-manual.html": [ + [ + "/wai-aria/toolbar_orientation_horizontal-manual.html", + {} + ] + ], + "wai-aria/toolbar_orientation_unspecified-manual.html": [ + [ + "/wai-aria/toolbar_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/toolbar_orientation_vertical-manual.html": [ + [ + "/wai-aria/toolbar_orientation_vertical-manual.html", + {} + ] + ], + "wai-aria/tree_orientation_horizontal-manual.html": [ + [ + "/wai-aria/tree_orientation_horizontal-manual.html", + {} + ] + ], + "wai-aria/tree_orientation_unspecified-manual.html": [ + [ + "/wai-aria/tree_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/tree_orientation_vertical-manual.html": [ + [ + "/wai-aria/tree_orientation_vertical-manual.html", + {} + ] + ], + "wai-aria/treegrid_colcount_8-manual.html": [ + [ + "/wai-aria/treegrid_colcount_8-manual.html", + {} + ] + ], + "wai-aria/treegrid_orientation_horizontal-manual.html": [ + [ + "/wai-aria/treegrid_orientation_horizontal-manual.html", + {} + ] + ], + "wai-aria/treegrid_orientation_unspecified-manual.html": [ + [ + "/wai-aria/treegrid_orientation_unspecified-manual.html", + {} + ] + ], + "wai-aria/treegrid_orientation_vertical-manual.html": [ + [ + "/wai-aria/treegrid_orientation_vertical-manual.html", + {} + ] + ], + "wai-aria/treegrid_rowcount_3-manual.html": [ + [ + "/wai-aria/treegrid_rowcount_3-manual.html", + {} + ] + ], + "wai-aria/treeitem_selected_false-manual.html": [ + [ + "/wai-aria/treeitem_selected_false-manual.html", + {} + ] + ], + "wai-aria/treeitem_selected_true-manual.html": [ + [ + "/wai-aria/treeitem_selected_true-manual.html", + {} + ] + ], + "wai-aria/treeitem_selected_undefined-manual.html": [ + [ + "/wai-aria/treeitem_selected_undefined-manual.html", + {} + ] + ], + "wai-aria/treeitem_selected_value_changes-manual.html": [ + [ + "/wai-aria/treeitem_selected_value_changes-manual.html", + {} + ] + ], "webstorage/storage_local-manual.html": [ [ "/webstorage/storage_local-manual.html", @@ -6945,6 +8607,30 @@ {} ] ], + "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14.html": [ + [ + "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14.html", + [ + [ + "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14_ref.html", + "==" + ] + ], + {} + ] + ], + "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15.html": [ + [ + "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15.html", + [ + [ + "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15_ref.html", + "==" + ] + ], + {} + ] + ], "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_2.html": [ [ "/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_2.html", @@ -7149,6 +8835,18 @@ {} ] ], + "apng/animated-png-timeout.html": [ + [ + "/apng/animated-png-timeout.html", + [ + [ + "/apng/animated-png-timeout-ref.html", + "==" + ] + ], + {} + ] + ], "assumptions/canvas-background.html": [ [ "/assumptions/canvas-background.html", @@ -8325,6 +10023,126 @@ {} ] ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html": [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html", + [ + [ + "/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html", + "==" + ] + ], + {} + ] + ], "html/editing/the-hidden-attribute/hidden-1a.html": [ [ "/html/editing/the-hidden-attribute/hidden-1a.html", @@ -9141,6 +10959,18 @@ {} ] ], + "html/semantics/document-metadata/the-link-element/stylesheet-change-href.html": [ + [ + "/html/semantics/document-metadata/the-link-element/stylesheet-change-href.html", + [ + [ + "/html/semantics/document-metadata/the-link-element/stylesheet-change-href-ref.html", + "==" + ] + ], + {} + ] + ], "html/semantics/document-metadata/the-link-element/stylesheet-empty-href.html": [ [ "/html/semantics/document-metadata/the-link-element/stylesheet-empty-href.html", @@ -9273,6 +11103,18 @@ {} ] ], + "html/semantics/embedded-content/the-img-element/document-adopt-base-url.html": [ + [ + "/html/semantics/embedded-content/the-img-element/document-adopt-base-url.html", + [ + [ + "/html/semantics/embedded-content/the-img-element/document-base-url-ref.html", + "==" + ] + ], + {} + ] + ], "html/semantics/embedded-content/the-img-element/document-base-url.html": [ [ "/html/semantics/embedded-content/the-img-element/document-base-url.html", @@ -13671,6 +15513,11 @@ ] }, "support": { + "./.codecov.yml": [ + [ + {} + ] + ], "./.gitignore": [ [ {} @@ -13706,6 +15553,11 @@ {} ] ], + "./check_stability.ini": [ + [ + {} + ] + ], "./check_stability.py": [ [ {} @@ -13726,6 +15578,11 @@ {} ] ], + "./ci_unittest.sh": [ + [ + {} + ] + ], "./config.default.json": [ [ {} @@ -13771,6 +15628,16 @@ {} ] ], + "2dcontext/2x4.png": [ + [ + {} + ] + ], + "2dcontext/4x2.png": [ + [ + {} + ] + ], "2dcontext/best-practices/.gitkeep": [ [ {} @@ -14221,6 +16088,16 @@ {} ] ], + "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14_ref.html": [ + [ + {} + ] + ], + "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15_ref.html": [ + [ + {} + ] + ], "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_1_ref.html": [ [ {} @@ -15226,6 +17103,11 @@ {} ] ], + "WebCryptoAPI/util/worker-report-crypto-subtle-presence.js": [ + [ + {} + ] + ], "WebCryptoAPI/wrapKey_unwrapKey/wrapKey_unwrapKey.js": [ [ {} @@ -16136,7 +18018,7 @@ {} ] ], - "ambient-light/AmbientLightSensor.js": [ + "accelerometer/support-iframe.html": [ [ {} ] @@ -18576,6 +20458,11 @@ {} ] ], + "apng/animated-png-timeout-ref.html": [ + [ + {} + ] + ], "app-uri/OWNERS": [ [ {} @@ -18701,6 +20588,11 @@ {} ] ], + "bluetooth/OWNERS": [ + [ + {} + ] + ], "clear-site-data/support/echo-clear-site-data.py": [ [ {} @@ -18726,6 +20618,11 @@ {} ] ], + "common/PrefixedPostMessage.js": [ + [ + {} + ] + ], "common/blank.html": [ [ {} @@ -18801,6 +20698,16 @@ {} ] ], + "common/object-association.js": [ + [ + {} + ] + ], + "common/performance-timeline-utils.js": [ + [ + {} + ] + ], "common/redirect-opt-in.py": [ [ {} @@ -41806,12 +43713,7 @@ {} ] ], - "content-security-policy/child-src/child-src-worker-allowed.sub.html.sub.headers": [ - [ - {} - ] - ], - "content-security-policy/child-src/child-src-worker-blocked.sub.html.sub.headers": [ + "content-security-policy/child-src/child-src-redirect-blocked.sub.html.sub.headers": [ [ {} ] @@ -41836,47 +43738,52 @@ {} ] ], - "content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html": [ + "content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html": [ [ {} ] ], - "content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html.headers": [ + "content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html.sub.headers": [ [ {} ] ], - "content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html": [ + "content-security-policy/frame-ancestors/support/frame-ancestors-test.sub.js": [ [ {} ] ], - "content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html.headers": [ + "content-security-policy/frame-ancestors/support/frame-ancestors.sub.html": [ [ {} ] ], - "content-security-policy/frame-ancestors/reporting-frame-allows-none-meta.html": [ + "content-security-policy/frame-ancestors/support/frame-ancestors.sub.html.sub.headers": [ [ {} ] ], - "content-security-policy/frame-ancestors/reporting-frame-allows-none.html": [ + "content-security-policy/frame-ancestors/support/frame-in-frame.sub.html": [ [ {} ] ], - "content-security-policy/frame-ancestors/reporting-frame-allows-none.html.headers": [ + "content-security-policy/frame-ancestors/support/frame-in-frame.sub.html.sub.headers": [ [ {} ] ], - "content-security-policy/frame-ancestors/reporting-frame-allows-self.html": [ + "content-security-policy/frame-src/frame-src-redirect.html.headers": [ [ {} ] ], - "content-security-policy/frame-ancestors/reporting-frame-allows-self.html.headers": [ + "content-security-policy/frame-src/support/frame.html": [ + [ + {} + ] + ], + "content-security-policy/frame-src/support/testharness-helper.sub.js": [ [ {} ] @@ -42076,6 +43983,21 @@ {} ] ], + "content-security-policy/script-src/crossoriginScript.js": [ + [ + {} + ] + ], + "content-security-policy/script-src/crossoriginScript.js.headers": [ + [ + {} + ] + ], + "content-security-policy/script-src/externalScript.js": [ + [ + {} + ] + ], "content-security-policy/script-src/inlineSuccessTest.js": [ [ {} @@ -42131,6 +44053,11 @@ {} ] ], + "content-security-policy/script-src/script-src-sri_hash.sub.html.sub.headers": [ + [ + {} + ] + ], "content-security-policy/script-src/script-src-strict_dynamic_and_unsafe_eval_eval.html.headers": [ [ {} @@ -42216,6 +44143,11 @@ {} ] ], + "content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html.headers": [ + [ + {} + ] + ], "content-security-policy/securitypolicyviolation/support/inside-worker.sub.js": [ [ {} @@ -42226,6 +44158,16 @@ {} ] ], + "content-security-policy/securitypolicyviolation/support/testharness-helper.sub.js": [ + [ + {} + ] + ], + "content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html.headers": [ + [ + {} + ] + ], "content-security-policy/style-src/resources/style-src-import.sub.css": [ [ {} @@ -42316,6 +44258,21 @@ {} ] ], + "content-security-policy/support/post-message.js": [ + [ + {} + ] + ], + "content-security-policy/support/postmessage-fail.html": [ + [ + {} + ] + ], + "content-security-policy/support/postmessage-pass.html": [ + [ + {} + ] + ], "content-security-policy/support/report.py": [ [ {} @@ -42456,6 +44413,11 @@ {} ] ], + "css-paint-api/OWNERS": [ + [ + {} + ] + ], "css-timing-1/OWNERS": [ [ {} @@ -42761,11 +44723,456 @@ {} ] ], + "cssom-view/support/1x1-green.png": [ + [ + {} + ] + ], + "cssom-view/support/1x1-lime.png": [ + [ + {} + ] + ], + "cssom-view/support/1x1-maroon.png": [ + [ + {} + ] + ], + "cssom-view/support/1x1-navy.png": [ + [ + {} + ] + ], + "cssom-view/support/1x1-red.png": [ + [ + {} + ] + ], + "cssom-view/support/1x1-white.png": [ + [ + {} + ] + ], + "cssom-view/support/60x60-gg-rr.png": [ + [ + {} + ] + ], + "cssom-view/support/60x60-green.png": [ + [ + {} + ] + ], + "cssom-view/support/60x60-red.png": [ + [ + {} + ] + ], + "cssom-view/support/README": [ + [ + {} + ] + ], + "cssom-view/support/a-green.css": [ + [ + {} + ] + ], + "cssom-view/support/b-green.css": [ + [ + {} + ] + ], + "cssom-view/support/c-red.css": [ + [ + {} + ] + ], + "cssom-view/support/cat.png": [ + [ + {} + ] + ], + "cssom-view/support/import-green.css": [ + [ + {} + ] + ], + "cssom-view/support/import-red.css": [ + [ + {} + ] + ], + "cssom-view/support/pattern-grg-rgr-grg.png": [ + [ + {} + ] + ], + "cssom-view/support/pattern-grg-rrg-rgg.png": [ + [ + {} + ] + ], + "cssom-view/support/pattern-rgr-grg-rgr.png": [ + [ + {} + ] + ], + "cssom-view/support/pattern-tr.png": [ + [ + {} + ] + ], + "cssom-view/support/ruler-h-50%.png": [ + [ + {} + ] + ], + "cssom-view/support/ruler-h-50px.png": [ + [ + {} + ] + ], + "cssom-view/support/ruler-v-100px.png": [ + [ + {} + ] + ], + "cssom-view/support/ruler-v-50px.png": [ + [ + {} + ] + ], + "cssom-view/support/square-purple.png": [ + [ + {} + ] + ], + "cssom-view/support/square-teal.png": [ + [ + {} + ] + ], + "cssom-view/support/square-white.png": [ + [ + {} + ] + ], + "cssom-view/support/support/README": [ + [ + {} + ] + ], + "cssom-view/support/support/swatch-green.png": [ + [ + {} + ] + ], + "cssom-view/support/support/swatch-red.png": [ + [ + {} + ] + ], + "cssom-view/support/swatch-blue.png": [ + [ + {} + ] + ], + "cssom-view/support/swatch-green.png": [ + [ + {} + ] + ], + "cssom-view/support/swatch-lime.png": [ + [ + {} + ] + ], + "cssom-view/support/swatch-orange.png": [ + [ + {} + ] + ], + "cssom-view/support/swatch-red.png": [ + [ + {} + ] + ], + "cssom-view/support/swatch-teal.png": [ + [ + {} + ] + ], + "cssom-view/support/swatch-white.png": [ + [ + {} + ] + ], + "cssom-view/support/swatch-yellow.png": [ + [ + {} + ] + ], + "cssom-view/support/test-bl.png": [ + [ + {} + ] + ], + "cssom-view/support/test-br.png": [ + [ + {} + ] + ], + "cssom-view/support/test-inner-half-size.png": [ + [ + {} + ] + ], + "cssom-view/support/test-outer.png": [ + [ + {} + ] + ], + "cssom-view/support/test-tl.png": [ + [ + {} + ] + ], + "cssom-view/support/test-tr.png": [ + [ + {} + ] + ], + "cssom/OWNERS": [ + [ + {} + ] + ], "cssom/stylesheet-same-origin.css": [ [ {} ] ], + "cssom/support/1x1-green.png": [ + [ + {} + ] + ], + "cssom/support/1x1-lime.png": [ + [ + {} + ] + ], + "cssom/support/1x1-maroon.png": [ + [ + {} + ] + ], + "cssom/support/1x1-navy.png": [ + [ + {} + ] + ], + "cssom/support/1x1-red.png": [ + [ + {} + ] + ], + "cssom/support/1x1-white.png": [ + [ + {} + ] + ], + "cssom/support/60x60-gg-rr.png": [ + [ + {} + ] + ], + "cssom/support/60x60-green.png": [ + [ + {} + ] + ], + "cssom/support/60x60-red.png": [ + [ + {} + ] + ], + "cssom/support/README": [ + [ + {} + ] + ], + "cssom/support/a-green.css": [ + [ + {} + ] + ], + "cssom/support/b-green.css": [ + [ + {} + ] + ], + "cssom/support/c-red.css": [ + [ + {} + ] + ], + "cssom/support/cat.png": [ + [ + {} + ] + ], + "cssom/support/import-green.css": [ + [ + {} + ] + ], + "cssom/support/import-red.css": [ + [ + {} + ] + ], + "cssom/support/pattern-grg-rgr-grg.png": [ + [ + {} + ] + ], + "cssom/support/pattern-grg-rrg-rgg.png": [ + [ + {} + ] + ], + "cssom/support/pattern-rgr-grg-rgr.png": [ + [ + {} + ] + ], + "cssom/support/pattern-tr.png": [ + [ + {} + ] + ], + "cssom/support/ruler-h-50%.png": [ + [ + {} + ] + ], + "cssom/support/ruler-h-50px.png": [ + [ + {} + ] + ], + "cssom/support/ruler-v-100px.png": [ + [ + {} + ] + ], + "cssom/support/ruler-v-50px.png": [ + [ + {} + ] + ], + "cssom/support/square-purple.png": [ + [ + {} + ] + ], + "cssom/support/square-teal.png": [ + [ + {} + ] + ], + "cssom/support/square-white.png": [ + [ + {} + ] + ], + "cssom/support/support/README": [ + [ + {} + ] + ], + "cssom/support/support/swatch-green.png": [ + [ + {} + ] + ], + "cssom/support/support/swatch-red.png": [ + [ + {} + ] + ], + "cssom/support/swatch-blue.png": [ + [ + {} + ] + ], + "cssom/support/swatch-green.png": [ + [ + {} + ] + ], + "cssom/support/swatch-lime.png": [ + [ + {} + ] + ], + "cssom/support/swatch-orange.png": [ + [ + {} + ] + ], + "cssom/support/swatch-red.png": [ + [ + {} + ] + ], + "cssom/support/swatch-teal.png": [ + [ + {} + ] + ], + "cssom/support/swatch-white.png": [ + [ + {} + ] + ], + "cssom/support/swatch-yellow.png": [ + [ + {} + ] + ], + "cssom/support/test-bl.png": [ + [ + {} + ] + ], + "cssom/support/test-br.png": [ + [ + {} + ] + ], + "cssom/support/test-inner-half-size.png": [ + [ + {} + ] + ], + "cssom/support/test-outer.png": [ + [ + {} + ] + ], + "cssom/support/test-tl.png": [ + [ + {} + ] + ], + "cssom/support/test-tr.png": [ + [ + {} + ] + ], "custom-elements/OWNERS": [ [ {} @@ -42916,7 +45323,7 @@ {} ] ], - "docs/_writing-tests/idlharness.html": [ + "docs/_writing-tests/idlharness.md": [ [ {} ] @@ -42956,7 +45363,7 @@ {} ] ], - "docs/_writing-tests/testharness-api.html": [ + "docs/_writing-tests/testharness-api.md": [ [ {} ] @@ -43601,6 +46008,11 @@ {} ] ], + "editing/data/README.md": [ + [ + {} + ] + ], "editing/data/backcolor.js": [ [ {} @@ -44121,16 +46533,6 @@ {} ] ], - "encrypted-media/content/video_512x288_h264-360k_multikey_key1_dashinit.mp4": [ - [ - {} - ] - ], - "encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4": [ - [ - {} - ] - ], "encrypted-media/polyfill/cast-polyfill.js": [ [ {} @@ -44771,6 +47173,11 @@ {} ] ], + "fetch/api/resources/script-with-header.py": [ + [ + {} + ] + ], "fetch/api/resources/status.py": [ [ {} @@ -44876,11 +47283,6 @@ {} ] ], - "fonts/CanvasTest.sfd": [ - [ - {} - ] - ], "fonts/CanvasTest.ttf": [ [ {} @@ -45246,6 +47648,11 @@ {} ] ], + "generic-sensor/generic-sensor-tests.js": [ + [ + {} + ] + ], "geolocation-API/OWNERS": [ [ {} @@ -45261,6 +47668,11 @@ {} ] ], + "gyroscope/support-iframe.html": [ + [ + {} + ] + ], "hr-time/OWNERS": [ [ {} @@ -46436,6 +48848,11 @@ {} ] ], + "html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_iframe.html": [ + [ + {} + ] + ], "html/browsers/sandboxing/.gitkeep": [ [ {} @@ -46526,6 +48943,16 @@ {} ] ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/close-self.html": [ + [ + {} + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/message-opener.html": [ + [ + {} + ] + ], "html/browsers/the-window-object/browser-interface-elements/.gitkeep": [ [ {} @@ -46681,57 +49108,82 @@ {} ] ], - "html/browsers/windows/browsing-context-names/001-1.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_parent-001-iframe-1.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/002-1.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_parent-002-iframe.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/existing.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_parent-002-window.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-1.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_parent-003-iframe.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-2.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_parent-003-window.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-3.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_parent-004-iframe-1.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-1.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_parent-004-iframe-2.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-2.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_self-001-iframe.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/resources/parent-top-nested.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_self-002-iframe.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/resources/parent-top-replace.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_top-002-window.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/resources/parent-top.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-1.html": [ + [ + {} + ] + ], + "html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-2.html": [ + [ + {} + ] + ], + "html/browsers/windows/browsing-context-names/resources/choose-default-002-iframe.html": [ + [ + {} + ] + ], + "html/browsers/windows/browsing-context-names/resources/choose-existing-001-iframe.html": [ + [ + {} + ] + ], + "html/browsers/windows/browsing-context-names/resources/open-in-_parent.html": [ + [ + {} + ] + ], + "html/browsers/windows/browsing-context-names/resources/open-in-_top.html": [ [ {} ] @@ -46741,22 +49193,17 @@ {} ] ], - "html/browsers/windows/browsing-context-names/resources/post-to-top-or-close.html": [ - [ - {} - ] - ], "html/browsers/windows/browsing-context-names/resources/post-to-top.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/self1.html": [ + "html/browsers/windows/browsing-context-names/resources/report-has-opener.html": [ [ {} ] ], - "html/browsers/windows/browsing-context-names/self2.html": [ + "html/browsers/windows/browsing-context-names/resources/report-is-top.html": [ [ {} ] @@ -47561,21 +50008,11 @@ {} ] ], - "html/dom/resources/interfaces.idl": [ - [ - {} - ] - ], "html/dom/resources/self-origin-subframe.html": [ [ {} ] ], - "html/dom/resources/untested-interfaces.idl": [ - [ - {} - ] - ], "html/editing/.gitkeep": [ [ {} @@ -52006,6 +54443,11 @@ {} ] ], + "html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html": [ + [ + {} + ] + ], "html/editing/focus/.gitkeep": [ [ {} @@ -52321,6 +54763,106 @@ {} ] ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.js": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/blank.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-sharedworker.js": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-worker.js": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-iframe.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-worker.js": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe-domain.sub.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-popup.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker-with-channel.js": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker.js": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-1.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-2.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-3.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-4-incrementer.html": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-failure.js": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/sharedworker-failure.js": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-incrementer.js": [ + [ + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-sab.js": [ + [ + {} + ] + ], "html/infrastructure/terminology/.gitkeep": [ [ {} @@ -52936,6 +55478,16 @@ {} ] ], + "html/rendering/non-replaced-elements/the-page/support/body-marginwidth-marginheight.html": [ + [ + {} + ] + ], + "html/rendering/non-replaced-elements/the-page/support/body-topmargin-leftmargin.html": [ + [ + {} + ] + ], "html/rendering/non-replaced-elements/the-page/test-body.xhtml": [ [ {} @@ -53161,11 +55713,21 @@ {} ] ], + "html/semantics/document-metadata/the-link-element/resources/bad.css": [ + [ + {} + ] + ], "html/semantics/document-metadata/the-link-element/resources/empty-href.css": [ [ {} ] ], + "html/semantics/document-metadata/the-link-element/resources/good.css": [ + [ + {} + ] + ], "html/semantics/document-metadata/the-link-element/resources/stylesheet.css": [ [ {} @@ -53176,6 +55738,11 @@ {} ] ], + "html/semantics/document-metadata/the-link-element/stylesheet-change-href-ref.html": [ + [ + {} + ] + ], "html/semantics/document-metadata/the-link-element/stylesheet-empty-href-ref.html": [ [ {} @@ -54276,6 +56843,11 @@ {} ] ], + "html/semantics/interactive-elements/the-dialog-element/centering-iframe.sub.html": [ + [ + {} + ] + ], "html/semantics/interactive-elements/the-dialog-element/contains.json": [ [ {} @@ -54616,6 +57188,11 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/module/instantiation-error-1.js": [ + [ + {} + ] + ], "html/semantics/scripting-1/the-script-element/resources/cocoa-module.js": [ [ {} @@ -55611,6 +58188,16 @@ {} ] ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-failure.js": [ + [ + {} + ] + ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-success.js": [ + [ + {} + ] + ], "html/webappapis/scripting/processing-model-2/support/syntax-error-in-setInterval.js": [ [ {} @@ -55666,11 +58253,6 @@ {} ] ], - "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js": [ - [ - {} - ] - ], "html/webappapis/system-state-and-capabilities/the-navigator-object/contains.json": [ [ {} @@ -55746,6 +58328,11 @@ {} ] ], + "images/apng.png": [ + [ + {} + ] + ], "images/background.png": [ [ {} @@ -55941,6 +58528,36 @@ {} ] ], + "interfaces/cssom.idl": [ + [ + {} + ] + ], + "interfaces/dom.idl": [ + [ + {} + ] + ], + "interfaces/html.idl": [ + [ + {} + ] + ], + "interfaces/touchevents.idl": [ + [ + {} + ] + ], + "interfaces/uievents.idl": [ + [ + {} + ] + ], + "interfaces/webrtc-pc.idl": [ + [ + {} + ] + ], "js/builtins/Math.maxmin.js": [ [ {} @@ -55981,6 +58598,11 @@ {} ] ], + "magnetometer/support-iframe.html": [ + [ + {} + ] + ], "mathml/README.md": [ [ {} @@ -56506,11 +59128,6 @@ {} ] ], - "media/CanvasTest.ttf": [ - [ - {} - ] - ], "media/OWNERS": [ [ {} @@ -58606,6 +61223,11 @@ {} ] ], + "orientation-sensor/OWNERS": [ + [ + {} + ] + ], "page-visibility/OWNERS": [ [ {} @@ -58621,6 +61243,11 @@ {} ] ], + "page-visibility/resources/prerender_target.html": [ + [ + {} + ] + ], "page-visibility/unload-1.html": [ [ {} @@ -58641,6 +61268,11 @@ {} ] ], + "payment-request/payment-request-response-id.html": [ + [ + {} + ] + ], "performance-timeline/OWNERS": [ [ {} @@ -58791,6 +61423,31 @@ {} ] ], + "presentation-api/receiving-ua/support/PresentationConnectionList_onconnectionavailable_receiving-ua.html": [ + [ + {} + ] + ], + "presentation-api/receiving-ua/support/PresentationConnection_onclose_receiving-ua.html": [ + [ + {} + ] + ], + "presentation-api/receiving-ua/support/PresentationConnection_onmessage_receiving-ua.html": [ + [ + {} + ] + ], + "presentation-api/receiving-ua/support/PresentationConnection_send_receiving-ua.html": [ + [ + {} + ] + ], + "presentation-api/receiving-ua/support/PresentationConnection_terminate_receiving-ua.html": [ + [ + {} + ] + ], "presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html": [ [ {} @@ -58806,7 +61463,12 @@ {} ] ], - "presentation-api/receiving-ua/support/idlharness_receiving-ua.https.html": [ + "presentation-api/receiving-ua/support/idlharness_receiving-ua.html": [ + [ + {} + ] + ], + "presentation-api/receiving-ua/support/iframe.html": [ [ {} ] @@ -61496,6 +64158,11 @@ {} ] ], + "resource-timing/resources/TAOResponse.py": [ + [ + {} + ] + ], "resource-timing/resources/fake_responses.html": [ [ {} @@ -61511,6 +64178,51 @@ {} ] ], + "resource-timing/resources/iframe_TAO_match_origin.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe_TAO_match_wildcard.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe_TAO_multi.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe_TAO_null.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe_TAO_origin.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe_TAO_origin_uppercase.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe_TAO_space.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe_TAO_wildcard.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe_TAO_zero.html": [ + [ + {} + ] + ], "resource-timing/resources/inject_resource_test.html": [ [ {} @@ -61656,11 +64368,6 @@ {} ] ], - "selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.js": [ - [ - {} - ] - ], "selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html": [ [ {} @@ -61681,6 +64388,31 @@ {} ] ], + "server-timing/resources/blue.png": [ + [ + {} + ] + ], + "server-timing/resources/blue.png.sub.headers": [ + [ + {} + ] + ], + "server-timing/resources/green.png": [ + [ + {} + ] + ], + "server-timing/resources/green.png.sub.headers": [ + [ + {} + ] + ], + "server-timing/test_server_timing.html.sub.headers": [ + [ + {} + ] + ], "service-workers/OWNERS": [ [ {} @@ -61741,6 +64473,11 @@ {} ] ], + "service-workers/cache-storage/script-tests/cache-keys.js": [ + [ + {} + ] + ], "service-workers/cache-storage/script-tests/cache-match.js": [ [ {} @@ -61776,6 +64513,11 @@ {} ] ], + "service-workers/service-worker/ServiceWorkerGlobalScope/resources/error-worker.js": [ + [ + {} + ] + ], "service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-constructor-worker.js": [ [ {} @@ -61946,6 +64688,16 @@ {} ] ], + "service-workers/service-worker/navigation-preload/resources/resource-timing-scope.py": [ + [ + {} + ] + ], + "service-workers/service-worker/navigation-preload/resources/resource-timing-worker.js": [ + [ + {} + ] + ], "service-workers/service-worker/navigation-preload/resources/wait-for-activate-worker.js": [ [ {} @@ -61991,6 +64743,11 @@ {} ] ], + "service-workers/service-worker/resources/client-id-worker.js": [ + [ + {} + ] + ], "service-workers/service-worker/resources/client-navigate-frame.html": [ [ {} @@ -62006,6 +64763,21 @@ {} ] ], + "service-workers/service-worker/resources/clients-get-client-types-frame.html": [ + [ + {} + ] + ], + "service-workers/service-worker/resources/clients-get-client-types-shared-worker.js": [ + [ + {} + ] + ], + "service-workers/service-worker/resources/clients-get-cross-origin-frame.html": [ + [ + {} + ] + ], "service-workers/service-worker/resources/clients-get-frame.html": [ [ {} @@ -62031,6 +64803,11 @@ {} ] ], + "service-workers/service-worker/resources/clients-matchall-on-evaluation-worker.js": [ + [ + {} + ] + ], "service-workers/service-worker/resources/clients-matchall-worker.js": [ [ {} @@ -62166,6 +64943,16 @@ {} ] ], + "service-workers/service-worker/resources/fetch-event-respond-with-argument-iframe.html": [ + [ + {} + ] + ], + "service-workers/service-worker/resources/fetch-event-respond-with-argument-worker.js": [ + [ + {} + ] + ], "service-workers/service-worker/resources/fetch-event-respond-with-stops-propagation-worker.js": [ [ {} @@ -62321,6 +65108,11 @@ {} ] ], + "service-workers/service-worker/resources/import-mime-type-worker.py": [ + [ + {} + ] + ], "service-workers/service-worker/resources/indexeddb-worker.js": [ [ {} @@ -62801,6 +65593,11 @@ {} ] ], + "staticrange/OWNERS": [ + [ + {} + ] + ], "storage/OWNERS": [ [ {} @@ -62816,6 +65613,16 @@ {} ] ], + "storage/resources/storagemanager-persist-worker.js": [ + [ + {} + ] + ], + "storage/resources/storagemanager-persisted-worker.js": [ + [ + {} + ] + ], "storage/storage-estimate-indexeddb.js": [ [ {} @@ -63021,6 +65828,11 @@ {} ] ], + "streams/writable-streams/error.js": [ + [ + {} + ] + ], "streams/writable-streams/floating-point-total-queue-size.js": [ [ {} @@ -63031,6 +65843,11 @@ {} ] ], + "streams/writable-streams/properties.js": [ + [ + {} + ] + ], "streams/writable-streams/reentrant-strategy.js": [ [ {} @@ -63856,6 +66673,11 @@ {} ] ], + "web-nfc/OWNERS": [ + [ + {} + ] + ], "webaudio/.gitignore": [ [ {} @@ -64086,6 +66908,11 @@ {} ] ], + "webdriver/support/__init__.py": [ + [ + {} + ] + ], "webdriver/support/asserts.py": [ [ {} @@ -64106,6 +66933,11 @@ {} ] ], + "webdriver/support/merge_dictionaries.py": [ + [ + {} + ] + ], "webgl/OWNERS": [ [ {} @@ -81174,6 +84006,12 @@ {} ] ], + "IndexedDB/idbobjectstore-index-finished.html": [ + [ + "/IndexedDB/idbobjectstore-index-finished.html", + {} + ] + ], "IndexedDB/idbobjectstore-query-exception-order.html": [ [ "/IndexedDB/idbobjectstore-query-exception-order.html", @@ -81698,6 +84536,12 @@ {} ] ], + "IndexedDB/idbtransaction-objectStore-finished.html": [ + [ + "/IndexedDB/idbtransaction-objectStore-finished.html", + {} + ] + ], "IndexedDB/idbtransaction-oncomplete.htm": [ [ "/IndexedDB/idbtransaction-oncomplete.htm", @@ -82030,33 +84874,97 @@ } ] ], - "WebCryptoAPI/derive_bits_keys/test_ecdh_bits.html": [ + "WebCryptoAPI/derive_bits_keys/test_ecdh_bits.https.html": [ [ - "/WebCryptoAPI/derive_bits_keys/test_ecdh_bits.html", + "/WebCryptoAPI/derive_bits_keys/test_ecdh_bits.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/derive_bits_keys/test_ecdh_keys.html": [ + "WebCryptoAPI/derive_bits_keys/test_ecdh_keys.https.html": [ [ - "/WebCryptoAPI/derive_bits_keys/test_ecdh_keys.html", + "/WebCryptoAPI/derive_bits_keys/test_ecdh_keys.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/derive_bits_keys/test_hkdf.html": [ + "WebCryptoAPI/derive_bits_keys/test_hkdf.https.html": [ [ - "/WebCryptoAPI/derive_bits_keys/test_hkdf.html", + "/WebCryptoAPI/derive_bits_keys/test_hkdf.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/derive_bits_keys/test_pbkdf2.html": [ + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_empty.https.html": [ [ - "/WebCryptoAPI/derive_bits_keys/test_pbkdf2.html", + "/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_empty.https.html", + { + "timeout": "long" + } + ] + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_long.https.html": [ + [ + "/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_long.https.html", + { + "timeout": "long" + } + ] + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_short.https.html": [ + [ + "/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_short.https.html", + { + "timeout": "long" + } + ] + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_empty.https.html": [ + [ + "/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_empty.https.html", + { + "timeout": "long" + } + ] + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_long.https.html": [ + [ + "/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_long.https.html", + { + "timeout": "long" + } + ] + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_short.https.html": [ + [ + "/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_short.https.html", + { + "timeout": "long" + } + ] + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_empty.https.html": [ + [ + "/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_empty.https.html", + { + "timeout": "long" + } + ] + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_long.https.html": [ + [ + "/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_long.https.html", + { + "timeout": "long" + } + ] + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_short.https.html": [ + [ + "/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_short.https.html", { "timeout": "long" } @@ -82068,9 +84976,9 @@ {} ] ], - "WebCryptoAPI/digest/test_digest.html": [ + "WebCryptoAPI/digest/test_digest.https.html": [ [ - "/WebCryptoAPI/digest/test_digest.html", + "/WebCryptoAPI/digest/test_digest.https.html", { "timeout": "long" } @@ -82100,33 +85008,33 @@ {} ] ], - "WebCryptoAPI/encrypt_decrypt/test_aes_cbc.html": [ + "WebCryptoAPI/encrypt_decrypt/test_aes_cbc.https.html": [ [ - "/WebCryptoAPI/encrypt_decrypt/test_aes_cbc.html", + "/WebCryptoAPI/encrypt_decrypt/test_aes_cbc.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/encrypt_decrypt/test_aes_ctr.html": [ + "WebCryptoAPI/encrypt_decrypt/test_aes_ctr.https.html": [ [ - "/WebCryptoAPI/encrypt_decrypt/test_aes_ctr.html", + "/WebCryptoAPI/encrypt_decrypt/test_aes_ctr.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/encrypt_decrypt/test_aes_gcm.html": [ + "WebCryptoAPI/encrypt_decrypt/test_aes_gcm.https.html": [ [ - "/WebCryptoAPI/encrypt_decrypt/test_aes_gcm.html", + "/WebCryptoAPI/encrypt_decrypt/test_aes_gcm.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.html": [ + "WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.https.html": [ [ - "/WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.html", + "/WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.https.html", { "timeout": "long" } @@ -82304,193 +85212,185 @@ } ] ], - "WebCryptoAPI/generateKey/test_aes-cbc.html": [ + "WebCryptoAPI/generateKey/test_aes-cbc.https.html": [ [ - "/WebCryptoAPI/generateKey/test_aes-cbc.html", + "/WebCryptoAPI/generateKey/test_aes-cbc.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_aes-ctr.html": [ + "WebCryptoAPI/generateKey/test_aes-ctr.https.html": [ [ - "/WebCryptoAPI/generateKey/test_aes-ctr.html", + "/WebCryptoAPI/generateKey/test_aes-ctr.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures.html": [ + "WebCryptoAPI/generateKey/test_failures.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures.html", + "/WebCryptoAPI/generateKey/test_failures.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_AES-CBC.html": [ + "WebCryptoAPI/generateKey/test_failures_AES-CBC.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_AES-CBC.html", + "/WebCryptoAPI/generateKey/test_failures_AES-CBC.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_AES-CTR.html": [ + "WebCryptoAPI/generateKey/test_failures_AES-CTR.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_AES-CTR.html", + "/WebCryptoAPI/generateKey/test_failures_AES-CTR.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_AES-GCM.html": [ + "WebCryptoAPI/generateKey/test_failures_AES-GCM.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_AES-GCM.html", + "/WebCryptoAPI/generateKey/test_failures_AES-GCM.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_AES-KW.html": [ + "WebCryptoAPI/generateKey/test_failures_AES-KW.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_AES-KW.html", + "/WebCryptoAPI/generateKey/test_failures_AES-KW.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_ECDH.html": [ + "WebCryptoAPI/generateKey/test_failures_ECDH.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_ECDH.html", + "/WebCryptoAPI/generateKey/test_failures_ECDH.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_ECDSA.html": [ + "WebCryptoAPI/generateKey/test_failures_ECDSA.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_ECDSA.html", + "/WebCryptoAPI/generateKey/test_failures_ECDSA.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_HMAC.html": [ + "WebCryptoAPI/generateKey/test_failures_HMAC.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_HMAC.html", + "/WebCryptoAPI/generateKey/test_failures_HMAC.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_RSA-OAEP.html": [ + "WebCryptoAPI/generateKey/test_failures_RSA-OAEP.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_RSA-OAEP.html", + "/WebCryptoAPI/generateKey/test_failures_RSA-OAEP.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_RSA-PSS.html": [ + "WebCryptoAPI/generateKey/test_failures_RSA-PSS.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_RSA-PSS.html", + "/WebCryptoAPI/generateKey/test_failures_RSA-PSS.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.html": [ + "WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.https.html": [ [ - "/WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.html", + "/WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes.html": [ + "WebCryptoAPI/generateKey/test_successes_AES-CBC.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes.html", + "/WebCryptoAPI/generateKey/test_successes_AES-CBC.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes_AES-CBC.html": [ + "WebCryptoAPI/generateKey/test_successes_AES-CTR.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes_AES-CBC.html", + "/WebCryptoAPI/generateKey/test_successes_AES-CTR.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes_AES-CTR.html": [ + "WebCryptoAPI/generateKey/test_successes_AES-GCM.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes_AES-CTR.html", + "/WebCryptoAPI/generateKey/test_successes_AES-GCM.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes_AES-GCM.html": [ + "WebCryptoAPI/generateKey/test_successes_AES-KW.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes_AES-GCM.html", + "/WebCryptoAPI/generateKey/test_successes_AES-KW.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes_AES-KW.html": [ + "WebCryptoAPI/generateKey/test_successes_ECDH.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes_AES-KW.html", + "/WebCryptoAPI/generateKey/test_successes_ECDH.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes_ECDH.html": [ + "WebCryptoAPI/generateKey/test_successes_ECDSA.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes_ECDH.html", + "/WebCryptoAPI/generateKey/test_successes_ECDSA.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes_ECDSA.html": [ + "WebCryptoAPI/generateKey/test_successes_HMAC.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes_ECDSA.html", + "/WebCryptoAPI/generateKey/test_successes_HMAC.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes_HMAC.html": [ + "WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes_HMAC.html", + "/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes_RSA-OAEP.html": [ + "WebCryptoAPI/generateKey/test_successes_RSA-PSS.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.html", + "/WebCryptoAPI/generateKey/test_successes_RSA-PSS.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/generateKey/test_successes_RSA-PSS.html": [ + "WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.https.html": [ [ - "/WebCryptoAPI/generateKey/test_successes_RSA-PSS.html", - { - "timeout": "long" - } - ] - ], - "WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.html": [ - [ - "/WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.html", + "/WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.https.html", { "timeout": "long" } @@ -82512,6 +85412,12 @@ {} ] ], + "WebCryptoAPI/idlharness.https.html": [ + [ + "/WebCryptoAPI/idlharness.https.html", + {} + ] + ], "WebCryptoAPI/idlharness.worker.js": [ [ "/WebCryptoAPI/idlharness.worker.html", @@ -82536,21 +85442,33 @@ {} ] ], - "WebCryptoAPI/import_export/test_ec_importKey.html": [ + "WebCryptoAPI/import_export/test_ec_importKey.https.html": [ [ - "/WebCryptoAPI/import_export/test_ec_importKey.html", + "/WebCryptoAPI/import_export/test_ec_importKey.https.html", {} ] ], - "WebCryptoAPI/import_export/test_rsa_importKey.html": [ + "WebCryptoAPI/import_export/test_rsa_importKey.https.html": [ [ - "/WebCryptoAPI/import_export/test_rsa_importKey.html", + "/WebCryptoAPI/import_export/test_rsa_importKey.https.html", {} ] ], - "WebCryptoAPI/import_export/test_symmetric_importKey.html": [ + "WebCryptoAPI/import_export/test_symmetric_importKey.https.html": [ [ - "/WebCryptoAPI/import_export/test_symmetric_importKey.html", + "/WebCryptoAPI/import_export/test_symmetric_importKey.https.html", + {} + ] + ], + "WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html": [ + [ + "/WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html", + {} + ] + ], + "WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html": [ + [ + "/WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html", {} ] ], @@ -82578,41 +85496,41 @@ {} ] ], - "WebCryptoAPI/sign_verify/test_ecdsa.html": [ + "WebCryptoAPI/sign_verify/test_ecdsa.https.html": [ [ - "/WebCryptoAPI/sign_verify/test_ecdsa.html", + "/WebCryptoAPI/sign_verify/test_ecdsa.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/sign_verify/test_hmac.html": [ + "WebCryptoAPI/sign_verify/test_hmac.https.html": [ [ - "/WebCryptoAPI/sign_verify/test_hmac.html", + "/WebCryptoAPI/sign_verify/test_hmac.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/sign_verify/test_rsa_pkcs.html": [ + "WebCryptoAPI/sign_verify/test_rsa_pkcs.https.html": [ [ - "/WebCryptoAPI/sign_verify/test_rsa_pkcs.html", + "/WebCryptoAPI/sign_verify/test_rsa_pkcs.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/sign_verify/test_rsa_pss.html": [ + "WebCryptoAPI/sign_verify/test_rsa_pss.https.html": [ [ - "/WebCryptoAPI/sign_verify/test_rsa_pss.html", + "/WebCryptoAPI/sign_verify/test_rsa_pss.https.html", { "timeout": "long" } ] ], - "WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.html": [ + "WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.https.html": [ [ - "/WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.html", + "/WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.https.html", { "timeout": "long" } @@ -82674,6 +85592,18 @@ {} ] ], + "WebIDL/ecmascript-binding/interface-prototype-object.html": [ + [ + "/WebIDL/ecmascript-binding/interface-prototype-object.html", + {} + ] + ], + "WebIDL/ecmascript-binding/legacy-callback-interface-object.html": [ + [ + "/WebIDL/ecmascript-binding/legacy-callback-interface-object.html", + {} + ] + ], "XMLHttpRequest/FormData-append.html": [ [ "/XMLHttpRequest/FormData-append.html", @@ -84022,15 +86952,27 @@ {} ] ], + "accelerometer/Accelerometer.https.html": [ + [ + "/accelerometer/Accelerometer.https.html", + {} + ] + ], + "accelerometer/Accelerometer_insecure_context.html": [ + [ + "/accelerometer/Accelerometer_insecure_context.html", + {} + ] + ], "accelerometer/idlharness.https.html": [ [ "/accelerometer/idlharness.https.html", {} ] ], - "ambient-light/AmbientLightSensor_browsing_context.https.html": [ + "ambient-light/AmbientLightSensor.https.html": [ [ - "/ambient-light/AmbientLightSensor_browsing_context.https.html", + "/ambient-light/AmbientLightSensor.https.html", {} ] ], @@ -84040,38 +86982,6 @@ {} ] ], - "ambient-light/AmbientLightSensor_onchange.https.html": [ - [ - "/ambient-light/AmbientLightSensor_onchange.https.html", - {} - ] - ], - "ambient-light/AmbientLightSensor_reading.https.html": [ - [ - "/ambient-light/AmbientLightSensor_reading.https.html", - {} - ] - ], - "ambient-light/AmbientLightSensor_start.https.html": [ - [ - "/ambient-light/AmbientLightSensor_start.https.html", - {} - ] - ], - "ambient-light/AmbientLightSensor_stop.https.html": [ - [ - "/ambient-light/AmbientLightSensor_stop.https.html", - {} - ] - ], - "ambient-light/AmbientLightSensor_tests.html": [ - [ - "/ambient-light/AmbientLightSensor_tests.html", - { - "timeout": "long" - } - ] - ], "ambient-light/idlharness.https.html": [ [ "/ambient-light/idlharness.https.html", @@ -84970,6 +87880,12 @@ {} ] ], + "content-security-policy/child-src/child-src-redirect-blocked.sub.html": [ + [ + "/content-security-policy/child-src/child-src-redirect-blocked.sub.html", + {} + ] + ], "content-security-policy/child-src/child-src-worker-allowed.sub.html": [ [ "/content-security-policy/child-src/child-src-worker-allowed.sub.html", @@ -85012,6 +87928,12 @@ {} ] ], + "content-security-policy/embedded-enforcement/embedding_csp-header-invalid-format.html": [ + [ + "/content-security-policy/embedded-enforcement/embedding_csp-header-invalid-format.html", + {} + ] + ], "content-security-policy/embedded-enforcement/embedding_csp-header.html": [ [ "/content-security-policy/embedded-enforcement/embedding_csp-header.html", @@ -85126,51 +88048,183 @@ {} ] ], - "content-security-policy/frame-ancestors/deep-allows-none.sub.html": [ + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-none-block.html": [ [ - "/content-security-policy/frame-ancestors/deep-allows-none.sub.html", + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-none-block.html", {} ] ], - "content-security-policy/frame-ancestors/multiple-frames-meta-ignored.sub.html": [ + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block.html": [ [ - "/content-security-policy/frame-ancestors/multiple-frames-meta-ignored.sub.html", + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block.html", {} ] ], - "content-security-policy/frame-ancestors/multiple-frames-one-blocked.sub.html": [ + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-star-allow.html": [ [ - "/content-security-policy/frame-ancestors/multiple-frames-one-blocked.sub.html", + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-star-allow.html", {} ] ], - "content-security-policy/frame-ancestors/multiple-frames-self-allowed.sub.html": [ + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-allow.html": [ [ - "/content-security-policy/frame-ancestors/multiple-frames-self-allowed.sub.html", + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-allow.html", {} ] ], - "content-security-policy/frame-ancestors/nested-traversing-allowed.sub.html": [ + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-block.html": [ [ - "/content-security-policy/frame-ancestors/nested-traversing-allowed.sub.html", + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-block.html", {} ] ], - "content-security-policy/frame-ancestors/nested-traversing-banned-top-is-self.sub.html": [ + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-none-block.html": [ [ - "/content-security-policy/frame-ancestors/nested-traversing-banned-top-is-self.sub.html", + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-none-block.html", {} ] ], - "content-security-policy/frame-ancestors/nested-traversing-banned.sub.html": [ + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-self-block.html": [ [ - "/content-security-policy/frame-ancestors/nested-traversing-banned.sub.html", + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-self-block.html", {} ] ], - "content-security-policy/frame-ancestors/single-frame-self-allowed.sub.html": [ + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-star-allow.html": [ [ - "/content-security-policy/frame-ancestors/single-frame-self-allowed.sub.html", + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-star-allow.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-block.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-sandboxed-cross-url-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-sandboxed-cross-url-block.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-none-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-none-block.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-self-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-self-block.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-star-allow.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-star-allow.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-allow.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-allow.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-none-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-none-block.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-self-allow.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-self-allow.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-star-allow.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-star-allow.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-allow.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-allow.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-block.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-none-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-none-block.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-overrides-xfo.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-overrides-xfo.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-self-allow.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-self-allow.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-self-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-self-block.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-star-allow-crossorigin.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-star-allow-crossorigin.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-star-allow-sameorigin.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-star-allow-sameorigin.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-url-allow.sub.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-url-allow.sub.html", + {} + ] + ], + "content-security-policy/frame-ancestors/frame-ancestors-url-block.html": [ + [ + "/content-security-policy/frame-ancestors/frame-ancestors-url-block.html", + {} + ] + ], + "content-security-policy/frame-src/frame-src-redirect.html": [ + [ + "/content-security-policy/frame-src/frame-src-redirect.html", {} ] ], @@ -85448,6 +88502,12 @@ {} ] ], + "content-security-policy/script-src/script-src-sri_hash.sub.html": [ + [ + "/content-security-policy/script-src/script-src-sri_hash.sub.html", + {} + ] + ], "content-security-policy/script-src/script-src-strict_dynamic_and_unsafe_eval_eval.html": [ [ "/content-security-policy/script-src/script-src-strict_dynamic_and_unsafe_eval_eval.html", @@ -85544,6 +88604,12 @@ {} ] ], + "content-security-policy/script-src/script-src-strict_dynamic_worker.https.html": [ + [ + "/content-security-policy/script-src/script-src-strict_dynamic_worker.https.html", + {} + ] + ], "content-security-policy/securitypolicyviolation/blockeduri-eval.html": [ [ "/content-security-policy/securitypolicyviolation/blockeduri-eval.html", @@ -85562,6 +88628,12 @@ {} ] ], + "content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html": [ + [ + "/content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html", + {} + ] + ], "content-security-policy/securitypolicyviolation/inside-dedicated-worker.html": [ [ "/content-security-policy/securitypolicyviolation/inside-dedicated-worker.html", @@ -85634,6 +88706,12 @@ {} ] ], + "content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html": [ + [ + "/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html", + {} + ] + ], "content-security-policy/style-src/style-src-error-event-fires.html": [ [ "/content-security-policy/style-src/style-src-error-event-fires.html", @@ -85760,6 +88838,12 @@ {} ] ], + "content-security-policy/svg/object-in-svg-foreignobject.sub.html": [ + [ + "/content-security-policy/svg/object-in-svg-foreignobject.sub.html", + {} + ] + ], "content-security-policy/svg/svg-from-guid.html": [ [ "/content-security-policy/svg/svg-from-guid.html", @@ -86020,6 +89104,18 @@ {} ] ], + "credential-management/idl.https.html": [ + [ + "/credential-management/idl.https.html", + {} + ] + ], + "css-font-loading/fontfacesetloadevent-constructor.html": [ + [ + "/css-font-loading/fontfacesetloadevent-constructor.html", + {} + ] + ], "css-timing-1/cubic-bezier-timing-functions-output.html": [ [ "/css-timing-1/cubic-bezier-timing-functions-output.html", @@ -86256,24 +89352,96 @@ {} ] ], + "cssom-view/CaretPosition-001.html": [ + [ + "/cssom-view/CaretPosition-001.html", + {} + ] + ], "cssom-view/HTMLBody-ScrollArea_quirksmode.html": [ [ "/cssom-view/HTMLBody-ScrollArea_quirksmode.html", {} ] ], + "cssom-view/MediaQueryList-001.html": [ + [ + "/cssom-view/MediaQueryList-001.html", + {} + ] + ], "cssom-view/MediaQueryList-with-empty-string.html": [ [ "/cssom-view/MediaQueryList-with-empty-string.html", {} ] ], + "cssom-view/Screen-pixelDepth-Screen-colorDepth001.html": [ + [ + "/cssom-view/Screen-pixelDepth-Screen-colorDepth001.html", + {} + ] + ], + "cssom-view/cssom-getBoundingClientRect-001.html": [ + [ + "/cssom-view/cssom-getBoundingClientRect-001.html", + {} + ] + ], + "cssom-view/cssom-getBoundingClientRect-002.html": [ + [ + "/cssom-view/cssom-getBoundingClientRect-002.html", + {} + ] + ], + "cssom-view/cssom-getClientRects.html": [ + [ + "/cssom-view/cssom-getClientRects.html", + {} + ] + ], + "cssom-view/cssom-view-img-attributes-001.html": [ + [ + "/cssom-view/cssom-view-img-attributes-001.html", + {} + ] + ], + "cssom-view/cssom-view-window-screen-interface.html": [ + [ + "/cssom-view/cssom-view-window-screen-interface.html", + {} + ] + ], + "cssom-view/cssom-view/media-query-list-interface.xht": [ + [ + "/cssom-view/cssom-view/media-query-list-interface.xht", + {} + ] + ], + "cssom-view/cssom-view/window-interface.xht": [ + [ + "/cssom-view/cssom-view/window-interface.xht", + {} + ] + ], + "cssom-view/elementFromPoint-001.html": [ + [ + "/cssom-view/elementFromPoint-001.html", + {} + ] + ], "cssom-view/elementFromPoint.html": [ [ "/cssom-view/elementFromPoint.html", {} ] ], + "cssom-view/elementFromPosition.html": [ + [ + "/cssom-view/elementFromPosition.html", + {} + ] + ], "cssom-view/elementScroll.html": [ [ "/cssom-view/elementScroll.html", @@ -86292,6 +89460,24 @@ {} ] ], + "cssom-view/htmlelement-offset-width-001.html": [ + [ + "/cssom-view/htmlelement-offset-width-001.html", + {} + ] + ], + "cssom-view/matchMedia.xht": [ + [ + "/cssom-view/matchMedia.xht", + {} + ] + ], + "cssom-view/matchMediaAddListener.html": [ + [ + "/cssom-view/matchMediaAddListener.html", + {} + ] + ], "cssom-view/mouseEvent.html": [ [ "/cssom-view/mouseEvent.html", @@ -86304,18 +89490,78 @@ {} ] ], + "cssom-view/offsetParent_element_test.html": [ + [ + "/cssom-view/offsetParent_element_test.html", + {} + ] + ], + "cssom-view/scrollWidthHeight.xht": [ + [ + "/cssom-view/scrollWidthHeight.xht", + {} + ] + ], + "cssom-view/scrollWidthHeightWhenNotScrollable.xht": [ + [ + "/cssom-view/scrollWidthHeightWhenNotScrollable.xht", + {} + ] + ], "cssom-view/scrolling-no-browsing-context.html": [ [ "/cssom-view/scrolling-no-browsing-context.html", {} ] ], + "cssom-view/scrolling-quirks-vs-nonquirks.html": [ + [ + "/cssom-view/scrolling-quirks-vs-nonquirks.html", + {} + ] + ], "cssom-view/scrollingElement.html": [ [ "/cssom-view/scrollingElement.html", {} ] ], + "cssom-view/ttwf-js-cssomview-getclientrects-length.html": [ + [ + "/cssom-view/ttwf-js-cssomview-getclientrects-length.html", + {} + ] + ], + "cssom-view/ttwf-scrollintoview.html": [ + [ + "/cssom-view/ttwf-scrollintoview.html", + {} + ] + ], + "cssom-view/window-screen-height-immutable.html": [ + [ + "/cssom-view/window-screen-height-immutable.html", + {} + ] + ], + "cssom-view/window-screen-height.html": [ + [ + "/cssom-view/window-screen-height.html", + {} + ] + ], + "cssom-view/window-screen-width-immutable.html": [ + [ + "/cssom-view/window-screen-width-immutable.html", + {} + ] + ], + "cssom-view/window-screen-width.html": [ + [ + "/cssom-view/window-screen-width.html", + {} + ] + ], "cssom/CSS.html": [ [ "/cssom/CSS.html", @@ -86364,12 +89610,90 @@ {} ] ], + "cssom/MediaList.xhtml": [ + [ + "/cssom/MediaList.xhtml", + {} + ] + ], "cssom/StyleSheetList.html": [ [ "/cssom/StyleSheetList.html", {} ] ], + "cssom/computed-style-001.html": [ + [ + "/cssom/computed-style-001.html", + {} + ] + ], + "cssom/css-style-attribute-modifications.html": [ + [ + "/cssom/css-style-attribute-modifications.html", + {} + ] + ], + "cssom/css-style-declaration-modifications.html": [ + [ + "/cssom/css-style-declaration-modifications.html", + {} + ] + ], + "cssom/cssimportrule.html": [ + [ + "/cssom/cssimportrule.html", + {} + ] + ], + "cssom/cssom-cssText-serialize.html": [ + [ + "/cssom/cssom-cssText-serialize.html", + {} + ] + ], + "cssom/cssom-cssstyledeclaration-set.html": [ + [ + "/cssom/cssom-cssstyledeclaration-set.html", + {} + ] + ], + "cssom/cssom-fontfacerule-constructors.html": [ + [ + "/cssom/cssom-fontfacerule-constructors.html", + {} + ] + ], + "cssom/cssom-fontfacerule.html": [ + [ + "/cssom/cssom-fontfacerule.html", + {} + ] + ], + "cssom/cssom-setProperty-shorthand.html": [ + [ + "/cssom/cssom-setProperty-shorthand.html", + {} + ] + ], + "cssom/cssstyledeclaration-csstext.html": [ + [ + "/cssom/cssstyledeclaration-csstext.html", + {} + ] + ], + "cssom/cssstyledeclaration-mutability.html": [ + [ + "/cssom/cssstyledeclaration-mutability.html", + {} + ] + ], + "cssom/escape.html": [ + [ + "/cssom/escape.html", + {} + ] + ], "cssom/getComputedStyle-pseudo.html": [ [ "/cssom/getComputedStyle-pseudo.html", @@ -86382,36 +89706,138 @@ {} ] ], + "cssom/index-001.html": [ + [ + "/cssom/index-001.html", + {} + ] + ], + "cssom/index-002.html": [ + [ + "/cssom/index-002.html", + {} + ] + ], + "cssom/index-003.html": [ + [ + "/cssom/index-003.html", + {} + ] + ], + "cssom/inline-style-001.html": [ + [ + "/cssom/inline-style-001.html", + {} + ] + ], + "cssom/interfaces.html": [ + [ + "/cssom/interfaces.html", + {} + ] + ], + "cssom/medialist-interfaces-001.html": [ + [ + "/cssom/medialist-interfaces-001.html", + {} + ] + ], + "cssom/medialist-interfaces-002.html": [ + [ + "/cssom/medialist-interfaces-002.html", + {} + ] + ], + "cssom/medialist-interfaces-003.html": [ + [ + "/cssom/medialist-interfaces-003.html", + {} + ] + ], + "cssom/medialist-interfaces-004.html": [ + [ + "/cssom/medialist-interfaces-004.html", + {} + ] + ], "cssom/overflow-serialization.html": [ [ "/cssom/overflow-serialization.html", {} ] ], + "cssom/selectorSerialize.html": [ + [ + "/cssom/selectorSerialize.html", + {} + ] + ], "cssom/serialization-CSSDeclaration-with-important.html": [ [ "/cssom/serialization-CSSDeclaration-with-important.html", {} ] ], + "cssom/serialize-namespaced-type-selectors.html": [ + [ + "/cssom/serialize-namespaced-type-selectors.html", + {} + ] + ], "cssom/serialize-values.html": [ [ "/cssom/serialize-values.html", {} ] ], + "cssom/serialize-variable-reference.html": [ + [ + "/cssom/serialize-variable-reference.html", + {} + ] + ], "cssom/shorthand-serialization.html": [ [ "/cssom/shorthand-serialization.html", {} ] ], + "cssom/style-sheet-interfaces-001.html": [ + [ + "/cssom/style-sheet-interfaces-001.html", + {} + ] + ], + "cssom/style-sheet-interfaces-002.html": [ + [ + "/cssom/style-sheet-interfaces-002.html", + {} + ] + ], "cssom/stylesheet-same-origin.sub.html": [ [ "/cssom/stylesheet-same-origin.sub.html", {} ] ], + "cssom/ttwf-cssom-doc-ext-load-count.html": [ + [ + "/cssom/ttwf-cssom-doc-ext-load-count.html", + {} + ] + ], + "cssom/ttwf-cssom-doc-ext-load-tree-order.html": [ + [ + "/cssom/ttwf-cssom-doc-ext-load-tree-order.html", + {} + ] + ], + "cssom/ttwf-cssom-document-extension.html": [ + [ + "/cssom/ttwf-cssom-document-extension.html", + {} + ] + ], "cssom/variable-names.html": [ [ "/cssom/variable-names.html", @@ -86466,6 +89892,12 @@ {} ] ], + "custom-elements/custom-element-registry/per-global.html": [ + [ + "/custom-elements/custom-element-registry/per-global.html", + {} + ] + ], "custom-elements/disconnected-callbacks.html": [ [ "/custom-elements/disconnected-callbacks.html", @@ -86478,6 +89910,12 @@ {} ] ], + "custom-elements/microtasks-and-constructors.html": [ + [ + "/custom-elements/microtasks-and-constructors.html", + {} + ] + ], "custom-elements/parser/parser-constructs-custom-element-in-document-write.html": [ [ "/custom-elements/parser/parser-constructs-custom-element-in-document-write.html", @@ -90018,6 +93456,12 @@ {} ] ], + "fetch/api/basic/block-mime-as-script.html": [ + [ + "/fetch/api/basic/block-mime-as-script.html", + {} + ] + ], "fetch/api/basic/conditional-get.html": [ [ "/fetch/api/basic/conditional-get.html", @@ -91066,6 +94510,18 @@ {} ] ], + "gyroscope/Gyroscope.https.html": [ + [ + "/gyroscope/Gyroscope.https.html", + {} + ] + ], + "gyroscope/Gyroscope_insecure_context.html": [ + [ + "/gyroscope/Gyroscope_insecure_context.html", + {} + ] + ], "gyroscope/idlharness.https.html": [ [ "/gyroscope/idlharness.https.html", @@ -92116,6 +95572,12 @@ {} ] ], + "html/browsers/history/the-location-interface/per-global.window.js": [ + [ + "/html/browsers/history/the-location-interface/per-global.window.html", + {} + ] + ], "html/browsers/history/the-location-interface/reload_document_open_write.html": [ [ "/html/browsers/history/the-location-interface/reload_document_open_write.html", @@ -92264,6 +95726,12 @@ {} ] ], + "html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter.html": [ + [ + "/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter.html", + {} + ] + ], "html/browsers/sandboxing/sandbox-allow-same-origin.html": [ [ "/html/browsers/sandboxing/sandbox-allow-same-origin.html", @@ -92356,6 +95824,142 @@ } ] ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-innerwidth-innerheight.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-innerwidth-innerheight.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-screenx-screeny.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-screenx-screeny.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-top-left.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-top-left.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-width-height.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-width-height.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-height.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-height.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerheight.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerheight.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerwidth.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerwidth.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-left.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-left.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screenx.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screenx.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screeny.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screeny.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-top.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-top.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-width.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-width.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-innerheight-innerwidth.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-innerheight-innerwidth.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-noopener.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-noopener.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-screenx-screeny.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-screenx-screeny.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-top-left.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-top-left.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-width-height.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-width-height.html", + { + "timeout": "long" + } + ] + ], "html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1.html": [ [ "/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1.html", @@ -92500,69 +96104,93 @@ {} ] ], - "html/browsers/windows/browsing-context-names/001.html": [ + "html/browsers/windows/browsing-context-names/choose-_blank-001.html": [ [ - "/html/browsers/windows/browsing-context-names/001.html", + "/html/browsers/windows/browsing-context-names/choose-_blank-001.html", {} ] ], - "html/browsers/windows/browsing-context-names/002.html": [ + "html/browsers/windows/browsing-context-names/choose-_blank-002.html": [ [ - "/html/browsers/windows/browsing-context-names/002.html", + "/html/browsers/windows/browsing-context-names/choose-_blank-002.html", {} ] ], - "html/browsers/windows/browsing-context-names/browsing-context-_blank.html": [ + "html/browsers/windows/browsing-context-names/choose-_blank-003.html": [ [ - "/html/browsers/windows/browsing-context-names/browsing-context-_blank.html", + "/html/browsers/windows/browsing-context-names/choose-_blank-003.html", {} ] ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html": [ + "html/browsers/windows/browsing-context-names/choose-_parent-001.html": [ [ - "/html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html", + "/html/browsers/windows/browsing-context-names/choose-_parent-001.html", {} ] ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-parent-001.html": [ + "html/browsers/windows/browsing-context-names/choose-_parent-002.html": [ [ - "/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-001.html", + "/html/browsers/windows/browsing-context-names/choose-_parent-002.html", {} ] ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-parent-002.html": [ + "html/browsers/windows/browsing-context-names/choose-_parent-003.html": [ [ - "/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-002.html", + "/html/browsers/windows/browsing-context-names/choose-_parent-003.html", {} ] ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-parent-003.html": [ + "html/browsers/windows/browsing-context-names/choose-_parent-004.html": [ [ - "/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-003.html", + "/html/browsers/windows/browsing-context-names/choose-_parent-004.html", {} ] ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-parent-004.html": [ + "html/browsers/windows/browsing-context-names/choose-_self-001.html": [ [ - "/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-004.html", + "/html/browsers/windows/browsing-context-names/choose-_self-001.html", {} ] ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html": [ + "html/browsers/windows/browsing-context-names/choose-_self-002.html": [ [ - "/html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html", + "/html/browsers/windows/browsing-context-names/choose-_self-002.html", {} ] ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html": [ + "html/browsers/windows/browsing-context-names/choose-_top-001.html": [ [ - "/html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html", + "/html/browsers/windows/browsing-context-names/choose-_top-001.html", {} ] ], - "html/browsers/windows/browsing-context-names/browsing-context-default-name.html": [ + "html/browsers/windows/browsing-context-names/choose-_top-002.html": [ [ - "/html/browsers/windows/browsing-context-names/browsing-context-default-name.html", + "/html/browsers/windows/browsing-context-names/choose-_top-002.html", + {} + ] + ], + "html/browsers/windows/browsing-context-names/choose-_top-003.html": [ + [ + "/html/browsers/windows/browsing-context-names/choose-_top-003.html", + {} + ] + ], + "html/browsers/windows/browsing-context-names/choose-default-001.html": [ + [ + "/html/browsers/windows/browsing-context-names/choose-default-001.html", + {} + ] + ], + "html/browsers/windows/browsing-context-names/choose-default-002.html": [ + [ + "/html/browsers/windows/browsing-context-names/choose-default-002.html", + {} + ] + ], + "html/browsers/windows/browsing-context-names/choose-existing-001.html": [ + [ + "/html/browsers/windows/browsing-context-names/choose-existing-001.html", {} ] ], @@ -93964,6 +97592,110 @@ {} ] ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-dedicatedworker.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-dedicatedworker.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-sharedworker.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-sharedworker.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.js": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.html", + {} + ], + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.worker.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-notifications-api.any.js": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-notifications-api.any.html", + {} + ], + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-notifications-api.any.worker.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-failure.https.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-failure.https.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html", + {} + ] + ], + "html/infrastructure/safe-passing-of-structured-data/structured_clone_blob.html": [ + [ + "/html/infrastructure/safe-passing-of-structured-data/structured_clone_blob.html", + {} + ] + ], "html/infrastructure/terminology/plugins/text-plain.html": [ [ "/html/infrastructure/terminology/plugins/text-plain.html", @@ -94136,6 +97868,18 @@ {} ] ], + "html/rendering/non-replaced-elements/the-page/iframe-body-margin-attributes.html": [ + [ + "/html/rendering/non-replaced-elements/the-page/iframe-body-margin-attributes.html", + {} + ] + ], + "html/rendering/non-replaced-elements/the-page/iframe-marginwidth-marginheight.html": [ + [ + "/html/rendering/non-replaced-elements/the-page/iframe-marginwidth-marginheight.html", + {} + ] + ], "html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html": [ [ "/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html", @@ -95688,6 +99432,12 @@ {} ] ], + "html/semantics/embedded-content/the-canvas-element/imagedata.html": [ + [ + "/html/semantics/embedded-content/the-canvas-element/imagedata.html", + {} + ] + ], "html/semantics/embedded-content/the-canvas-element/initial.colour.html": [ [ "/html/semantics/embedded-content/the-canvas-element/initial.colour.html", @@ -96402,6 +100152,12 @@ {} ] ], + "html/semantics/embedded-content/the-img-element/delay-load-event.html": [ + [ + "/html/semantics/embedded-content/the-img-element/delay-load-event.html", + {} + ] + ], "html/semantics/embedded-content/the-img-element/environment-changes/viewport-change.html": [ [ "/html/semantics/embedded-content/the-img-element/environment-changes/viewport-change.html", @@ -96668,6 +100424,24 @@ {} ] ], + "html/semantics/forms/form-control-infrastructure/form_attribute.html": [ + [ + "/html/semantics/forms/form-control-infrastructure/form_attribute.html", + {} + ] + ], + "html/semantics/forms/form-control-infrastructure/form_owner_and_table.html": [ + [ + "/html/semantics/forms/form-control-infrastructure/form_owner_and_table.html", + {} + ] + ], + "html/semantics/forms/form-control-infrastructure/form_owner_and_table_2.html": [ + [ + "/html/semantics/forms/form-control-infrastructure/form_owner_and_table_2.html", + {} + ] + ], "html/semantics/forms/form-submission-0/form-data-set-usv.html": [ [ "/html/semantics/forms/form-submission-0/form-data-set-usv.html", @@ -97346,6 +101120,12 @@ {} ] ], + "html/semantics/interactive-elements/the-dialog-element/centering.html": [ + [ + "/html/semantics/interactive-elements/the-dialog-element/centering.html", + {} + ] + ], "html/semantics/interactive-elements/the-dialog-element/dialog-close.html": [ [ "/html/semantics/interactive-elements/the-dialog-element/dialog-close.html", @@ -97364,6 +101144,12 @@ {} ] ], + "html/semantics/interactive-elements/the-menu-element/menuitem-label.html": [ + [ + "/html/semantics/interactive-elements/the-menu-element/menuitem-label.html", + {} + ] + ], "html/semantics/interactive-elements/the-summary-element/activation-behavior.html": [ [ "/html/semantics/interactive-elements/the-summary-element/activation-behavior.html", @@ -97528,6 +101314,12 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html": [ + [ + "/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html", + {} + ] + ], "html/semantics/scripting-1/the-script-element/nomodule-reflect.html": [ [ "/html/semantics/scripting-1/the-script-element/nomodule-reflect.html", @@ -97900,6 +101692,12 @@ {} ] ], + "html/semantics/tabular-data/processing-model-1/span-limits.html": [ + [ + "/html/semantics/tabular-data/processing-model-1/span-limits.html", + {} + ] + ], "html/semantics/tabular-data/the-caption-element/caption_001.html": [ [ "/html/semantics/tabular-data/the-caption-element/caption_001.html", @@ -98056,6 +101854,18 @@ {} ] ], + "html/semantics/text-level-semantics/the-a-element/a.rel-getter-01.html": [ + [ + "/html/semantics/text-level-semantics/the-a-element/a.rel-getter-01.html", + {} + ] + ], + "html/semantics/text-level-semantics/the-a-element/a.rel-setter-01.html": [ + [ + "/html/semantics/text-level-semantics/the-a-element/a.rel-setter-01.html", + {} + ] + ], "html/semantics/text-level-semantics/the-a-element/a.text-getter-01.html": [ [ "/html/semantics/text-level-semantics/the-a-element/a.text-getter-01.html", @@ -99884,6 +103694,30 @@ {} ] ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-dedicatedworker.html": [ + [ + "/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-dedicatedworker.html", + {} + ] + ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-serviceworker.https.html": [ + [ + "/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-serviceworker.https.html", + {} + ] + ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-sharedworker.html": [ + [ + "/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-sharedworker.html", + {} + ] + ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-window.html": [ + [ + "/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-window.html", + {} + ] + ], "html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setInterval.html": [ [ "/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setInterval.html", @@ -100052,18 +103886,6 @@ {} ] ], - "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html": [ - [ - "/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html", - {} - ] - ], - "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js": [ - [ - "/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.html", - {} - ] - ], "html/webappapis/system-state-and-capabilities/the-navigator-object/content.html": [ [ "/html/webappapis/system-state-and-capabilities/the-navigator-object/content.html", @@ -100112,6 +103934,16 @@ {} ] ], + "html/webappapis/system-state-and-capabilities/the-navigator-object/navigator.any.js": [ + [ + "/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator.any.html", + {} + ], + [ + "/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator.any.worker.html", + {} + ] + ], "html/webappapis/system-state-and-capabilities/the-navigator-object/navigatorlanguage.html": [ [ "/html/webappapis/system-state-and-capabilities/the-navigator-object/navigatorlanguage.html", @@ -100172,6 +104004,30 @@ {} ] ], + "html/webappapis/timers/negative-setinterval.html": [ + [ + "/html/webappapis/timers/negative-setinterval.html", + {} + ] + ], + "html/webappapis/timers/negative-settimeout.html": [ + [ + "/html/webappapis/timers/negative-settimeout.html", + {} + ] + ], + "html/webappapis/timers/type-long-setinterval.html": [ + [ + "/html/webappapis/timers/type-long-setinterval.html", + {} + ] + ], + "html/webappapis/timers/type-long-settimeout.html": [ + [ + "/html/webappapis/timers/type-long-settimeout.html", + {} + ] + ], "http/content_length.html": [ [ "/http/content_length.html", @@ -100322,6 +104178,36 @@ {} ] ], + "keyboard-lock/idlharness.https.html": [ + [ + "/keyboard-lock/idlharness.https.html", + {} + ] + ], + "keyboard-lock/navigator-cancelKeyboardLock.https.html": [ + [ + "/keyboard-lock/navigator-cancelKeyboardLock.https.html", + {} + ] + ], + "keyboard-lock/navigator-requestKeyboardLock-two-parallel-requests.https.html": [ + [ + "/keyboard-lock/navigator-requestKeyboardLock-two-parallel-requests.https.html", + {} + ] + ], + "keyboard-lock/navigator-requestKeyboardLock-two-sequential-requests.https.html": [ + [ + "/keyboard-lock/navigator-requestKeyboardLock-two-sequential-requests.https.html", + {} + ] + ], + "keyboard-lock/navigator-requestKeyboardLock.https.html": [ + [ + "/keyboard-lock/navigator-requestKeyboardLock.https.html", + {} + ] + ], "longtask-timing/longtask-attributes.html": [ [ "/longtask-timing/longtask-attributes.html", @@ -100370,6 +104256,18 @@ {} ] ], + "magnetometer/Magnetometer.https.html": [ + [ + "/magnetometer/Magnetometer.https.html", + {} + ] + ], + "magnetometer/Magnetometer_insecure_context.html": [ + [ + "/magnetometer/Magnetometer_insecure_context.html", + {} + ] + ], "magnetometer/idlharness.https.html": [ [ "/magnetometer/idlharness.https.html", @@ -100520,15 +104418,15 @@ {} ] ], - "media-capabilities/idlharness.html": [ + "media-capabilities/decodingInfo.html": [ [ - "/media-capabilities/idlharness.html", + "/media-capabilities/decodingInfo.html", {} ] ], - "media-capabilities/query.html": [ + "media-capabilities/idlharness.html": [ [ - "/media-capabilities/query.html", + "/media-capabilities/idlharness.html", {} ] ], @@ -100898,6 +104796,12 @@ {} ] ], + "mediacapture-image/idlharness.html": [ + [ + "/mediacapture-image/idlharness.html", + {} + ] + ], "mediacapture-record/BlobEvent-constructor.html": [ [ "/mediacapture-record/BlobEvent-constructor.html", @@ -102332,6 +106236,12 @@ {} ] ], + "mixed-content/imageset.https.sub.html": [ + [ + "/mixed-content/imageset.https.sub.html", + {} + ] + ], "mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html": [ [ "/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html", @@ -102698,6 +106608,18 @@ {} ] ], + "navigation-timing/nav2_test_document_replaced.html": [ + [ + "/navigation-timing/nav2_test_document_replaced.html", + {} + ] + ], + "navigation-timing/nav2_test_frame_removed.html": [ + [ + "/navigation-timing/nav2_test_frame_removed.html", + {} + ] + ], "navigation-timing/nav2_test_instance_accessible_from_the_start.html": [ [ "/navigation-timing/nav2_test_instance_accessible_from_the_start.html", @@ -112960,12 +116882,24 @@ {} ] ], + "orientation-sensor/idlharness.https.html": [ + [ + "/orientation-sensor/idlharness.https.html", + {} + ] + ], "page-visibility/idlharness.html": [ [ "/page-visibility/idlharness.html", {} ] ], + "page-visibility/prerender_call.html": [ + [ + "/page-visibility/prerender_call.html", + {} + ] + ], "page-visibility/test_attributes_exist.html": [ [ "/page-visibility/test_attributes_exist.html", @@ -113068,6 +117002,12 @@ {} ] ], + "payment-request/payment-request-id.https.html": [ + [ + "/payment-request/payment-request-id.https.html", + {} + ] + ], "payment-request/payment-request-in-iframe.html": [ [ "/payment-request/payment-request-in-iframe.html", @@ -113316,6 +117256,12 @@ {} ] ], + "presentation-api/controlling-ua/defaultRequest.https.html": [ + [ + "/presentation-api/controlling-ua/defaultRequest.https.html", + {} + ] + ], "presentation-api/controlling-ua/getAvailability.https.html": [ [ "/presentation-api/controlling-ua/getAvailability.https.html", @@ -121514,6 +125460,60 @@ {} ] ], + "resource-timing/resource_TAO_match_origin.htm": [ + [ + "/resource-timing/resource_TAO_match_origin.htm", + {} + ] + ], + "resource-timing/resource_TAO_match_wildcard.htm": [ + [ + "/resource-timing/resource_TAO_match_wildcard.htm", + {} + ] + ], + "resource-timing/resource_TAO_multi.htm": [ + [ + "/resource-timing/resource_TAO_multi.htm", + {} + ] + ], + "resource-timing/resource_TAO_null.htm": [ + [ + "/resource-timing/resource_TAO_null.htm", + {} + ] + ], + "resource-timing/resource_TAO_origin.htm": [ + [ + "/resource-timing/resource_TAO_origin.htm", + {} + ] + ], + "resource-timing/resource_TAO_origin_uppercase.htm": [ + [ + "/resource-timing/resource_TAO_origin_uppercase.htm", + {} + ] + ], + "resource-timing/resource_TAO_space.htm": [ + [ + "/resource-timing/resource_TAO_space.htm", + {} + ] + ], + "resource-timing/resource_TAO_wildcard.htm": [ + [ + "/resource-timing/resource_TAO_wildcard.htm", + {} + ] + ], + "resource-timing/resource_TAO_zero.htm": [ + [ + "/resource-timing/resource_TAO_zero.htm", + {} + ] + ], "resource-timing/resource_cached.htm": [ [ "/resource-timing/resource_cached.htm", @@ -121762,6 +125762,14 @@ } ] ], + "selection/collapse-15.html": [ + [ + "/selection/collapse-15.html", + { + "timeout": "long" + } + ] + ], "selection/collapse-30.html": [ [ "/selection/collapse-30.html", @@ -121770,6 +125778,14 @@ } ] ], + "selection/collapse-45.html": [ + [ + "/selection/collapse-45.html", + { + "timeout": "long" + } + ] + ], "selection/collapseToStartEnd.html": [ [ "/selection/collapseToStartEnd.html", @@ -121856,9 +125872,9 @@ {} ] ], - "selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html": [ + "selection/type.html": [ [ - "/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html", + "/selection/type.html", {} ] ], @@ -121886,6 +125902,12 @@ {} ] ], + "server-timing/test_server_timing.html": [ + [ + "/server-timing/test_server_timing.html", + {} + ] + ], "service-workers/cache-storage/common.https.html": [ [ "/service-workers/cache-storage/common.https.html", @@ -121910,6 +125932,14 @@ } ] ], + "service-workers/cache-storage/serviceworker/cache-keys.https.html": [ + [ + "/service-workers/cache-storage/serviceworker/cache-keys.https.html", + { + "timeout": "long" + } + ] + ], "service-workers/cache-storage/serviceworker/cache-match.https.html": [ [ "/service-workers/cache-storage/serviceworker/cache-match.https.html", @@ -121980,6 +126010,14 @@ } ] ], + "service-workers/cache-storage/window/cache-keys.https.html": [ + [ + "/service-workers/cache-storage/window/cache-keys.https.html", + { + "timeout": "long" + } + ] + ], "service-workers/cache-storage/window/cache-match.https.html": [ [ "/service-workers/cache-storage/window/cache-match.https.html", @@ -122052,6 +126090,14 @@ } ] ], + "service-workers/cache-storage/worker/cache-keys.https.html": [ + [ + "/service-workers/cache-storage/worker/cache-keys.https.html", + { + "timeout": "long" + } + ] + ], "service-workers/cache-storage/worker/cache-match.https.html": [ [ "/service-workers/cache-storage/worker/cache-match.https.html", @@ -122130,6 +126176,12 @@ {} ] ], + "service-workers/service-worker/ServiceWorkerGlobalScope/service-worker-error-event.https.html": [ + [ + "/service-workers/service-worker/ServiceWorkerGlobalScope/service-worker-error-event.https.html", + {} + ] + ], "service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html": [ [ "/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html", @@ -122202,12 +126254,24 @@ {} ] ], + "service-workers/service-worker/client-id.https.html": [ + [ + "/service-workers/service-worker/client-id.https.html", + {} + ] + ], "service-workers/service-worker/client-navigate.https.html": [ [ "/service-workers/service-worker/client-navigate.https.html", {} ] ], + "service-workers/service-worker/clients-get-client-types.https.html": [ + [ + "/service-workers/service-worker/clients-get-client-types.https.html", + {} + ] + ], "service-workers/service-worker/clients-get-cross-origin.https.html": [ [ "/service-workers/service-worker/clients-get-cross-origin.https.html", @@ -122238,6 +126302,12 @@ {} ] ], + "service-workers/service-worker/clients-matchall-on-evaluation.https.html": [ + [ + "/service-workers/service-worker/clients-matchall-on-evaluation.https.html", + {} + ] + ], "service-workers/service-worker/clients-matchall-order.https.html": [ [ "/service-workers/service-worker/clients-matchall-order.https.html", @@ -122330,6 +126400,12 @@ } ] ], + "service-workers/service-worker/fetch-event-respond-with-argument.https.html": [ + [ + "/service-workers/service-worker/fetch-event-respond-with-argument.https.html", + {} + ] + ], "service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html": [ [ "/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html", @@ -122574,6 +126650,12 @@ {} ] ], + "service-workers/service-worker/navigation-preload/resource-timing.https.html": [ + [ + "/service-workers/service-worker/navigation-preload/resource-timing.https.html", + {} + ] + ], "service-workers/service-worker/navigation-redirect.https.html": [ [ "/service-workers/service-worker/navigation-redirect.https.html", @@ -123020,6 +127102,12 @@ {} ] ], + "shadow-dom/slots-fallback-in-document.html": [ + [ + "/shadow-dom/slots-fallback-in-document.html", + {} + ] + ], "shadow-dom/slots-fallback.html": [ [ "/shadow-dom/slots-fallback.html", @@ -123362,6 +127450,12 @@ {} ] ], + "staticrange/idlharness.html": [ + [ + "/staticrange/idlharness.html", + {} + ] + ], "storage/estimate-indexeddb-worker.https.html": [ [ "/storage/estimate-indexeddb-worker.https.html", @@ -123404,6 +127498,36 @@ {} ] ], + "storage/storagemanager-estimate.https.html": [ + [ + "/storage/storagemanager-estimate.https.html", + {} + ] + ], + "storage/storagemanager-persist-worker.https.html": [ + [ + "/storage/storagemanager-persist-worker.https.html", + {} + ] + ], + "storage/storagemanager-persist.https.html": [ + [ + "/storage/storagemanager-persist.https.html", + {} + ] + ], + "storage/storagemanager-persisted-worker.https.html": [ + [ + "/storage/storagemanager-persisted-worker.https.html", + {} + ] + ], + "storage/storagemanager-persisted.https.html": [ + [ + "/storage/storagemanager-persisted.https.html", + {} + ] + ], "streams/byte-length-queuing-strategy.dedicatedworker.html": [ [ "/streams/byte-length-queuing-strategy.dedicatedworker.html", @@ -124172,6 +128296,30 @@ {} ] ], + "streams/writable-streams/error.dedicatedworker.html": [ + [ + "/streams/writable-streams/error.dedicatedworker.html", + {} + ] + ], + "streams/writable-streams/error.html": [ + [ + "/streams/writable-streams/error.html", + {} + ] + ], + "streams/writable-streams/error.serviceworker.https.html": [ + [ + "/streams/writable-streams/error.serviceworker.https.html", + {} + ] + ], + "streams/writable-streams/error.sharedworker.html": [ + [ + "/streams/writable-streams/error.sharedworker.html", + {} + ] + ], "streams/writable-streams/floating-point-total-queue-size.dedicatedworker.html": [ [ "/streams/writable-streams/floating-point-total-queue-size.dedicatedworker.html", @@ -124220,6 +128368,30 @@ {} ] ], + "streams/writable-streams/properties.dedicatedworker.html": [ + [ + "/streams/writable-streams/properties.dedicatedworker.html", + {} + ] + ], + "streams/writable-streams/properties.html": [ + [ + "/streams/writable-streams/properties.html", + {} + ] + ], + "streams/writable-streams/properties.serviceworker.https.html": [ + [ + "/streams/writable-streams/properties.serviceworker.https.html", + {} + ] + ], + "streams/writable-streams/properties.sharedworker.html": [ + [ + "/streams/writable-streams/properties.sharedworker.html", + {} + ] + ], "streams/writable-streams/reentrant-strategy.dedicatedworker.html": [ [ "/streams/writable-streams/reentrant-strategy.dedicatedworker.html", @@ -124307,7 +128479,9 @@ "svg/interfaces.html": [ [ "/svg/interfaces.html", - {} + { + "timeout": "long" + } ] ], "svg/linking/scripted/href-animate-element.html": [ @@ -124478,15 +128652,13 @@ {} ] ], - "url/historical.html": [ + "url/historical.any.js": [ [ - "/url/historical.html", + "/url/historical.any.html", {} - ] - ], - "url/historical.worker.js": [ + ], [ - "/url/historical.worker.html", + "/url/historical.any.worker.html", {} ] ], @@ -124878,6 +129050,12 @@ {} ] ], + "web-animations/interfaces/Animation/idlharness.html": [ + [ + "/web-animations/interfaces/Animation/idlharness.html", + {} + ] + ], "web-animations/interfaces/Animation/oncancel.html": [ [ "/web-animations/interfaces/Animation/oncancel.html", @@ -125106,12 +129284,30 @@ {} ] ], + "web-animations/timing-model/animations/canceling-an-animation.html": [ + [ + "/web-animations/timing-model/animations/canceling-an-animation.html", + {} + ] + ], "web-animations/timing-model/animations/current-time.html": [ [ "/web-animations/timing-model/animations/current-time.html", {} ] ], + "web-animations/timing-model/animations/finishing-an-animation.html": [ + [ + "/web-animations/timing-model/animations/finishing-an-animation.html", + {} + ] + ], + "web-animations/timing-model/animations/pausing-an-animation.html": [ + [ + "/web-animations/timing-model/animations/pausing-an-animation.html", + {} + ] + ], "web-animations/timing-model/animations/playing-an-animation.html": [ [ "/web-animations/timing-model/animations/playing-an-animation.html", @@ -125154,6 +129350,12 @@ {} ] ], + "web-nfc/idlharness.https.html": [ + [ + "/web-nfc/idlharness.https.html", + {} + ] + ], "webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html": [ [ "/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html", @@ -129570,6 +133772,12 @@ {} ] ], + "webmessaging/messageerror.html": [ + [ + "/webmessaging/messageerror.html", + {} + ] + ], "webmessaging/postMessage_ArrayBuffer.sub.htm": [ [ "/webmessaging/postMessage_ArrayBuffer.sub.htm", @@ -129972,12 +134180,54 @@ {} ] ], + "webrtc/RTCConfiguration-iceCandidatePoolSize.html": [ + [ + "/webrtc/RTCConfiguration-iceCandidatePoolSize.html", + {} + ] + ], "webrtc/RTCDataChannelEvent-constructor.html": [ [ "/webrtc/RTCDataChannelEvent-constructor.html", {} ] ], + "webrtc/RTCPeerConnection-canTrickleIceCandidates.html": [ + [ + "/webrtc/RTCPeerConnection-canTrickleIceCandidates.html", + {} + ] + ], + "webrtc/RTCPeerConnection-constructor.html": [ + [ + "/webrtc/RTCPeerConnection-constructor.html", + {} + ] + ], + "webrtc/RTCPeerConnection-createDataChannel.html": [ + [ + "/webrtc/RTCPeerConnection-createDataChannel.html", + {} + ] + ], + "webrtc/RTCPeerConnection-iceGatheringState.html": [ + [ + "/webrtc/RTCPeerConnection-iceGatheringState.html", + {} + ] + ], + "webrtc/RTCPeerConnection-idl.html": [ + [ + "/webrtc/RTCPeerConnection-idl.html", + {} + ] + ], + "webrtc/RTCPeerConnection-setRemoteDescription.html": [ + [ + "/webrtc/RTCPeerConnection-setRemoteDescription.html", + {} + ] + ], "webrtc/RTCPeerConnectionIceEvent-constructor.html": [ [ "/webrtc/RTCPeerConnectionIceEvent-constructor.html", @@ -129990,6 +134240,24 @@ {} ] ], + "webrtc/datachannel-idlharness.html": [ + [ + "/webrtc/datachannel-idlharness.html", + {} + ] + ], + "webrtc/getstats.html": [ + [ + "/webrtc/getstats.html", + {} + ] + ], + "webrtc/interfaces.html": [ + [ + "/webrtc/interfaces.html", + {} + ] + ], "webrtc/no-media-call.html": [ [ "/webrtc/no-media-call.html", @@ -130002,36 +134270,6 @@ {} ] ], - "webrtc/rtcpeerconnection/iceGatheringState.html": [ - [ - "/webrtc/rtcpeerconnection/iceGatheringState.html", - {} - ] - ], - "webrtc/rtcpeerconnection/rtcconfiguration-icecandidatepoolsize.html": [ - [ - "/webrtc/rtcpeerconnection/rtcconfiguration-icecandidatepoolsize.html", - {} - ] - ], - "webrtc/rtcpeerconnection/rtcpeerconnection-constructor.html": [ - [ - "/webrtc/rtcpeerconnection/rtcpeerconnection-constructor.html", - {} - ] - ], - "webrtc/rtcpeerconnection/rtcpeerconnection-idl.html": [ - [ - "/webrtc/rtcpeerconnection/rtcpeerconnection-idl.html", - {} - ] - ], - "webrtc/rtcpeerconnection/setRemoteDescription.html": [ - [ - "/webrtc/rtcpeerconnection/setRemoteDescription.html", - {} - ] - ], "webrtc/simplecall.html": [ [ "/webrtc/simplecall.html", @@ -133525,16 +137763,20 @@ } }, "paths": { + "./.codecov.yml": [ + "e2322808739a5977e90896b4755cfc20f4ab2046", + "support" + ], "./.gitignore": [ "a74e35d1ce44dcca7ecb513a8cbd6194fe0f2c58", "support" ], "./.gitmodules": [ - "078f9de776005fb33e6c58bf1aad5deab425ab39", + "525f7d93f00f11086aabc1f652cf06623e21986c", "support" ], "./.travis.yml": [ - "412ca6450f30e77589d7f6aea15d111ccb394b9d", + "d2475341537cf8a63ecb2bc8625dd757647bcc9c", "support" ], "./CONTRIBUTING.md": [ @@ -133550,11 +137792,15 @@ "support" ], "./README.md": [ - "8b7d5a19ca22280bea4475be804faee03bbe237d", + "a00890035c46ef53ab51d51107fde1891265379e", + "support" + ], + "./check_stability.ini": [ + "4ee10945191db8ce3e1d8bfae86bc3f0ad40868f", "support" ], "./check_stability.py": [ - "254d5ca0a4d3228fdb0f5564d7fcbfb53be214ec", + "90a4a7be64ad08f52a3c7a7885cdbef6e11a212e", "support" ], "./ci_built_diff.sh": [ @@ -133569,16 +137815,20 @@ "2d54d770ed8439a93e98961b3105b3248684744d", "support" ], + "./ci_unittest.sh": [ + "5ae19000641227045631083f038dafc92261d403", + "support" + ], "./config.default.json": [ "26f2c0e4aced7e1787adacb36e11c3cbf44bbd48", "support" ], "./lint": [ - "c40fe0907c52a1dd8c20222cf931cf7ae911993b", + "1ea93927bbc5cf570fdd6feefca4f39570b9aa37", "support" ], "./lint.whitelist": [ - "6c978a4331c4d48ae1824dd290f463be29d26598", + "eb36ee69795a6893e3f96a1d26470ea73213eca0", "support" ], "./manifest": [ @@ -133605,6 +137855,14 @@ "c67d3f646e86413722833d2308a9bfc793a916bf", "support" ], + "2dcontext/2x4.png": [ + "690bac789fecf2530b36dd889c68db3bd93ed9fd", + "support" + ], + "2dcontext/4x2.png": [ + "16f72935aaf97175593bcf27794506f0884f091b", + "support" + ], "2dcontext/best-practices/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -134577,6 +138835,22 @@ "30150e3530438d42704fda8b3623286658f6c724", "support" ], + "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14.html": [ + "fa83293cfbdbb67a9d5d27a20ac19ff5d9c46d07", + "reftest" + ], + "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14_ref.html": [ + "0feedb34e5ade7a4e58cb4eb92e2b958a06929fe", + "support" + ], + "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15.html": [ + "b37463cc33b46e9aba5bbe73244fd422ef38406e", + "reftest" + ], + "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15_ref.html": [ + "d6817ddb2ac78b524f7cc80ebd4f348aded4d89f", + "support" + ], "2dcontext/drawing-images-to-the-canvas/drawimage_html_image_1_ref.html": [ "9a70c803aaf5bd8a843b18d6d16779575d4dc6f8", "support" @@ -137702,7 +141976,7 @@ "support" ], "2dcontext/tools/gentestutils.py": [ - "9219d4911c668a1bbe314a66c5d09261bb64ea0a", + "61b25e0406addab477dc133edf87f25052be8a63", "support" ], "2dcontext/tools/name2dir.yaml": [ @@ -138154,11 +142428,11 @@ "testharness" ], "IndexedDB/idb_webworkers.htm": [ - "e57fd8321a437f3b6082c5d75025ad63bd007450", + "8956db4b23f21532383fd5629468fddec6611391", "testharness" ], "IndexedDB/idbcursor-advance-continue-async.htm": [ - "6dbb08d166c7c8c2cd5c918b83bb1b15fad50dce", + "4ed7d1efe3763e8b1e0bb95f529df91c137fa0f5", "testharness" ], "IndexedDB/idbcursor-advance-exception-order.html": [ @@ -138166,11 +142440,11 @@ "testharness" ], "IndexedDB/idbcursor-advance-invalid.htm": [ - "ddb2a1394f4846396f965e60a618f2bde1f57cf9", + "52aa1102409c464e09977d55a35f018a7e3ed390", "testharness" ], "IndexedDB/idbcursor-advance.htm": [ - "7becf54b03320a3b905c4ebfa476476f22409307", + "b7968addaeadd088544c146613f7343cb887f702", "testharness" ], "IndexedDB/idbcursor-continue-exception-order.htm": [ @@ -138178,15 +142452,15 @@ "testharness" ], "IndexedDB/idbcursor-continue.htm": [ - "953ae4b03fcfe2be3652df09577df2e3829dd53a", + "15f5ef0a1e0d396b30c5c8ef740918d69e405507", "testharness" ], "IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm": [ - "85dba064e12f6ee4c7f7a9ab288a8ecb11063298", + "4803def9e592d876f7d5f79d9e5b616d09bbc6f1", "testharness" ], "IndexedDB/idbcursor-continuePrimaryKey-exceptions.htm": [ - "7c2ddb95ce4b7c588ddb2907367a365902eba349", + "1ce0f8e83e296f593aafbd2de72f6437bf9c8b19", "testharness" ], "IndexedDB/idbcursor-continuePrimaryKey.htm": [ @@ -138198,23 +142472,23 @@ "testharness" ], "IndexedDB/idbcursor-direction-index-keyrange.htm": [ - "3b7f8b093301e1eb89d4398c76bd36101490d5e6", + "453d7b510cec23f777924f15919183f6d43849f9", "testharness" ], "IndexedDB/idbcursor-direction-index.htm": [ - "91dde42de3c1511b0cb5f45d9702368c814879bb", + "58e3d34b153e9c415c14db160921364f1765855a", "testharness" ], "IndexedDB/idbcursor-direction-objectstore-keyrange.htm": [ - "7834cd03a20e4e52ce4b55b4966c9c73e0a00301", + "fa5374e9f0cbcbef19b1819449c9e0fd6f87824a", "testharness" ], "IndexedDB/idbcursor-direction-objectstore.htm": [ - "14bda466bc9fb084b76101a9925acdc22cddaa29", + "e09e4f3196aee6ad096f87d1de9dd30521425eaf", "testharness" ], "IndexedDB/idbcursor-direction.htm": [ - "3185189d3b3ca40a908e69c074e68d9474b609c5", + "44f0410fa4997df37a758204e2d446187393ba1b", "testharness" ], "IndexedDB/idbcursor-key.htm": [ @@ -138230,7 +142504,7 @@ "testharness" ], "IndexedDB/idbcursor-source.htm": [ - "0677de106509b9b3f4d1e38780f479d9aaace626", + "e92b1e5ec888594a4b05c695761fd57fea52fd19", "testharness" ], "IndexedDB/idbcursor-update-exception-order.htm": [ @@ -138390,7 +142664,7 @@ "testharness" ], "IndexedDB/idbcursor_iterating.htm": [ - "6d5ed40df4126027ad48876f3d96f039c91b5d6a", + "cc86676b686c6545547ce7f59e140a6027279d5e", "testharness" ], "IndexedDB/idbcursor_iterating_index.htm": [ @@ -138402,11 +142676,11 @@ "testharness" ], "IndexedDB/idbcursor_iterating_objectstore.htm": [ - "79896d7345a47cd134204b79960dd4d38026a679", + "728242c9f1b72b7348c68c2723b25765bab64332", "testharness" ], "IndexedDB/idbcursor_iterating_objectstore2.htm": [ - "afdaeecc80f29426c884c2c852912db957fcdc28", + "811427a853df6d79e671569b87a95e51b3e06070", "testharness" ], "IndexedDB/idbcursor_update_index.htm": [ @@ -138486,11 +142760,11 @@ "testharness" ], "IndexedDB/idbdatabase-transaction-exception-order.html": [ - "8033f0b03f01eb4363291dbc4ef16ae4b66c5bc5", + "c0e6f03eb0169ea46dcf2117ee9f379157c95bf0", "testharness" ], "IndexedDB/idbdatabase_close.htm": [ - "6b0a32c465f735544b89da588bb043bbfbb66230", + "34b8d6cebcd0e5d0e781630b89d52606151df140", "testharness" ], "IndexedDB/idbdatabase_close2.htm": [ @@ -138546,7 +142820,7 @@ "testharness" ], "IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm": [ - "a806d39408f9a8fd9b5d2e623e19075e513d4c37", + "79ee4c1e5ec47887b081c9b3a8e66281023844ba", "testharness" ], "IndexedDB/idbdatabase_deleteObjectStore.htm": [ @@ -138634,11 +142908,11 @@ "testharness" ], "IndexedDB/idbfactory_open10.htm": [ - "580e789cc170cc477ad41a9958766b227e85e02d", + "e4750592975b9c6b4c20db92e617bfe0dad47b9b", "testharness" ], "IndexedDB/idbfactory_open11.htm": [ - "daae03bbc5edf280cf84bb52d77e27d36392c526", + "1ec2c59be1cab46f3466dbb5b29d95048bdd62cf", "testharness" ], "IndexedDB/idbfactory_open12.htm": [ @@ -138650,7 +142924,7 @@ "testharness" ], "IndexedDB/idbfactory_open3.htm": [ - "0abe9c45c058e827689f645a8dd04acf247861ee", + "4b4df0401e63d47e6711dc43f6a51343f7b024bf", "testharness" ], "IndexedDB/idbfactory_open4.htm": [ @@ -138662,11 +142936,11 @@ "testharness" ], "IndexedDB/idbfactory_open6.htm": [ - "35480d3728b630a107e0115656b8db8488779917", + "0715543ef0b2e71913cde6c84024baf6cf9f84dd", "testharness" ], "IndexedDB/idbfactory_open7.htm": [ - "58ecaaea2690baddf916ed848636a6ed8f171670", + "828118b68ad6f80e849bc4dfef245115d6b74f1b", "testharness" ], "IndexedDB/idbfactory_open8.htm": [ @@ -138762,11 +143036,11 @@ "testharness" ], "IndexedDB/idbindex_getAll.html": [ - "68e9f7f0e45fde88f7eceb2b2949e55e828af698", + "c28603db8b1d5941db7bb724d10d66312e77d0ab", "testharness" ], "IndexedDB/idbindex_getAllKeys.html": [ - "2bdca6e57b2b8733d10a5237b6b8b75bb7d9837f", + "16582e1aeb223503b3a5ed06eeb9aa6835997693", "testharness" ], "IndexedDB/idbindex_getKey.htm": [ @@ -138869,6 +143143,10 @@ "6c2fe5ac83765f679fd2572d4ad0d7d30466480d", "testharness" ], + "IndexedDB/idbobjectstore-index-finished.html": [ + "a93dd83fefe202688a8cfbf4d44de6ff5032bc86", + "testharness" + ], "IndexedDB/idbobjectstore-query-exception-order.html": [ "91e12b5c824638c4f46892364ca3572bf5f28cea", "testharness" @@ -139070,11 +143348,11 @@ "testharness" ], "IndexedDB/idbobjectstore_deleteIndex.htm": [ - "37f3a9de39abb19b9c6d524baf28c1379efdaf90", + "05db6e5cb1388765d64bae8310553ad87d2fa0f7", "testharness" ], "IndexedDB/idbobjectstore_deleted.htm": [ - "32ea0d23154b34e009839539cc482209105dec2d", + "b47fa902b979d5c2e270cb196cfd6f2e1d395298", "testharness" ], "IndexedDB/idbobjectstore_get.htm": [ @@ -139106,15 +143384,15 @@ "testharness" ], "IndexedDB/idbobjectstore_getAll.html": [ - "c9387cbe39891986a41d494b64e640f3db28704f", + "3070820db1168a459cf8357f4e7d545084e56334", "testharness" ], "IndexedDB/idbobjectstore_getAllKeys.html": [ - "bfb992f18be3cea8e6febebc22b2a524bfc8cb3a", + "e9f7529ff25900b75aef37edea45b9635802e1b7", "testharness" ], "IndexedDB/idbobjectstore_getKey.html": [ - "76906dde291ad82b93070aef7b1fcecae80adfff", + "d34c54405b817f6eac937532adcc130385c05865", "testharness" ], "IndexedDB/idbobjectstore_index.htm": [ @@ -139126,11 +143404,11 @@ "testharness" ], "IndexedDB/idbobjectstore_openCursor_invalid.htm": [ - "f8bb8abce5872a2543a9a9c85d3b25cc7c9c24d9", + "5457297bc3d408f30d1c9466d0b5d404f6adf473", "testharness" ], "IndexedDB/idbobjectstore_openKeyCursor.htm": [ - "45066f081f2229a16a4ec89ddcee858666651e87", + "fac19308e8e42d2ce3874406b527bb5dd29eba11", "testharness" ], "IndexedDB/idbobjectstore_put.htm": [ @@ -139198,7 +143476,7 @@ "testharness" ], "IndexedDB/idbrequest-onupgradeneeded.htm": [ - "b3b93705a62981706d810ebddaf73f4bee6d1612", + "db880099d6c54ae1168d8b7886680fe2a3332b83", "testharness" ], "IndexedDB/idbrequest_error.html": [ @@ -139213,12 +143491,16 @@ "9c3e4f3e4ec46d222a611a812ef1d670741a9b6b", "testharness" ], + "IndexedDB/idbtransaction-objectStore-finished.html": [ + "1ab1d55b67d1d0fe2a6b90a545a84eb81f1eb89b", + "testharness" + ], "IndexedDB/idbtransaction-oncomplete.htm": [ "c1204c119431395ef705ea01dfd67724db21955a", "testharness" ], "IndexedDB/idbtransaction.htm": [ - "2d058dd87d864ad538d975e7c10e235fca82f74c", + "af3ddcf5367fbcd5d838c29842f6482e1cbcfb49", "testharness" ], "IndexedDB/idbtransaction_abort.htm": [ @@ -139226,7 +143508,7 @@ "testharness" ], "IndexedDB/idbtransaction_objectStoreNames.html": [ - "3a2bb014fe738ebcafc87e449002feec25ae86f6", + "88418b8a79548ed39204153d7110fe7215e20c3d", "testharness" ], "IndexedDB/idbversionchangeevent.htm": [ @@ -139346,7 +143628,7 @@ "support" ], "IndexedDB/support.js": [ - "6544b743611f07c4f6ef2533e9bd0213a23fba07", + "c5634bec710dfbf13898df3100b5982b9d642111", "support" ], "IndexedDB/transaction-abort-generator-revert.html": [ @@ -139466,7 +143748,7 @@ "support" ], "WebCryptoAPI/derive_bits_keys/pbkdf2.js": [ - "f881616857e5f523338f338ffcbded34f1c6b9e9", + "dfd8eea5707720186820549837c8a1a319a8ecc4", "support" ], "WebCryptoAPI/derive_bits_keys/pbkdf2.worker.js": [ @@ -139477,20 +143759,52 @@ "0a073cb726ad239110545eb3cecada2a0ce5daf7", "support" ], - "WebCryptoAPI/derive_bits_keys/test_ecdh_bits.html": [ + "WebCryptoAPI/derive_bits_keys/test_ecdh_bits.https.html": [ "eb82990143fa33de7b62cdacd2db566512d74d44", "testharness" ], - "WebCryptoAPI/derive_bits_keys/test_ecdh_keys.html": [ + "WebCryptoAPI/derive_bits_keys/test_ecdh_keys.https.html": [ "d896626491b4f710970b28d30eb89604034fb8c4", "testharness" ], - "WebCryptoAPI/derive_bits_keys/test_hkdf.html": [ + "WebCryptoAPI/derive_bits_keys/test_hkdf.https.html": [ "6d0def388fed4db1606d03f2cbfd59020bd00c56", "testharness" ], - "WebCryptoAPI/derive_bits_keys/test_pbkdf2.html": [ - "07703342a2b5b80585d541ec47d4633381fd785c", + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_empty.https.html": [ + "48b0c6ac60cc130a5bc109fd43b5b1da74bad6da", + "testharness" + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_long.https.html": [ + "9f28363c1c182c354d688a44249abe3f6c6e9ff5", + "testharness" + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_short.https.html": [ + "2a6b28ee191cc62575872c19a21b402f668cd0d5", + "testharness" + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_empty.https.html": [ + "e1d654a4ccefef12b57ef32388debf5df170e938", + "testharness" + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_long.https.html": [ + "2e3e354fe0b4b96d2429bd6e3b5b702a327d9e84", + "testharness" + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_short.https.html": [ + "b53dd1eb6d350d6546e71e77d829eb3da4fc4c68", + "testharness" + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_empty.https.html": [ + "d36de62c712d53d29aa8cc6995851493d814654f", + "testharness" + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_long.https.html": [ + "518afb29e8f859a793e0e39317c6516aae99fb67", + "testharness" + ], + "WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_short.https.html": [ + "5e776aa3f202bb72a328947983b020f03ba6ec4d", "testharness" ], "WebCryptoAPI/digest/digest.js": [ @@ -139501,7 +143815,7 @@ "a9a6b7a15bf0b795729190a94bdda6ed1ddc013d", "testharness" ], - "WebCryptoAPI/digest/test_digest.html": [ + "WebCryptoAPI/digest/test_digest.https.html": [ "1f5893b2c01a60e1e49b8ba5dee8f3d6507cc604", "testharness" ], @@ -139545,19 +143859,19 @@ "e833d10f83ac5cff26e076371a545d60a8d37b8f", "support" ], - "WebCryptoAPI/encrypt_decrypt/test_aes_cbc.html": [ + "WebCryptoAPI/encrypt_decrypt/test_aes_cbc.https.html": [ "f79d96aaa96347302cf08c641c5064b9dc2e974c", "testharness" ], - "WebCryptoAPI/encrypt_decrypt/test_aes_ctr.html": [ + "WebCryptoAPI/encrypt_decrypt/test_aes_ctr.https.html": [ "a3d4d1e4ea38587d170f583061d58ce02224d81e", "testharness" ], - "WebCryptoAPI/encrypt_decrypt/test_aes_gcm.html": [ + "WebCryptoAPI/encrypt_decrypt/test_aes_gcm.https.html": [ "f545fb559442624770696da2addb489cb5534530", "testharness" ], - "WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.html": [ + "WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.https.html": [ "4905875dd185403d093361afb8e75bef50ce0c34", "testharness" ], @@ -139610,7 +143924,7 @@ "testharness" ], "WebCryptoAPI/generateKey/successes.js": [ - "a048156c0d724a735093a6f1209c8fed8281ffd1", + "9623250b44a270bd23f6d892e8a8296351fac708", "support" ], "WebCryptoAPI/generateKey/successes.worker.js": [ @@ -139657,99 +143971,95 @@ "b9e9790245742b8eeb4af7679cc0144710380c07", "testharness" ], - "WebCryptoAPI/generateKey/test_aes-cbc.html": [ + "WebCryptoAPI/generateKey/test_aes-cbc.https.html": [ "9c92564d0b64784bded21d3c337da125da1c0225", "testharness" ], - "WebCryptoAPI/generateKey/test_aes-ctr.html": [ + "WebCryptoAPI/generateKey/test_aes-ctr.https.html": [ "3804433a5bd2c382c8bd9afbd1b41792d9f927c1", "testharness" ], - "WebCryptoAPI/generateKey/test_failures.html": [ + "WebCryptoAPI/generateKey/test_failures.https.html": [ "a1458bc27b594b9051bfbb7e537aebe2c95b6859", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_AES-CBC.html": [ + "WebCryptoAPI/generateKey/test_failures_AES-CBC.https.html": [ "bf4b12efa09c2602bed73b4ae2b94ebdf5bf9749", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_AES-CTR.html": [ + "WebCryptoAPI/generateKey/test_failures_AES-CTR.https.html": [ "2d33a87c30f30d76e547cb6e4b9637292c2e7b6e", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_AES-GCM.html": [ + "WebCryptoAPI/generateKey/test_failures_AES-GCM.https.html": [ "aaeb0182a48f680fd7f421a8ba7efa29561ad7fb", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_AES-KW.html": [ + "WebCryptoAPI/generateKey/test_failures_AES-KW.https.html": [ "4dc9d4cff709a8a84569f6fc6eb2225a59fe8db4", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_ECDH.html": [ + "WebCryptoAPI/generateKey/test_failures_ECDH.https.html": [ "6eca49b0a06e1c468c28dffab3435cf14972095c", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_ECDSA.html": [ + "WebCryptoAPI/generateKey/test_failures_ECDSA.https.html": [ "decb88cd07b2ef2f2c07d1a1fd8e7dfc46e22350", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_HMAC.html": [ + "WebCryptoAPI/generateKey/test_failures_HMAC.https.html": [ "ffd768d80a38ae9e9ae029c3372a227681b020dd", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_RSA-OAEP.html": [ + "WebCryptoAPI/generateKey/test_failures_RSA-OAEP.https.html": [ "ea5fab99e5fdc1b4232aa4c9eed96657f64b1e67", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_RSA-PSS.html": [ + "WebCryptoAPI/generateKey/test_failures_RSA-PSS.https.html": [ "1e03b7b789b75bb25e3491fe8bcfc198dd53b46d", "testharness" ], - "WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.html": [ + "WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.https.html": [ "749e526a3f67c246a328a99abd4c1da728571413", "testharness" ], - "WebCryptoAPI/generateKey/test_successes.html": [ - "6dd8fd836361a4c02c602149fbde996d0131607a", - "testharness" - ], - "WebCryptoAPI/generateKey/test_successes_AES-CBC.html": [ + "WebCryptoAPI/generateKey/test_successes_AES-CBC.https.html": [ "e8ee3bdfb8aef171d6db35cc69a482f1a992d089", "testharness" ], - "WebCryptoAPI/generateKey/test_successes_AES-CTR.html": [ + "WebCryptoAPI/generateKey/test_successes_AES-CTR.https.html": [ "07f55a63a2327ee8804548ba5e802fcdba09010e", "testharness" ], - "WebCryptoAPI/generateKey/test_successes_AES-GCM.html": [ + "WebCryptoAPI/generateKey/test_successes_AES-GCM.https.html": [ "ebec06754972d621026a4284c316c882be362dc3", "testharness" ], - "WebCryptoAPI/generateKey/test_successes_AES-KW.html": [ + "WebCryptoAPI/generateKey/test_successes_AES-KW.https.html": [ "e76258a60418fb1467d16a17b4e01da1d99bd036", "testharness" ], - "WebCryptoAPI/generateKey/test_successes_ECDH.html": [ + "WebCryptoAPI/generateKey/test_successes_ECDH.https.html": [ "b2b7d0a233473a51e67a760638abf1f532d1232b", "testharness" ], - "WebCryptoAPI/generateKey/test_successes_ECDSA.html": [ + "WebCryptoAPI/generateKey/test_successes_ECDSA.https.html": [ "c21190c7c74eb856a9fce3a4913723b46fa1887a", "testharness" ], - "WebCryptoAPI/generateKey/test_successes_HMAC.html": [ + "WebCryptoAPI/generateKey/test_successes_HMAC.https.html": [ "ccfe6cefe42764a46dd817046b026034be033e97", "testharness" ], - "WebCryptoAPI/generateKey/test_successes_RSA-OAEP.html": [ - "7ebe1df33a5df5f5a2cead014af5502246b6b833", + "WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html": [ + "04b89d631e81fd7822049c8513984c3af3711efd", "testharness" ], - "WebCryptoAPI/generateKey/test_successes_RSA-PSS.html": [ + "WebCryptoAPI/generateKey/test_successes_RSA-PSS.https.html": [ "623370ae56918c14ac14f40fb057327b0844be04", "testharness" ], - "WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.html": [ + "WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.https.html": [ "ad5db5278bef55d9ae2336961c226199a4c94446", "testharness" ], @@ -139761,6 +144071,10 @@ "52b5381311cc0e2595d251273e054fa826de9765", "testharness" ], + "WebCryptoAPI/idlharness.https.html": [ + "52b5381311cc0e2595d251273e054fa826de9765", + "testharness" + ], "WebCryptoAPI/idlharness.worker.js": [ "e3478f4259364d773dab9ca5e0c7194a0b78d5b3", "testharness" @@ -139789,18 +144103,26 @@ "e9d9758d0478ecdf93a5fda9f196501e992de614", "testharness" ], - "WebCryptoAPI/import_export/test_ec_importKey.html": [ + "WebCryptoAPI/import_export/test_ec_importKey.https.html": [ "2c173849dd35c551b71983fb8efc20f650599da2", "testharness" ], - "WebCryptoAPI/import_export/test_rsa_importKey.html": [ + "WebCryptoAPI/import_export/test_rsa_importKey.https.html": [ "d12cf20829eace56868a7b40d38e75aca89932a6", "testharness" ], - "WebCryptoAPI/import_export/test_symmetric_importKey.html": [ + "WebCryptoAPI/import_export/test_symmetric_importKey.https.html": [ "a69847f41e437363676a4ced439faba50ce85e5d", "testharness" ], + "WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html": [ + "e219b5ee2c878779562aded462bfcaa7ad81b63d", + "testharness" + ], + "WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html": [ + "4df3813485b7277571d61ce38a5811729f91ddbe", + "testharness" + ], "WebCryptoAPI/sign_verify/ecdsa.js": [ "55c99894ea3ba9186de1082c189f37f77dfe12e1", "support" @@ -139845,19 +144167,19 @@ "766e1f95031b3f9f3dd5d0e3de8c70f5fdf5ac30", "support" ], - "WebCryptoAPI/sign_verify/test_ecdsa.html": [ + "WebCryptoAPI/sign_verify/test_ecdsa.https.html": [ "969eb4e062dfb91e40be42d4980f0d0e464d5b34", "testharness" ], - "WebCryptoAPI/sign_verify/test_hmac.html": [ + "WebCryptoAPI/sign_verify/test_hmac.https.html": [ "cd105449c7b9b75aa91ee0848fdca5bda78a1aae", "testharness" ], - "WebCryptoAPI/sign_verify/test_rsa_pkcs.html": [ + "WebCryptoAPI/sign_verify/test_rsa_pkcs.https.html": [ "d7840d0a6d848510bf547d64c8b197761f39e05e", "testharness" ], - "WebCryptoAPI/sign_verify/test_rsa_pss.html": [ + "WebCryptoAPI/sign_verify/test_rsa_pss.https.html": [ "408e1a081caa23f7e717128e94eb5cfeae9bac30", "testharness" ], @@ -139866,10 +144188,14 @@ "support" ], "WebCryptoAPI/util/helpers.js": [ - "6bf895ea91bfc92cb346f96af777bc9b8a0af0ee", + "76bfa10171fb405f321d015b4394a2a929d587dd", "support" ], - "WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.html": [ + "WebCryptoAPI/util/worker-report-crypto-subtle-presence.js": [ + "4aacae51744fa0284ebc89c43084c4dae873e5c1", + "support" + ], + "WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.https.html": [ "2f0070bafc5079f3b70dd8da567fde0ea6bfb113", "testharness" ], @@ -139910,13 +144236,21 @@ "testharness" ], "WebIDL/ecmascript-binding/has-instance.html": [ - "4266bf65ad4dd3dd2acaf7b8e0d18e8999f8252b", + "8df0ec18a02041106df53ccc3168261d29ab7943", "testharness" ], "WebIDL/ecmascript-binding/interface-object.html": [ "f68be23702792cb5236e608bf6e8421a9a851fb8", "testharness" ], + "WebIDL/ecmascript-binding/interface-prototype-object.html": [ + "13d2a9dbbd0d78e240c2b88d548f88ba41184e5f", + "testharness" + ], + "WebIDL/ecmascript-binding/legacy-callback-interface-object.html": [ + "4eac8c853a0627577d2bd96ed76c45bd187a5734", + "testharness" + ], "WebIDL/invalid/idl/enum.widl": [ "cebcfcecfe4b09a4d3ea15e766e9b13044dfe0b8", "support" @@ -140506,7 +144840,7 @@ "testharness" ], "XMLHttpRequest/formdata-foreach.html": [ - "0de3e65e068a59180ba03c67ce70e4db8f0bbd87", + "ac4bcf3c043dec99e2feeaeff828ead2db1e9606", "testharness" ], "XMLHttpRequest/formdata-get.htm": [ @@ -140546,7 +144880,7 @@ "testharness" ], "XMLHttpRequest/getresponseheader-chunked-trailer.htm": [ - "ead9af29dd6ece455b2df24367b26f63a991991f", + "37043cc8d180a405eb150b39e2caa5f4f5a0a9c3", "testharness" ], "XMLHttpRequest/getresponseheader-cookies-and-more.htm": [ @@ -140578,7 +144912,7 @@ "testharness" ], "XMLHttpRequest/interfaces.html": [ - "b65e817345a4410c2062242bef57031d4ff448b7", + "a4c597d2bdb85e37ffe5f5ebba961d7f8a3aeb29", "testharness" ], "XMLHttpRequest/loadstart-and-state.html": [ @@ -141517,60 +145851,52 @@ "b960bef807da94c0146ed2f537eaa1e05ec9a0ab", "testharness" ], + "accelerometer/Accelerometer.https.html": [ + "cb802e1f9df53ef6e8e3a34daf54f9e02b019383", + "testharness" + ], + "accelerometer/Accelerometer_insecure_context.html": [ + "62c0fdfe1ee0752956b4c68e877cd7f47ac887a1", + "testharness" + ], + "accelerometer/Accelerometer_onerror-manual.https.html": [ + "e03faad7d297ce2c5d6fefa66a2397c3d9a32e2d", + "manual" + ], "accelerometer/OWNERS": [ "36770a71443523aa2f91f9958ba24066f0b4dcec", "support" ], "accelerometer/idlharness.https.html": [ - "c7d55e65051d370f6a225ae7def35270144fed95", + "eedb225d9e8a05d528e62cc2d689dbfe36858052", "testharness" ], - "ambient-light/AmbientLightSensor.js": [ - "8313b3b63892b2dba96c17ff2fb4c4f5ae107efe", + "accelerometer/support-iframe.html": [ + "5782b270802060f88a1842c2393fb7d18c8c75a8", "support" ], - "ambient-light/AmbientLightSensor_browsing_context.https.html": [ - "2bff26861bbb67c58af6bbb6105bbcd57ac35b6d", + "ambient-light/AmbientLightSensor.https.html": [ + "3bc1a9bbc660ec9ee83f65914c35a52201eccb4b", "testharness" ], "ambient-light/AmbientLightSensor_insecure_context.html": [ - "c546291fd11aeb2e23dd0a68ea02511babedcb7a", - "testharness" - ], - "ambient-light/AmbientLightSensor_onchange.https.html": [ - "b0dae1e2c22f35a0e97dc63529750bc0242e67b3", + "9267bca8016bdde90ba2e5e866e9989db7c045dd", "testharness" ], "ambient-light/AmbientLightSensor_onerror-manual.https.html": [ - "9bbd4281bbab2a1b1a1c34600b0b3d5ea6b99e62", + "fa52072d6da7987db8f67c2a6fd9b2e281f03042", "manual" ], - "ambient-light/AmbientLightSensor_reading.https.html": [ - "36ffed0f2be6b280123a91e8d60740b6a7a95e5d", - "testharness" - ], - "ambient-light/AmbientLightSensor_start.https.html": [ - "b81065b401d4063b2fae2daaec4e7f53da3419ab", - "testharness" - ], - "ambient-light/AmbientLightSensor_stop.https.html": [ - "1068f563e1fe0d7595248086856ea3f3547cf221", - "testharness" - ], - "ambient-light/AmbientLightSensor_tests.html": [ - "1f90699129c27a5a5581a3cd989e097220e54620", - "testharness" - ], "ambient-light/OWNERS": [ "72539a05ddcce7467524b36255696565a2c484e8", "support" ], "ambient-light/idlharness.https.html": [ - "6fa24c2a71228917e83cfb2e44945c466c004959", + "0c0f48d162d3ef69b8fe1486a99cc315fab5ab31", "testharness" ], "ambient-light/support-iframe.html": [ - "ea1cdae3e30c279501483a6680bce50006879da5", + "62024c4c0cff6fb5a21a6db62cd9756de0a2f479", "support" ], "annotation-model/.editorconfig": [ @@ -143569,6 +147895,14 @@ "6c3b89b55e603f7a3556e0c9760c03d270755036", "support" ], + "apng/animated-png-timeout-ref.html": [ + "dcd3c58b9200109868f2b98bda346bf26f823e07", + "support" + ], + "apng/animated-png-timeout.html": [ + "b9ba0287c92e5dbda1dc207ab45e9c90e8618878", + "reftest" + ], "app-uri/OWNERS": [ "e28f77cc2634a830fd6e144e22d9d217e5949b37", "support" @@ -143661,10 +147995,6 @@ "314d421a5544db277664bb55bd04b87e9ed2fdba", "support" ], - "auxclick/auxclick_event-manual.html": [ - "464073435190f51b2725653a0a0589e10f136d2d", - "manual" - ], "background-fetch/OWNERS": [ "0c4e22b970a92b2d77b0f50cc27c2d46aad0b43b", "support" @@ -143777,8 +148107,12 @@ "e70503e7fb71617b9be631d5f2a9e73cacd83e3f", "support" ], + "bluetooth/OWNERS": [ + "ef497e5da8691971c612980bb94eae44fc17c509", + "support" + ], "bluetooth/idl-Bluetooth.html": [ - "cfe60f252017491dc85a00b1eb028fb3fe893c42", + "5d4d8278b1f24798765974c35777f70fcbfc9cfa", "testharness" ], "clear-site-data/navigation.html": [ @@ -143794,7 +148128,7 @@ "support" ], "clipboard/OWNERS": [ - "7c5c92bcb47be9151914d709e2b792a122f07a6e", + "bae753666bda85e9805a5e2fad80ba71459b8aba", "support" ], "common/OWNERS": [ @@ -143805,6 +148139,10 @@ "0516e849d40a16e82e1bb800372df28ed802aa8d", "support" ], + "common/PrefixedPostMessage.js": [ + "2a2e37640bd0089be111d96eeed0b311753e0234", + "support" + ], "common/blank.html": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -143865,6 +148203,14 @@ "a575b8135e6ddb1501fc2a082d7544ee86011b7d", "support" ], + "common/object-association.js": [ + "c6955b7bbf00d73ec5959678391aa59d36da8321", + "support" + ], + "common/performance-timeline-utils.js": [ + "0616ad8871126af7a74ff6937f3f7c623adcbd3e", + "support" + ], "common/redirect-opt-in.py": [ "70caa012fa7b91e20b7a08e3708097d1c1da44a3", "support" @@ -162786,7 +167132,7 @@ "support" ], "content-security-policy/child-src/child-src-allowed.sub.html": [ - "d67e0efa99e43d7be6da5b22c64c0b151001f0b7", + "8e70e19dbaffa7ca6b45b84b860eb11e343ce630", "testharness" ], "content-security-policy/child-src/child-src-allowed.sub.html.sub.headers": [ @@ -162794,7 +167140,7 @@ "support" ], "content-security-policy/child-src/child-src-blocked.sub.html": [ - "b70869e8f1ef02ca477849a776e5cada34a07288", + "19fd649af944749546aee5af41fc2b4d7f135aed", "testharness" ], "content-security-policy/child-src/child-src-blocked.sub.html.sub.headers": [ @@ -162802,7 +167148,7 @@ "support" ], "content-security-policy/child-src/child-src-conflicting-frame-src.sub.html": [ - "a080e3439a0852dbc594ef6d7a7d88e43ad7b09d", + "8c903c4be2ccb11bdaff13fc3ae8690fe04ba755", "testharness" ], "content-security-policy/child-src/child-src-conflicting-frame-src.sub.html.sub.headers": [ @@ -162810,29 +167156,29 @@ "support" ], "content-security-policy/child-src/child-src-cross-origin-load.sub.html": [ - "af56668d75e5ad0b0d51aa24cd66bcadeadd4cb6", + "51bbb0f02e67722433604c78f54a8619cb498dc0", "testharness" ], "content-security-policy/child-src/child-src-cross-origin-load.sub.html.sub.headers": [ "a7b058f47360dee56f92e6caa3cc5eab1dc3706f", "support" ], - "content-security-policy/child-src/child-src-worker-allowed.sub.html": [ - "578f3824687a9fbb2aa7f14bf2a9e8230398bace", + "content-security-policy/child-src/child-src-redirect-blocked.sub.html": [ + "1d7108c31df11379c79181a21a37822a5137fa73", "testharness" ], - "content-security-policy/child-src/child-src-worker-allowed.sub.html.sub.headers": [ - "08ace362a5648dd3375a47fd5081663a2658ba4d", + "content-security-policy/child-src/child-src-redirect-blocked.sub.html.sub.headers": [ + "268d2bc1c16366626596649ea24b776609849f9e", "support" ], + "content-security-policy/child-src/child-src-worker-allowed.sub.html": [ + "da18b70d2f859c83f1599e5f65bfeb67d1183ee4", + "testharness" + ], "content-security-policy/child-src/child-src-worker-blocked.sub.html": [ - "67cea32ca1b0cf32b20b53044b41bbdaad543721", + "16fc87d40c7466de1b59674abc4510c29c7d8cd2", "testharness" ], - "content-security-policy/child-src/child-src-worker-blocked.sub.html.sub.headers": [ - "8d64a8dd0cd9a115342f0ab27ccc4c5eeefd5200", - "support" - ], "content-security-policy/connect-src/connect-src-beacon-blocked.sub.html": [ "0965458e1d32dacec7a9379a7f0e484277389398", "testharness" @@ -162853,8 +167199,12 @@ "70aeb617f5d580917b385346ba629e035f062c32", "testharness" ], + "content-security-policy/embedded-enforcement/embedding_csp-header-invalid-format.html": [ + "3747c23fd624aefa80c2906095084e843843f3d8", + "testharness" + ], "content-security-policy/embedded-enforcement/embedding_csp-header.html": [ - "f3df200f0162d3e9a1cc2d944b3a821126105d59", + "3a9f255c0b99f7750fe487ae6e68063954184d05", "testharness" ], "content-security-policy/embedded-enforcement/iframe-csp-attribute.html": [ @@ -162945,80 +167295,172 @@ "888d3e58d3d094b767067e16494803af432ee057", "testharness" ], - "content-security-policy/frame-ancestors/deep-allows-none.sub.html": [ - "d23db3fa139be3bc1c5b82676f3a8f425c40f9ed", + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-none-block.html": [ + "e96b19c03463de925f03a666a173e948c0908302", "testharness" ], - "content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html": [ - "d9c576acb4ccae793afd83bd0b3d4cbe0040a2c4", - "support" - ], - "content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html.headers": [ - "33033f27634749dc56a2b6f3b08a7a127b422013", - "support" - ], - "content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html": [ - "1d5a4c537f8189b75a1caacdbbac5ba912f257d2", - "support" - ], - "content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html.headers": [ - "02b7f7088d6a2bcd97108c12586bd8ec28cc256b", - "support" - ], - "content-security-policy/frame-ancestors/multiple-frames-meta-ignored.sub.html": [ - "0c5c46e42deb18e0fd296137f64392da6afab2eb", + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block.html": [ + "816ef071086019d9abed995370cb39a8542f3322", "testharness" ], - "content-security-policy/frame-ancestors/multiple-frames-one-blocked.sub.html": [ - "fb6f8e23e5b32547c861e5e735ce68be306589fc", + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-star-allow.html": [ + "ecaa1cfb71b73c1ec55cdf7d8eb1058469897807", "testharness" ], - "content-security-policy/frame-ancestors/multiple-frames-self-allowed.sub.html": [ - "27b683b95dcb4f08c79c135c3558c7c26f0f600e", + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-allow.html": [ + "928e1285169b1d137550f67c083c6ba4eb532b6c", "testharness" ], - "content-security-policy/frame-ancestors/nested-traversing-allowed.sub.html": [ - "29f8bdb4197d807aabe50a98b2701b3785a336b5", + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-block.html": [ + "46a056e57129f76eabf6b53b833a24b1a861ed91", "testharness" ], - "content-security-policy/frame-ancestors/nested-traversing-banned-top-is-self.sub.html": [ - "ea3b49d5e380f1a99dd632e339b4eae8e2426095", + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-none-block.html": [ + "486eaffb8f7c9e28861adeef5e2af6777be73ee6", "testharness" ], - "content-security-policy/frame-ancestors/nested-traversing-banned.sub.html": [ - "d7ccb938da839e1d2190cabc1682f1f2fb1ed412", + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-self-block.html": [ + "9c40ca204dae2de593f46b723dc7e6bfa8f8e8fd", "testharness" ], - "content-security-policy/frame-ancestors/reporting-frame-allows-none-meta.html": [ - "4b8a46a45417a77b64d4b6f6d74033da0b170236", + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-star-allow.html": [ + "03ea8e9bd6c19aff4ceac59b178b1ef065afeedc", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow.html": [ + "f7a44723534d82a650cf8853d6cb114b46f1b535", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-block.html": [ + "37ead57a4f508fd817541ecb2b2576b7fe65532f", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-sandboxed-cross-url-block.html": [ + "4aee1e3833591c74694a3c960bd32c1047a8546f", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-none-block.html": [ + "2a831ff6c6a9b0a7c63b427105a077ffedbb46e1", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-self-block.html": [ + "332a0a289180b90d14bdb1f4b13c8225b9a810f5", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-star-allow.html": [ + "c8f8c077f2c8d5c55926dc03b084651313806240", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-allow.html": [ + "d8aa43dbab2fd38dd1b7b3ac004dddbf20b3a247", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block.html": [ + "e3ab2ece1d6db2be49a25a0f46c98d3fd07fa1e7", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-none-block.html": [ + "035865df4a43600910890fed3856fadaf05fd7b7", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-self-allow.html": [ + "79e712e18213a4eb754dc32c32ca864fbb2e4a9f", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-star-allow.html": [ + "ccec99fbc0f7dc7d0b0dcab855ab0d128eee2414", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-allow.html": [ + "c5d24d65811915fff1fafff89f29c6287abaf6d8", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-block.html": [ + "c6d7b2b67f933e00feadefa00263cc3b17443395", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-none-block.html": [ + "b5d0f5f0923f8c1e3400d91f6194f665d7a30a97", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-overrides-xfo.html": [ + "53ecb1ec56471ef236ca760437f16ed758c539f8", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-self-allow.html": [ + "635dd6a6ae1cc8f51fad8b9c0cdcaf7d2b8322b4", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-self-block.html": [ + "31b16e7e4c7113ec27cba6c0b880b2472fbc174b", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-star-allow-crossorigin.html": [ + "6af460fa2c57111abbc8f3ceeb09b31993821b22", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-star-allow-sameorigin.html": [ + "cf1d2e99cca0ca2bd4582f903eba3d585bcf91ce", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-url-allow.sub.html": [ + "e0921d30fdb2e9739497849133e93d49486cd417", + "testharness" + ], + "content-security-policy/frame-ancestors/frame-ancestors-url-block.html": [ + "f7b54ddb5688e4706d078538af1f16f2b82d3375", + "testharness" + ], + "content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html": [ + "2d370eb5855e59d75e3cd6658632dc8f69a35f3c", "support" ], - "content-security-policy/frame-ancestors/reporting-frame-allows-none.html": [ - "0b918917b5d811cf5099ac12348e47536b3e68df", + "content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html.sub.headers": [ + "48593d685ee69fd82565cf4c85c73ebc89309208", "support" ], - "content-security-policy/frame-ancestors/reporting-frame-allows-none.html.headers": [ - "5cfa9dcd8b15e16c44de2de76890b1ff08d85eb4", + "content-security-policy/frame-ancestors/support/frame-ancestors-test.sub.js": [ + "4dde1455ac8238da8c93cadfe7e2b544240d79a7", "support" ], - "content-security-policy/frame-ancestors/reporting-frame-allows-self.html": [ - "e88d74699b1a7b82369803ba2f27e6dee827258d", + "content-security-policy/frame-ancestors/support/frame-ancestors.sub.html": [ + "5e797157ef603dbdb9c3b3637d2a372c5d984433", "support" ], - "content-security-policy/frame-ancestors/reporting-frame-allows-self.html.headers": [ - "33033f27634749dc56a2b6f3b08a7a127b422013", + "content-security-policy/frame-ancestors/support/frame-ancestors.sub.html.sub.headers": [ + "3894c3bffcd450e30dcb7e04141e929ae9a522e9", "support" ], - "content-security-policy/frame-ancestors/single-frame-self-allowed.sub.html": [ - "b1f0ad6923b1078392704c198463fd259a82e974", + "content-security-policy/frame-ancestors/support/frame-in-frame.sub.html": [ + "22b75d559bd9a62619ca7c970c139775e6da7f48", + "support" + ], + "content-security-policy/frame-ancestors/support/frame-in-frame.sub.html.sub.headers": [ + "51e1354d16cfa4967e91206be8bd0d8c6ca577af", + "support" + ], + "content-security-policy/frame-src/frame-src-redirect.html": [ + "16ac0d81d039fc2514b72a68fa491159ad46f59c", "testharness" ], + "content-security-policy/frame-src/frame-src-redirect.html.headers": [ + "3df52b9299a0ada67d3211c5190269fa8b046211", + "support" + ], + "content-security-policy/frame-src/support/frame.html": [ + "3f5fd74f92250b09f2dd790d154ade7bc4748d78", + "support" + ], + "content-security-policy/frame-src/support/testharness-helper.sub.js": [ + "c11acf3aff5ffaf1a581ff8c73f077b7c0ee0a26", + "support" + ], "content-security-policy/generic/fail-0_1.js": [ "357bbab837dcc2794a46fb07e31ea49b16b447cf", "support" ], "content-security-policy/generic/generic-0_1-img-src.html": [ - "0af19ad686c41332aa090ba3cfe240ecd9f990ff", + "b9e456586e6acc8f56864ab36bea8c9ff67b3959", "testharness" ], "content-security-policy/generic/generic-0_1-img-src.html.sub.headers": [ @@ -163026,7 +167468,7 @@ "support" ], "content-security-policy/generic/generic-0_1-script-src.html": [ - "cb2a8523a7519c3b0458f726aa97bca08ac92c3c", + "d1d01090fb8ae7f33357d0d4d75e2606d637a881", "testharness" ], "content-security-policy/generic/generic-0_1-script-src.html.sub.headers": [ @@ -163309,6 +167751,18 @@ "91c932641750d0b053ca8ff8bc5d102025c3fdc9", "support" ], + "content-security-policy/script-src/crossoriginScript.js": [ + "982c87aacdeb92f948ce54283e989b0210835ca8", + "support" + ], + "content-security-policy/script-src/crossoriginScript.js.headers": [ + "90d51a5e46cc58404dd5ec1e9e4e10934a6c0707", + "support" + ], + "content-security-policy/script-src/externalScript.js": [ + "9747ab396294e301c0f0720a3c0731d92272ee54", + "support" + ], "content-security-policy/script-src/inlineSuccessTest.js": [ "a591a02337841f6e8e822174a390a723ee6a3656", "support" @@ -163389,6 +167843,14 @@ "4c2700452b8e0cb5451ee00aaa8ff92f12e9623e", "support" ], + "content-security-policy/script-src/script-src-sri_hash.sub.html": [ + "c720b6a69726026ea34545b94bcdc7cef443c453", + "testharness" + ], + "content-security-policy/script-src/script-src-sri_hash.sub.html.sub.headers": [ + "40b849448eb8f0ec56795ca51b0813b3159a01a9", + "support" + ], "content-security-policy/script-src/script-src-strict_dynamic_and_unsafe_eval_eval.html": [ "36d44f22b3f4ae8a26509613426b76cdd3d1a41f", "testharness" @@ -163517,6 +167979,10 @@ "a50a792b1ef19fe452196e5e50036d6de01dc6e5", "support" ], + "content-security-policy/script-src/script-src-strict_dynamic_worker.https.html": [ + "a59f7f33614eb541a216b317f0916271f359ba1b", + "testharness" + ], "content-security-policy/script-src/simpleSourcedScript.js": [ "549c6ea1f1bae2b78f933b5da0a5f2f72bae2564", "support" @@ -163533,6 +167999,14 @@ "5f2ff4a87aa476168cf3d13b10a8d81a387b8e42", "testharness" ], + "content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html": [ + "e338e94ea726419db64ed5b98c95b862c394409e", + "testharness" + ], + "content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html.headers": [ + "960ee8a9f7ccf33ea435890e2eae0e68399f32ed", + "support" + ], "content-security-policy/securitypolicyviolation/inside-dedicated-worker.html": [ "46d18c97d554716b714856c00bdc49388d211868", "testharness" @@ -163585,10 +168059,22 @@ "ac19897e2693ba3228640d03c770cd5a33c51381", "support" ], + "content-security-policy/securitypolicyviolation/support/testharness-helper.sub.js": [ + "71244cc74fa8f8ee8082c876264e053348905fbd", + "support" + ], "content-security-policy/securitypolicyviolation/targeting.html": [ "36ec8dd9ef0bd1be3615913015d857aa1a7c9e97", "testharness" ], + "content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html": [ + "ec7ce3c14a571eae99473dd595a39c2019ba9e36", + "testharness" + ], + "content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html.headers": [ + "6e15d48ddd21d1bbb9603081d5d7fef98ebfa106", + "support" + ], "content-security-policy/style-src/resources/style-src-import.sub.css": [ "37de4f39b0399d9a5a230b5446883f9e4b49a061", "support" @@ -163745,6 +168231,18 @@ "071616b3c0e43fab0b7a214000389585dafc393d", "support" ], + "content-security-policy/support/post-message.js": [ + "c957a15a1c7a0c5dffc9e7a13d54da243ca9a93a", + "support" + ], + "content-security-policy/support/postmessage-fail.html": [ + "5ccfe2ec548aa6e16649c319c8252e608777fe64", + "support" + ], + "content-security-policy/support/postmessage-pass.html": [ + "ddfde964afded9ff5189c8c7554bcb2b1b1e5938", + "support" + ], "content-security-policy/support/report.py": [ "8cd779a8017cba678a565475271b892e8ed53e58", "support" @@ -163773,6 +168271,10 @@ "ad81dd10fd77548004d7808bf176b89fe6002fa4", "support" ], + "content-security-policy/svg/object-in-svg-foreignobject.sub.html": [ + "a16c20b420126d3b910f429707aca671562e7939", + "testharness" + ], "content-security-policy/svg/scripted.svg": [ "e5a26ca493e75cb4245e9f0de986cde3ab697d62", "support" @@ -163918,7 +168420,7 @@ "support" ], "cors/allow-headers.htm": [ - "7152e6c95f03ce5bec3fb85473ea800b949ca935", + "e28cf5812e58e490ec28bb407c4575f3d33687dc", "testharness" ], "cors/basic.htm": [ @@ -163934,7 +168436,7 @@ "testharness" ], "cors/origin.htm": [ - "56eb70e8dcb45b72fd16150810c59e43b6abc2de", + "4fd804db576f22f4afc4ebc9f339341969322dbb", "testharness" ], "cors/preflight-cache.htm": [ @@ -163966,7 +168468,7 @@ "testharness" ], "cors/request-headers.htm": [ - "d5166a2dc96a5742c5320b9a61d6e75650a9d49d", + "56de3a6d1f3e96750f35cc2cacbdbb9b13e32f3f", "testharness" ], "cors/resources/.gitignore": [ @@ -164029,6 +168531,18 @@ "8307ed240a531033c96da89197dcfb5ea25cde87", "support" ], + "credential-management/idl.https.html": [ + "c9664273f5786aae604f86c136197e0ee5270a71", + "testharness" + ], + "css-font-loading/fontfacesetloadevent-constructor.html": [ + "ad355c3d5220c1b938182241a8e8abe030ace699", + "testharness" + ], + "css-paint-api/OWNERS": [ + "0c1517f7ba747014c7c091b61d48f11421ed91c2", + "support" + ], "css-timing-1/OWNERS": [ "7c9899aa9065ffe6e1206b630124d4939ae53c8f", "support" @@ -164945,24 +169459,72 @@ "538b95863c061da60e95c1a61ef9dc93da007aa4", "testharness" ], + "cssom-view/CaretPosition-001.html": [ + "182826b894852721a2efa7eaa0a3437904f13dbc", + "testharness" + ], "cssom-view/HTMLBody-ScrollArea_quirksmode.html": [ "cfe4e07fb9efa140a55175d3cf50ceaced93e1c9", "testharness" ], + "cssom-view/MediaQueryList-001.html": [ + "4b209fa18eda5f0c50639357e9851de28e545cf7", + "testharness" + ], "cssom-view/MediaQueryList-with-empty-string.html": [ "034fd2a3b8da32d4b2ef0465fe4361c424c6ad3d", "testharness" ], "cssom-view/OWNERS": [ - "c9aad9e1cbfa2cf07f24daf4ff61718696f8d1bd", + "083538f652edfeea9bde3d5d9f56667bc3773f6a", "support" ], + "cssom-view/Screen-pixelDepth-Screen-colorDepth001.html": [ + "256c4441e6f933c058065c2bea85d37acaa67a6f", + "testharness" + ], + "cssom-view/cssom-getBoundingClientRect-001.html": [ + "7118495560adadebcca98e6add47a74669f87788", + "testharness" + ], + "cssom-view/cssom-getBoundingClientRect-002.html": [ + "8dfaa313b4abad30281d07ce22ac06a61754cc06", + "testharness" + ], + "cssom-view/cssom-getClientRects.html": [ + "f4e750bc1267f5c519a513ef1f25bf3660365788", + "testharness" + ], + "cssom-view/cssom-view-img-attributes-001.html": [ + "d645ca84f24755ba4f583e47a42422fb1eaadbb9", + "testharness" + ], + "cssom-view/cssom-view-window-screen-interface.html": [ + "8fb3e3327f8f657e2215c91c75f49fd739c15c57", + "testharness" + ], + "cssom-view/cssom-view/media-query-list-interface.xht": [ + "62f0fdd48d1a4194d439ee22829b3346bed9a154", + "testharness" + ], + "cssom-view/cssom-view/window-interface.xht": [ + "4d8c4ddb997d85ca2c971602a3096f57565c01eb", + "testharness" + ], + "cssom-view/elementFromPoint-001.html": [ + "bf1c490777f450275a95ecfc6d6d2c0d055aca82", + "testharness" + ], "cssom-view/elementFromPoint.html": [ "e22ae99aa1fba51807aec245b810db5d584ac037", "testharness" ], + "cssom-view/elementFromPosition.html": [ + "d90dff8b15ec2977f341a7add9c7d627b62d9d0f", + "testharness" + ], "cssom-view/elementScroll.html": [ - "5471dca08aae9d446c487d40853957e9290677f3", + "24c65428976fc4971a33368e6bf6f8b77199d69b", "testharness" ], "cssom-view/elementsFromPoint.html": [ @@ -164973,10 +169535,22 @@ "1d88b7050e61c06aae97c42251401e1d6acb7f06", "testharness" ], + "cssom-view/htmlelement-offset-width-001.html": [ + "071bcc0320577077bc6768921f28e33e892ccd9a", + "testharness" + ], "cssom-view/iframe.html": [ "81c8e70138fc30d0954d9de692ee396310586c7f", "support" ], + "cssom-view/matchMedia.xht": [ + "3330cf1603555d50d097cdc584cf1c193c8b32d3", + "testharness" + ], + "cssom-view/matchMediaAddListener.html": [ + "ec5b756e980676c8707bcb2d7d91b7c977158e0d", + "testharness" + ], "cssom-view/mouseEvent.html": [ "d64c45f021a5c6db7b65575288a91e28a25a2982", "testharness" @@ -164985,14 +169559,230 @@ "ad44e3f4ba132bfb4a522b14a4ff5356dbbbad14", "testharness" ], + "cssom-view/offsetParent_element_test.html": [ + "6e7579de7add0162ac99f3326f070bbd6051932b", + "testharness" + ], + "cssom-view/scrollWidthHeight.xht": [ + "06ec592720f3db3c04cdd792177179b11a097a23", + "testharness" + ], + "cssom-view/scrollWidthHeightWhenNotScrollable.xht": [ + "dfac20693a9d2bcbc74e372177b1a04472de8f8f", + "testharness" + ], "cssom-view/scrolling-no-browsing-context.html": [ "1b504d68ded5e70043da04e89b77342585144f4b", "testharness" ], + "cssom-view/scrolling-quirks-vs-nonquirks.html": [ + "a799c737e7962865c3ed3e380a664cafe97dcfe8", + "testharness" + ], "cssom-view/scrollingElement.html": [ "e3bc7ab9a646c1275e5dab9394df97d72ef8a42e", "testharness" ], + "cssom-view/support/1x1-green.png": [ + "51e7b6974a09eda6cb31337717c5eaeb9c44b443", + "support" + ], + "cssom-view/support/1x1-lime.png": [ + "b040eb633a35c0648ad72a2902361faf25bc419d", + "support" + ], + "cssom-view/support/1x1-maroon.png": [ + "f78757e5ebe897bd618d100718385c84e00f2369", + "support" + ], + "cssom-view/support/1x1-navy.png": [ + "a3fd80b2c79866fd343e18eef5a51ed6e835e53e", + "support" + ], + "cssom-view/support/1x1-red.png": [ + "b8da86921d04ba42f42b0a60b03c5c2172f58c2b", + "support" + ], + "cssom-view/support/1x1-white.png": [ + "71b246439f915ad21c7d39414d9f85c8ed73b4ca", + "support" + ], + "cssom-view/support/60x60-gg-rr.png": [ + "e4843d42a26189132e1bdd53e8618521330baeca", + "support" + ], + "cssom-view/support/60x60-green.png": [ + "2f8eb2409b0a18e0bff90725ec7eedc16e7be448", + "support" + ], + "cssom-view/support/60x60-red.png": [ + "415b835abaaab822aab11880354296e7356bbb0a", + "support" + ], + "cssom-view/support/README": [ + "c46bfcee920aef0b9167764ec78c699ed217c8f2", + "support" + ], + "cssom-view/support/a-green.css": [ + "a9716c222274ba868bfd06c05e28cb7762d93245", + "support" + ], + "cssom-view/support/b-green.css": [ + "eb78a4d12f35b4249051826ea000c53d04df80b7", + "support" + ], + "cssom-view/support/c-red.css": [ + "dc288b7aa49b57e0abf803741e78582ba5ceffdb", + "support" + ], + "cssom-view/support/cat.png": [ + "461fd17b274662b88500cdf42bab7f3b79e6019d", + "support" + ], + "cssom-view/support/import-green.css": [ + "db4f420efdb292d6520be1a3bf052ed3f6f9e7e3", + "support" + ], + "cssom-view/support/import-red.css": [ + "0f2b9133fcfa22d5506a5cee307bd1a4d50e87e9", + "support" + ], + "cssom-view/support/pattern-grg-rgr-grg.png": [ + "cfb6ecc271c296c69b133a81f350a777b608bea4", + "support" + ], + "cssom-view/support/pattern-grg-rrg-rgg.png": [ + "27080d4df556f59d4b501e03f2847bd9da5756a9", + "support" + ], + "cssom-view/support/pattern-rgr-grg-rgr.png": [ + "c100a35c361205932c506f1b3399753b91e4c45e", + "support" + ], + "cssom-view/support/pattern-tr.png": [ + "c1e687deee7b79ae091f2b42c4f6cff430076444", + "support" + ], + "cssom-view/support/ruler-h-50%.png": [ + "9364be82a07500d6684a275174bcf5185444cb52", + "support" + ], + "cssom-view/support/ruler-h-50px.png": [ + "b3d7cc680b20a5fc44ea93f7df6d33894bc7b09b", + "support" + ], + "cssom-view/support/ruler-v-100px.png": [ + "d8b49696edb2bd614e9c00f96e7862798b6e621f", + "support" + ], + "cssom-view/support/ruler-v-50px.png": [ + "eb299dc261ec04c8f2c11afb6f7a1c2ec147587b", + "support" + ], + "cssom-view/support/square-purple.png": [ + "ef0619128f22e05920930420b7d96f91f860d904", + "support" + ], + "cssom-view/support/square-teal.png": [ + "92efae44b710cf1ddd9ba96e593dae03fb2519c4", + "support" + ], + "cssom-view/support/square-white.png": [ + "2f93fcc1462ba32b9b7899e5e78c869e529e68ee", + "support" + ], + "cssom-view/support/support/README": [ + "18698bf71d328054eba0b473486058bc9286c1a4", + "support" + ], + "cssom-view/support/support/swatch-green.png": [ + "eedea3e9a99c18f5fc2de3796be2c6f9da2ea07d", + "support" + ], + "cssom-view/support/support/swatch-red.png": [ + "c51a03a807743f59e3027371ccfbd8e80235a485", + "support" + ], + "cssom-view/support/swatch-blue.png": [ + "e79958e10feeeed3db88dee9bae9ea80055593c5", + "support" + ], + "cssom-view/support/swatch-green.png": [ + "c51a03a807743f59e3027371ccfbd8e80235a485", + "support" + ], + "cssom-view/support/swatch-lime.png": [ + "ee2cc3dcd6d8dda7c0e4ef3bbc7e63c74118211d", + "support" + ], + "cssom-view/support/swatch-orange.png": [ + "10768a5177b772013e628c7397ae64725057295d", + "support" + ], + "cssom-view/support/swatch-red.png": [ + "eedea3e9a99c18f5fc2de3796be2c6f9da2ea07d", + "support" + ], + "cssom-view/support/swatch-teal.png": [ + "994cd98028aff20822f2dca5a6058fb616bf5ce4", + "support" + ], + "cssom-view/support/swatch-white.png": [ + "5bccb1922de065e551d7d106e6493bb91040f3da", + "support" + ], + "cssom-view/support/swatch-yellow.png": [ + "9cc73897c2e1fc45f5224d81d02a6b87bf72b1fa", + "support" + ], + "cssom-view/support/test-bl.png": [ + "16e4eaa4864c10e72433e575f59c9b67763fe06a", + "support" + ], + "cssom-view/support/test-br.png": [ + "37f65e7a21d9b9b2daa508f193b8f665c58a1ce9", + "support" + ], + "cssom-view/support/test-inner-half-size.png": [ + "4ed63dd2bb54a8efc166719e00e1e27406b0ee59", + "support" + ], + "cssom-view/support/test-outer.png": [ + "a0b8dfa40065b27f1d939ce0aab39ada3933c574", + "support" + ], + "cssom-view/support/test-tl.png": [ + "956e5156fd8c0e75b1c0f3b8b3b900b653663f74", + "support" + ], + "cssom-view/support/test-tr.png": [ + "078e1dd6dd61d36cec239ed75d02051f61fe60a5", + "support" + ], + "cssom-view/ttwf-js-cssomview-getclientrects-length.html": [ + "7f3440e65abbe692e3c28f1f1d04671054ecc815", + "testharness" + ], + "cssom-view/ttwf-scrollintoview.html": [ + "55d874f53db3c8ed03fff063584eecbcda10d2ce", + "testharness" + ], + "cssom-view/window-screen-height-immutable.html": [ + "3193a200624217a260e17660006e9ce31a52814c", + "testharness" + ], + "cssom-view/window-screen-height.html": [ + "c5b24034e81ae8be76d66c7097092e8ce801a622", + "testharness" + ], + "cssom-view/window-screen-width-immutable.html": [ + "b44c4dead8c8779521f3f6983823cdc6cfab75b5", + "testharness" + ], + "cssom-view/window-screen-width.html": [ + "a3529271f75eecb40da8ec1975202d8aa07b5d4a", + "testharness" + ], "cssom/CSS.html": [ "2c55d573bbd90f5ca3e564131ae697b547e4a43c", "testharness" @@ -165002,7 +169792,7 @@ "testharness" ], "cssom/CSSKeyframesRule.html": [ - "3efb8e5cef257a0b433192742d526709357b24c7", + "bca997a63c1389ef6d14aac2f32ab770fbd15ec4", "testharness" ], "cssom/CSSNamespaceRule.html": [ @@ -165014,7 +169804,7 @@ "testharness" ], "cssom/CSSStyleRule.html": [ - "f5767d7b9e7e32ad3b74b316e02f16ec625fa7e5", + "b7cfe3da8454d5c64a25c440e0776c80d8c3a751", "testharness" ], "cssom/CSSStyleSheet.html": [ @@ -165025,10 +169815,66 @@ "21d9e43514fb3a7fbf8933429242dc544224ef24", "testharness" ], + "cssom/MediaList.xhtml": [ + "277ec40d3a64d9881e594901a6bcdcd6b70405db", + "testharness" + ], + "cssom/OWNERS": [ + "504fa320d984433da43ab370215ecc2ee29ef66d", + "support" + ], "cssom/StyleSheetList.html": [ "3a0e6f64f70f863d679e537c4bfb76aaa0d3598a", "testharness" ], + "cssom/computed-style-001.html": [ + "a940a84552ddcd716af743e0e8746c7582b5c760", + "testharness" + ], + "cssom/css-style-attribute-modifications.html": [ + "9199534f3b6cc473832562b1701ade3a05dde172", + "testharness" + ], + "cssom/css-style-declaration-modifications.html": [ + "c169d758c1d91b75697b04cf72750f8ac1650e1a", + "testharness" + ], + "cssom/cssimportrule.html": [ + "da36c32a7ecad7542c73572917709ee394dc843c", + "testharness" + ], + "cssom/cssom-cssText-serialize.html": [ + "66ad91da39c1e1da9021f6443e9b6d34baf57dcb", + "testharness" + ], + "cssom/cssom-cssstyledeclaration-set.html": [ + "12f5dce3d37a718ac5c872f662cc9f3d9cf09179", + "testharness" + ], + "cssom/cssom-fontfacerule-constructors.html": [ + "c064661df74571d374f49a693f3263fcf138e670", + "testharness" + ], + "cssom/cssom-fontfacerule.html": [ + "965a8f6289fa5c6e34bfd447de3b8ef86573fea1", + "testharness" + ], + "cssom/cssom-setProperty-shorthand.html": [ + "14c752e5dbeab2d58983d53aceab08519379bf0f", + "testharness" + ], + "cssom/cssstyledeclaration-csstext.html": [ + "aa2adbfcc58f3a844e2e1f2c96e5efed2c81f2c3", + "testharness" + ], + "cssom/cssstyledeclaration-mutability.html": [ + "5f29436964d01c57f61d513cee5b83281643ac54", + "testharness" + ], + "cssom/escape.html": [ + "c9ed57c7ef7a035c25feff4ea60547a57d727f31", + "testharness" + ], "cssom/getComputedStyle-pseudo.html": [ "6c74e57a2e32a13cc3b7e955a2d89dafdf6d1730", "testharness" @@ -165037,22 +169883,78 @@ "2c78218b89efb9bdf60cf708920be142051347c7", "testharness" ], + "cssom/index-001.html": [ + "ab9e9f102f5909d9b5587f2c0ea54c0c6b59868d", + "testharness" + ], + "cssom/index-002.html": [ + "fe12bc0005ccfccfafd4f23644b28fbb5f5e33d1", + "testharness" + ], + "cssom/index-003.html": [ + "f55d9bc5b2e25b1af5169ecc164f62b6a95abfe5", + "testharness" + ], + "cssom/inline-style-001.html": [ + "377c8610bc597d47a93f70a9cf95b3c7657d8319", + "testharness" + ], + "cssom/interfaces.html": [ + "5876c88acd95d18166fdd049bdb3f09cdde4eb3f", + "testharness" + ], + "cssom/medialist-interfaces-001.html": [ + "dfaea262508d72d123006409174e3e21832a305f", + "testharness" + ], + "cssom/medialist-interfaces-002.html": [ + "114fac94342afe2e7fe432a67c4b0bbf03d24bc4", + "testharness" + ], + "cssom/medialist-interfaces-003.html": [ + "b9ddd611cc585202b1e76382666b04197af334b0", + "testharness" + ], + "cssom/medialist-interfaces-004.html": [ + "e3cdc88670ca46b3752fd8118d94dae2cc95258d", + "testharness" + ], "cssom/overflow-serialization.html": [ "199039706289f577652b968706fc1251398acd1c", "testharness" ], + "cssom/selectorSerialize.html": [ + "002777c7c598eb1131ab625365ee3fe08650e830", + "testharness" + ], "cssom/serialization-CSSDeclaration-with-important.html": [ "ecc8b95fb2d71cacee271f4fea2fc16f35cdba57", "testharness" ], + "cssom/serialize-namespaced-type-selectors.html": [ + "51f6a0c4a0c693338245409c60784f1a73fafb76", + "testharness" + ], "cssom/serialize-values.html": [ "329fe02cb9e54b1a24a8f9dedcfcf5c0f61c7f24", "testharness" ], + "cssom/serialize-variable-reference.html": [ + "5e83f084efc82184c3052a40bb4a061fd4a1336f", + "testharness" + ], "cssom/shorthand-serialization.html": [ "bd514834dbd48c267c16a4329af6fec7f6cbc081", "testharness" ], + "cssom/style-sheet-interfaces-001.html": [ + "15509e87505d5a22d4f6dbbffcc90c24fcee642a", + "testharness" + ], + "cssom/style-sheet-interfaces-002.html": [ + "875598ca4271d4adaa11fbb01981b290e6235019", + "testharness" + ], "cssom/stylesheet-same-origin.css": [ "268fb9a72d33b3d18bbb82aaaac48bb15c89a88e", "support" @@ -165061,6 +169963,194 @@ "719c525b1af3b6b46dfeeb0627034d799bab50b5", "testharness" ], + "cssom/support/1x1-green.png": [ + "51e7b6974a09eda6cb31337717c5eaeb9c44b443", + "support" + ], + "cssom/support/1x1-lime.png": [ + "b040eb633a35c0648ad72a2902361faf25bc419d", + "support" + ], + "cssom/support/1x1-maroon.png": [ + "f78757e5ebe897bd618d100718385c84e00f2369", + "support" + ], + "cssom/support/1x1-navy.png": [ + "a3fd80b2c79866fd343e18eef5a51ed6e835e53e", + "support" + ], + "cssom/support/1x1-red.png": [ + "b8da86921d04ba42f42b0a60b03c5c2172f58c2b", + "support" + ], + "cssom/support/1x1-white.png": [ + "71b246439f915ad21c7d39414d9f85c8ed73b4ca", + "support" + ], + "cssom/support/60x60-gg-rr.png": [ + "e4843d42a26189132e1bdd53e8618521330baeca", + "support" + ], + "cssom/support/60x60-green.png": [ + "2f8eb2409b0a18e0bff90725ec7eedc16e7be448", + "support" + ], + "cssom/support/60x60-red.png": [ + "415b835abaaab822aab11880354296e7356bbb0a", + "support" + ], + "cssom/support/README": [ + "c46bfcee920aef0b9167764ec78c699ed217c8f2", + "support" + ], + "cssom/support/a-green.css": [ + "a9716c222274ba868bfd06c05e28cb7762d93245", + "support" + ], + "cssom/support/b-green.css": [ + "eb78a4d12f35b4249051826ea000c53d04df80b7", + "support" + ], + "cssom/support/c-red.css": [ + "dc288b7aa49b57e0abf803741e78582ba5ceffdb", + "support" + ], + "cssom/support/cat.png": [ + "461fd17b274662b88500cdf42bab7f3b79e6019d", + "support" + ], + "cssom/support/import-green.css": [ + "db4f420efdb292d6520be1a3bf052ed3f6f9e7e3", + "support" + ], + "cssom/support/import-red.css": [ + "0f2b9133fcfa22d5506a5cee307bd1a4d50e87e9", + "support" + ], + "cssom/support/pattern-grg-rgr-grg.png": [ + "cfb6ecc271c296c69b133a81f350a777b608bea4", + "support" + ], + "cssom/support/pattern-grg-rrg-rgg.png": [ + "27080d4df556f59d4b501e03f2847bd9da5756a9", + "support" + ], + "cssom/support/pattern-rgr-grg-rgr.png": [ + "c100a35c361205932c506f1b3399753b91e4c45e", + "support" + ], + "cssom/support/pattern-tr.png": [ + "c1e687deee7b79ae091f2b42c4f6cff430076444", + "support" + ], + "cssom/support/ruler-h-50%.png": [ + "9364be82a07500d6684a275174bcf5185444cb52", + "support" + ], + "cssom/support/ruler-h-50px.png": [ + "b3d7cc680b20a5fc44ea93f7df6d33894bc7b09b", + "support" + ], + "cssom/support/ruler-v-100px.png": [ + "d8b49696edb2bd614e9c00f96e7862798b6e621f", + "support" + ], + "cssom/support/ruler-v-50px.png": [ + "eb299dc261ec04c8f2c11afb6f7a1c2ec147587b", + "support" + ], + "cssom/support/square-purple.png": [ + "ef0619128f22e05920930420b7d96f91f860d904", + "support" + ], + "cssom/support/square-teal.png": [ + "92efae44b710cf1ddd9ba96e593dae03fb2519c4", + "support" + ], + "cssom/support/square-white.png": [ + "2f93fcc1462ba32b9b7899e5e78c869e529e68ee", + "support" + ], + "cssom/support/support/README": [ + "18698bf71d328054eba0b473486058bc9286c1a4", + "support" + ], + "cssom/support/support/swatch-green.png": [ + "eedea3e9a99c18f5fc2de3796be2c6f9da2ea07d", + "support" + ], + "cssom/support/support/swatch-red.png": [ + "c51a03a807743f59e3027371ccfbd8e80235a485", + "support" + ], + "cssom/support/swatch-blue.png": [ + "e79958e10feeeed3db88dee9bae9ea80055593c5", + "support" + ], + "cssom/support/swatch-green.png": [ + "c51a03a807743f59e3027371ccfbd8e80235a485", + "support" + ], + "cssom/support/swatch-lime.png": [ + "ee2cc3dcd6d8dda7c0e4ef3bbc7e63c74118211d", + "support" + ], + "cssom/support/swatch-orange.png": [ + "10768a5177b772013e628c7397ae64725057295d", + "support" + ], + "cssom/support/swatch-red.png": [ + "eedea3e9a99c18f5fc2de3796be2c6f9da2ea07d", + "support" + ], + "cssom/support/swatch-teal.png": [ + "994cd98028aff20822f2dca5a6058fb616bf5ce4", + "support" + ], + "cssom/support/swatch-white.png": [ + "5bccb1922de065e551d7d106e6493bb91040f3da", + "support" + ], + "cssom/support/swatch-yellow.png": [ + "9cc73897c2e1fc45f5224d81d02a6b87bf72b1fa", + "support" + ], + "cssom/support/test-bl.png": [ + "16e4eaa4864c10e72433e575f59c9b67763fe06a", + "support" + ], + "cssom/support/test-br.png": [ + "37f65e7a21d9b9b2daa508f193b8f665c58a1ce9", + "support" + ], + "cssom/support/test-inner-half-size.png": [ + "4ed63dd2bb54a8efc166719e00e1e27406b0ee59", + "support" + ], + "cssom/support/test-outer.png": [ + "a0b8dfa40065b27f1d939ce0aab39ada3933c574", + "support" + ], + "cssom/support/test-tl.png": [ + "956e5156fd8c0e75b1c0f3b8b3b900b653663f74", + "support" + ], + "cssom/support/test-tr.png": [ + "078e1dd6dd61d36cec239ed75d02051f61fe60a5", + "support" + ], + "cssom/ttwf-cssom-doc-ext-load-count.html": [ + "800db5cd4f7342d8c4e5309d4035182ce42f7251", + "testharness" + ], + "cssom/ttwf-cssom-doc-ext-load-tree-order.html": [ + "cae6e4133be602bb4eb134f32d8a12ae53d35011", + "testharness" + ], + "cssom/ttwf-cssom-document-extension.html": [ + "0c1c8fb977b24bb3b5ca33051b32932f36f5a960", + "testharness" + ], "cssom/variable-names.html": [ "5ab67b9e86fd700a556d153898c2896448cc1759", "testharness" @@ -165101,6 +170191,10 @@ "724060b276a1f3254fd226e329631005ec5a5e87", "testharness" ], + "custom-elements/custom-element-registry/per-global.html": [ + "3b143f80d77a0b15b59cc6e6f5344f85dafe4f4e", + "testharness" + ], "custom-elements/disconnected-callbacks.html": [ "ad030517981b11892126023bc758b7fe323a3d14", "testharness" @@ -165109,6 +170203,10 @@ "11b7927c9a2946c752f56e5b44cfb4051ab8b6d6", "testharness" ], + "custom-elements/microtasks-and-constructors.html": [ + "088fcd47e328e30c6119a37bbf19768e7f14763d", + "testharness" + ], "custom-elements/parser/parser-constructs-custom-element-in-document-write.html": [ "b338f193a803ea679bbf0e041f71daf1e6d703f6", "testharness" @@ -165369,12 +170467,12 @@ "7574493bd02c0586f61424de2e2f3f337f67f270", "support" ], - "docs/_writing-tests/idlharness.html": [ - "2d127308c9dbb03c3e4a69964511b5e1a0e12030", + "docs/_writing-tests/idlharness.md": [ + "9f908f014553757d12fb91626a31a8312ec75bc5", "support" ], "docs/_writing-tests/index.md": [ - "0001b10cca68edee0d438bc99fea3b7599f7666f", + "8ef1c49c0692116968994e66483a318f6f40f5d3", "support" ], "docs/_writing-tests/lint-tool.md": [ @@ -165401,12 +170499,12 @@ "62747b6d0328445778050f3e4d6ec46dbdc3a18c", "support" ], - "docs/_writing-tests/testharness-api.html": [ - "fad99e6c6946066568e605a8ac6de7e2e49ac148", + "docs/_writing-tests/testharness-api.md": [ + "9c4484ec7a6053d4d745c6aac6cca821b1de982e", "support" ], "docs/_writing-tests/testharness.md": [ - "150d8638cff4e28c06014dbc0e7e9d9ef150c096", + "154bd922b6f50ec003280616381522a24faffb14", "support" ], "docs/_writing-tests/visual.md": [ @@ -165414,7 +170512,7 @@ "support" ], "docs/assets/_reftest_graph_example.dot": [ - "5fb97d276ed847bc271376dc6c068f57c067d790", + "bc8ebc09e30ff18994b32aa9e5ea43334c276ade", "support" ], "docs/assets/commit-directly.png": [ @@ -165442,7 +170540,7 @@ "support" ], "docs/assets/main.scss": [ - "427cae125889f51bef386097f0127e948f02652e", + "a0f4501b19a64a73c1037e2843a49060c4659bc9", "support" ], "docs/assets/menu.js": [ @@ -165670,7 +170768,7 @@ "support" ], "dom/events/EventListener-invoke-legacy.html": [ - "5c047e994f2bcb971918b42760c70cea7176abcb", + "e56b332acb454ab76964b78588536777946ddff8", "testharness" ], "dom/events/EventListenerOptions-capture.html": [ @@ -165702,7 +170800,7 @@ "testharness" ], "dom/interfaces.html": [ - "0cbf5532f442fdb9ba773fd053f8831b7b522767", + "f8eb7f5fcfdc9ca4a500d5e43855a24a169c81cf", "testharness" ], "dom/lists/DOMTokenList-Iterable.html": [ @@ -166130,7 +171228,7 @@ "support" ], "dom/nodes/Document-createEvent.html": [ - "00da7c85dab7a6f6414d4c58205ac501be0c588d", + "9274ffffe1b08dee78b64ffc70582957f0386bca", "testharness" ], "dom/nodes/Document-createEvent.js": [ @@ -166262,7 +171360,7 @@ "testharness" ], "dom/nodes/Element-classlist.html": [ - "7e3b68e65468fba0708f4084a9b2f6af93edde90", + "c197df35960b77a7794eed10a1a927867a6658f4", "testharness" ], "dom/nodes/Element-closest.html": [ @@ -166566,11 +171664,11 @@ "support" ], "dom/nodes/ParentNode-querySelector-All-xht.xht": [ - "ad28a6ca45cc102865b170dac5a9837a09ad5563", + "5469b8ad07ecbb07d5ca46d82c71aa4e470a5c2e", "testharness" ], "dom/nodes/ParentNode-querySelector-All.html": [ - "c94c9d2b9d84260e9ef7ae36a77ffceaaf18fad1", + "83baf7fa751b086622742908845c7a4db2e65fcb", "testharness" ], "dom/nodes/ParentNode-querySelector-All.js": [ @@ -166602,7 +171700,7 @@ "testharness" ], "dom/nodes/attributes.html": [ - "2e68d3bc430dcd87b826327ead2f8b89c0abdef6", + "cddff48a942168622772069ca2b2bcf0318deed4", "testharness" ], "dom/nodes/attributes.js": [ @@ -166758,7 +171856,7 @@ "testharness" ], "dom/nodes/mutationobservers.js": [ - "cbbccd9dc0cc4003feb6a4db7087590d5df9d6c5", + "595d6f555e03c0158c24448bf2bf35a3684a61fb", "support" ], "dom/nodes/prepend-on-Document.html": [ @@ -166778,7 +171876,7 @@ "testharness" ], "dom/nodes/selectors.js": [ - "019ceba60eaa07690fa3922995f53e65725d7f95", + "da3b97296a9fec2838a2cf1f5506893416627802", "support" ], "dom/ranges/Range-attributes.html": [ @@ -167122,13 +172220,169 @@ "support" ], "dpub-aam/OWNERS": [ - "16577d2283b826f0541dbc795177c7aac7e1b228", + "3a6002295ea2893ba74763e46965bd2d1291d55b", "support" ], "dpub-aam/README.md": [ "4b90a271f1ae6bfe28684797085ed59b2471b0f3", "support" ], + "dpub-aam/doc-abstract-manual.html": [ + "fe8331812ca78bf742f1563c9cf7064da331ccf0", + "manual" + ], + "dpub-aam/doc-acknowledgments-manual.html": [ + "e68c8ea6a948c3f205d497ee8c6841d94828d9f8", + "manual" + ], + "dpub-aam/doc-afterword-manual.html": [ + "ed57486061061270041d5e65ca37ef1e39fe85e2", + "manual" + ], + "dpub-aam/doc-appendix-manual.html": [ + "f2e9a80d2f2cd6c9824e963ab228ad3a30f00f46", + "manual" + ], + "dpub-aam/doc-backlink-manual.html": [ + "72ebb0d9564345dba613c3289492311dceebf0b7", + "manual" + ], + "dpub-aam/doc-biblioentry-manual.html": [ + "b555d4e67a81e405230ebee7f029fb7fed35b144", + "manual" + ], + "dpub-aam/doc-bibliography-manual.html": [ + "8b308c46bc7eb6acd380db88275c0a3247d2f5c2", + "manual" + ], + "dpub-aam/doc-biblioref-manual.html": [ + "ba578575a6f7eb5df31c797d562a19fd605b217d", + "manual" + ], + "dpub-aam/doc-chapter-manual.html": [ + "67bddab5b1f3941762d6cabc88276a059de8cf1e", + "manual" + ], + "dpub-aam/doc-colophon-manual.html": [ + "ec67cf4526e2fe95458456d2f333ca2f96786da6", + "manual" + ], + "dpub-aam/doc-conclusion-manual.html": [ + "7ca5220cf1d18aa933ccfb450c46b3a87d13a408", + "manual" + ], + "dpub-aam/doc-cover-manual.html": [ + "30b3b74ec46b54d2a0f737b50615eccbdb3b0f77", + "manual" + ], + "dpub-aam/doc-credit-manual.html": [ + "fe3df9e65f66333d0c30931cfdca4ca21db9d61d", + "manual" + ], + "dpub-aam/doc-credits-manual.html": [ + "6f745becf88d11ae3789095e64e82f94c0e4c8d6", + "manual" + ], + "dpub-aam/doc-dedication-manual.html": [ + "2ef98622fcbc67ec5cc21203a34a039a46da099c", + "manual" + ], + "dpub-aam/doc-endnote-manual.html": [ + "35661dfe5a8d5858eb9d065b8784cdcb4403ca82", + "manual" + ], + "dpub-aam/doc-endnotes-manual.html": [ + "fbff613b4b56d10d3708f3432656fb572683519d", + "manual" + ], + "dpub-aam/doc-epigraph-manual.html": [ + "3face4bf002fffcfddc54c34d3356b68fd0a1f2a", + "manual" + ], + "dpub-aam/doc-epilogue-manual.html": [ + "30be563ad8db5f7dddf67c757b68880014613b3c", + "manual" + ], + "dpub-aam/doc-errata-manual.html": [ + "879af14b31d9f5c71bb2db81ffcbfa81506624a6", + "manual" + ], + "dpub-aam/doc-example-manual.html": [ + "f4ee8cbc92b43ed64c9c44a316835dd55af03c47", + "manual" + ], + "dpub-aam/doc-footnote-manual.html": [ + "9d87bc526843a679b6ae23e4968fc3536524e779", + "manual" + ], + "dpub-aam/doc-foreword-manual.html": [ + "b88e137197d29800eb4a61fb2a095afe733c9f2b", + "manual" + ], + "dpub-aam/doc-glossary-manual.html": [ + "e0425c1f2617e57d441cfd8e560cf843da6eec05", + "manual" + ], + "dpub-aam/doc-glossref-manual.html": [ + "3564f0d21197da092b85e67b5f074fe66e45b871", + "manual" + ], + "dpub-aam/doc-index-manual.html": [ + "3a8e036535af7ee05e481ebd591492816df8d579", + "manual" + ], + "dpub-aam/doc-introduction-manual.html": [ + "00203fb91611439b8a0a3e950034f017c74ae4fb", + "manual" + ], + "dpub-aam/doc-noteref-manual.html": [ + "4052b204d1c9a9012870c783143daf56b35d2419", + "manual" + ], + "dpub-aam/doc-notice-manual.html": [ + "bea225fc2799e3616f291dee95644e6f265b1f18", + "manual" + ], + "dpub-aam/doc-pagebreak-manual.html": [ + "532f20e099dafe407ef3a52cd28ec75d161f4b7d", + "manual" + ], + "dpub-aam/doc-pagelist-manual.html": [ + "a231e2b6c5ca4c43e7c556ee0371b2b73950aaf8", + "manual" + ], + "dpub-aam/doc-part-manual.html": [ + "20473300cc7f5e0b39e32e7ffd8d0b9f88d76f81", + "manual" + ], + "dpub-aam/doc-preface-manual.html": [ + "be32f3d679eddf85a0698a9aa4f1f3e7311af5da", + "manual" + ], + "dpub-aam/doc-prologue-manual.html": [ + "5d29ba8e083b516d21e3d0a98f279c923ec44b94", + "manual" + ], + "dpub-aam/doc-pullquote-manual.html": [ + "17de6c30ef2940f54f72c547a5dc2436f8fd28e5", + "manual" + ], + "dpub-aam/doc-qna-manual.html": [ + "036d2764e6cf7664d12df86dfbcb603f024e0074", + "manual" + ], + "dpub-aam/doc-subtitle-manual.html": [ + "34eb597cea221ad5340b975916710f9456d71edb", + "manual" + ], + "dpub-aam/doc-tip-manual.html": [ + "73bda654beb49cf9772f9e532a8458a0ced124ac", + "manual" + ], + "dpub-aam/doc-toc-manual.html": [ + "6db9d04c7697ae5b34c687f20b379aad5551b59c", + "manual" + ], "dpub-aria/.editorconfig": [ "18e9e31b4beb20bcfa5ad281584d816204a3f531", "support" @@ -167153,136 +172407,140 @@ "faf2706da35ec626faa833c0498ef1e356584d27", "support" ], + "editing/data/README.md": [ + "f6eade04ca964b7f9adbb4246734433014442175", + "support" + ], "editing/data/backcolor.js": [ - "a988f4c9e1ee5aa5c1ef1159b4b8b9c260bc8272", + "61761a49890c5b955929e655b53ad0587eec8e91", "support" ], "editing/data/bold.js": [ - "42c827538938e385a2c0f33e7fcbf26820fad74c", + "0022a155aba2db8619b5625b45960746d3d8d1ee", "support" ], "editing/data/createlink.js": [ - "3fd0f1356c1036f83f4151790dc3d989b47b7b6a", + "95f3043ab22e5a804483bd8505f140865ecde088", "support" ], "editing/data/delete.js": [ - "fef65beefeb76d9fdafd9afbb0fc70a9de3a61f5", + "7af419763d9e8354361a109645da610099cf97b7", "support" ], "editing/data/fontname.js": [ - "c436324c10eb0b76cae3bb6d162776e8af62ac91", + "b4ffcc3be199393827079bf73dd7433d810e2466", "support" ], "editing/data/fontsize.js": [ - "0a1a242603bea5199a334843f33a7bc757423ea1", + "7077999cd649765a09ca16d843a7cd780eaaa1a8", "support" ], "editing/data/forecolor.js": [ - "4704c7d76160f9fca158bdbe2d84117706aaadd2", + "531d9fd219aec6c36231a1927e234a9ea6f5009b", "support" ], "editing/data/formatblock.js": [ - "7ec42b88c07ea41a37ee890bdc9ac5730f5edbb5", + "d4cadc6257aa75a7dc85c0c258f5b884e23a620c", "support" ], "editing/data/forwarddelete.js": [ - "f6495290991e83aa0438e100d1ad8286f44b00b3", + "1836be2c6f827de512381e9556e99de6cad165d6", "support" ], "editing/data/hilitecolor.js": [ - "bcf7e39416f394bf2120b04ccb3edaeca7b7f863", + "8901795b4f4cde2f59d616764870b93220366180", "support" ], "editing/data/indent.js": [ - "10bb2567852a40d480785cd147a0f5cbe888d19b", + "821cc4fefcfce96832c1a4547698801b554ae426", "support" ], "editing/data/inserthorizontalrule.js": [ - "a65609ebe407670a94a2ff59ed62ea4c2a3e1080", + "118414ee839b94b9a747e0dfd2068d728c171db7", "support" ], "editing/data/inserthtml.js": [ - "8e8c02364a0f5ff7bff12a5446c9896fca5e6886", + "3e853e0b406e4441a2326468b4e21c5b6ffc1c98", "support" ], "editing/data/insertimage.js": [ - "c2e2ad08ea335bb3be59d99de96132366f446eda", + "19f38b05e1694ecb8e26aea374c2b7cd3b2a2467", "support" ], "editing/data/insertlinebreak.js": [ - "fd09fb1a5c1f24f53b9a896c073dc3eed5d8cfd5", + "ba0a0f2eda2703c742dd71b3106a3c78da27e677", "support" ], "editing/data/insertorderedlist.js": [ - "99217ac94529676adc19b8a49460becf92a9d7c4", + "9387d479a52fd5146d5d708eb1244250f3dd02b6", "support" ], "editing/data/insertparagraph.js": [ - "6e70f6c308844af53888cd4093580242fd73a275", + "5cc4cee5d1ba32775a3a940e11ce46215b276466", "support" ], "editing/data/inserttext.js": [ - "5a0ceb860b775c14a2a096edfc75881eea1909f5", + "be6f17c7af88382808ee574d9291fbc606ab7ec4", "support" ], "editing/data/insertunorderedlist.js": [ - "259f57149badc8c124f3e963b6f1d5fbe4e9dbdb", + "ed8c92ce7bc902a5125e082798ad9abfef469f18", "support" ], "editing/data/italic.js": [ - "5459c6140ac7aadc49b716b82feba092eb8f67af", + "c2f373e29fd1894189243718e8bd003b92f3375a", "support" ], "editing/data/justifycenter.js": [ - "d61ca0251b32c1d11db99222bb48dfec4a18c6fa", + "066b910ecb3b087abe17279ab7c35eb43a883e19", "support" ], "editing/data/justifyfull.js": [ - "5f39fc5babb2d785f63a74989bf4d900a03f932d", + "906d2f7ec92f26695e760e6cdf855ef697869b61", "support" ], "editing/data/justifyleft.js": [ - "413a8ebf1501bd136bd4b789c5cec272a9204e9d", + "aa7d9db71cb624eae3acfce352c83ada85fcfe3c", "support" ], "editing/data/justifyright.js": [ - "563d0d450b72d94cf062ec6c74ee1160ed8fc13a", + "bc17e41ed4e658ff2b6622d76f2ca781da2cf5e9", "support" ], "editing/data/misc.js": [ - "413d681a83942734a410f614a40c5f913b9bbf6c", + "5e7a34bcaccb5ef4c2efa782fbc19991931bf8bc", "support" ], "editing/data/multitest.js": [ - "aaecbcfb0c1077e4940181f74c6ddbd91d23fcbd", + "5caa8e9d6140d6ebc68611784f9c2e535cc6daa0", "support" ], "editing/data/outdent.js": [ - "98d12d9e2eaadb98ab9580ebac19c1bf372ea5c7", + "370659febaa07f3cb3045931efdbe0ccdb6bd26d", "support" ], "editing/data/removeformat.js": [ - "b7a24b8162be7c11b0cf2a6443fe0d3973e3bc75", + "f3f054d79780525df262cb9d1c90799eec4751d1", "support" ], "editing/data/strikethrough.js": [ - "6016f3210874b49ae49093d0c3ab63ac8cd5abf8", + "728a5a2f08ff217757017cde8e7646e1ae42ea7f", "support" ], "editing/data/subscript.js": [ - "0bf0515ad3643a09ab8af047fa01e14f62d13208", + "8259fca2d6342a2de81752eab6f19223d0fe4140", "support" ], "editing/data/superscript.js": [ - "f8b0e882d6911894e0b3b9ba74faad382d3db478", + "2211663469529e5811c73fc30bafe2182341bcbe", "support" ], "editing/data/underline.js": [ - "cb53bbac4065882c9bb1ef95975794cfd6b8616a", + "aa89a58d130544c25b8483179b7ea80c52fb7e37", "support" ], "editing/data/unlink.js": [ - "b15636f4a5dc2a56712aa5133139244d0ba77624", + "7b5266ad05b6fc4c8653c026030e74b10ba1de31", "support" ], "editing/event.html": [ @@ -167962,7 +173220,7 @@ "support" ], "encrypted-media/content/content-metadata.js": [ - "4089766ce88368170d45b6a5b0e8db48fa2ef891", + "5bb828a1f1a9f05d74fd2103d06bc33d28174bbc", "support" ], "encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4": [ @@ -167993,14 +173251,6 @@ "0fb6d575a357dd5fdc4544a55cb8ef4e25f0f449", "support" ], - "encrypted-media/content/video_512x288_h264-360k_multikey_key1_dashinit.mp4": [ - "da39a3ee5e6b4b0d3255bfef95601890afd80709", - "support" - ], - "encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4": [ - "13a90556e91d127b0b8cf4a5ea3aec1dc99c2339", - "support" - ], "encrypted-media/drm-check-initdata-type.html": [ "ae0f79ae94465890ded3e3a6bfd60f320b23ad44", "testharness" @@ -168454,7 +173704,7 @@ "support" ], "eventsource/README.md": [ - "7ffbbf36f58487deadfc6ee31d7b12488a8b6daf", + "f450de54700a6057f2acb57d2c52257684b337f8", "support" ], "eventsource/dedicated-worker/eventsource-close.htm": [ @@ -168777,6 +174027,10 @@ "ab322023411faca98534f620806b2418a6767e64", "testharness" ], + "fetch/api/basic/block-mime-as-script.html": [ + "1dd503f1537b09f7aa875ea9a636d587b03601e3", + "testharness" + ], "fetch/api/basic/conditional-get.html": [ "77822a239b405b0b5c0259a335bac6cbe26b7fed", "testharness" @@ -169014,7 +174268,7 @@ "testharness" ], "fetch/api/headers/headers-idl.html": [ - "13804a9850b05753cf2ad85c926fd071f9fc1888", + "42dc60a28c86ef378a8aa614f411f13bae0a081a", "testharness" ], "fetch/api/headers/headers-normalize.html": [ @@ -169178,7 +174432,7 @@ "testharness" ], "fetch/api/redirect/redirect-location.js": [ - "793e947c027bbf8b2f11b7f2fe482f0480739220", + "3b48bf04659cc82462c3f33db47fd2f44f63c0c3", "support" ], "fetch/api/redirect/redirect-method-worker.html": [ @@ -169310,7 +174564,7 @@ "testharness" ], "fetch/api/request/request-error.html": [ - "bfd03777a43be514a0839ab14f5206f486332fdb", + "ff308916884f69b3f4aa8f2017c4d9fe0caf0f00", "testharness" ], "fetch/api/request/request-headers.html": [ @@ -169322,7 +174576,7 @@ "testharness" ], "fetch/api/request/request-init-001.sub.html": [ - "096424b40f6a21e989a6a5d8684b29ee8cbb963e", + "49bc4349b4e7a85d88cacd54227355aa986535f1", "testharness" ], "fetch/api/request/request-init-002.html": [ @@ -169330,7 +174584,7 @@ "testharness" ], "fetch/api/request/request-init-003.sub.html": [ - "059edc7e857af7231abc1434f3dcebb35229f459", + "f3084c91090e9c86c5586e947e63baf4990b582e", "testharness" ], "fetch/api/request/request-keepalive-quota.html": [ @@ -169385,6 +174639,10 @@ "387c35bf1e576f00a10ce5abb4cc92e78da56845", "support" ], + "fetch/api/resources/script-with-header.py": [ + "0c988e869e2e7af06bef67a2eba8211554b38323", + "support" + ], "fetch/api/resources/status.py": [ "d521bae08fa1ee19e7bbf4301157703e567ad5c6", "support" @@ -169597,10 +174855,6 @@ "94af02c5ca5146386acd4fae5856f89cd244bed1", "testharness" ], - "fonts/CanvasTest.sfd": [ - "c8103241670f9b5d4e5ae9083bbf7ec0221afe3b", - "support" - ], "fonts/CanvasTest.ttf": [ "10a7017b4caead6817aa08b25f14950e6402dd95", "support" @@ -170069,20 +175323,24 @@ "0a3ea46f600d1af4fb6f4a9777812476c3c66fcc", "support" ], + "generic-sensor/generic-sensor-tests.js": [ + "7b36a69dd7d9148f70a1d40d4108dcd747cb2913", + "support" + ], "generic-sensor/idlharness.html": [ "0e3f29a3a065a3db2f6e0e77d9c6bbdf47bf5ca8", "testharness" ], "geolocation-API/OWNERS": [ - "0657e9c1d1281428355eb545ba0b4552dc8900ec", + "84c4182ceed0f75ada11e63c3dfc2acc2939cbb6", "support" ], "geolocation-API/PositionOptions.https.html": [ - "3ed405ebbe4b6fde9dfa6b3426c52c7025efd84c", + "772c305b5b9e6a8ae61a44b395771b8d60bd7187", "testharness" ], "geolocation-API/clearWatch_TypeError.html": [ - "281cdbc3d81e498514a0cca3e839c33e1b217974", + "cce531a95f13a25148903807da87725390dd13dc", "testharness" ], "geolocation-API/getCurrentPosition_IDL.https.html": [ @@ -170102,7 +175360,7 @@ "manual" ], "geolocation-API/getCurrentPosition_permission_allow.https.html": [ - "695f80f5a06279b3a0bdd137e6a402da66a5eeee", + "02b0a2b3c021da0b811ba1c21ce0fc63d7839652", "testharness" ], "geolocation-API/getCurrentPosition_permission_deny-manual.html": [ @@ -170110,7 +175368,7 @@ "manual" ], "geolocation-API/getCurrentPosition_permission_deny.https.html": [ - "28939dd8e719ba66497a814edd1f4500ad348e95", + "aabbc7b2d392e2bbc26c08262bae4d57348da7a2", "testharness" ], "geolocation-API/interfaces.html": [ @@ -170118,7 +175376,7 @@ "testharness" ], "geolocation-API/support.js": [ - "021f696f918554830708d272e95caf13c7d596e4", + "68515a39a244240502d7a871be505a079360cdce", "support" ], "geolocation-API/watchPosition_TypeError.html": [ @@ -170130,17 +175388,33 @@ "manual" ], "geolocation-API/watchPosition_permission_deny.https.html": [ - "8da70bf5b65ace1e8a26e458d6c011c6183c5501", + "ca3036737a662e8673477b1a09b6fce89f0f98f4", "testharness" ], + "gyroscope/Gyroscope.https.html": [ + "03510d4964a52a53fc7648b5435e810e75ea747a", + "testharness" + ], + "gyroscope/Gyroscope_insecure_context.html": [ + "319bcf346337ccdd67f94ba2d0d4849e5b57da5e", + "testharness" + ], + "gyroscope/Gyroscope_onerror-manual.https.html": [ + "1e15b883bd317ca83783864fc563794cb0f6df8e", + "manual" + ], "gyroscope/OWNERS": [ "36770a71443523aa2f91f9958ba24066f0b4dcec", "support" ], "gyroscope/idlharness.https.html": [ - "2a2de0a720181358749232ce7a5301d79eb120d1", + "567b200f0ea88894bbffbffb6d20ea546f516e7d", "testharness" ], + "gyroscope/support-iframe.html": [ + "b02be6c1cdae86e449b8bf635e18e0b60957bb81", + "support" + ], "hr-time/OWNERS": [ "b82f9756b15ef3ea45fb250e304031d9ceaee9c7", "support" @@ -170362,39 +175636,63 @@ "support" ], "html-media-capture/capture_audio-manual.html": [ - "2b5cc72f7f2d323dfc0c96623c9fc026abeec2db", + "fd611892abb621d1310eba3e46f6439465b8dd3f", "manual" ], "html-media-capture/capture_audio_cancel-manual.html": [ - "7f245012220fa028e1152b3f0c7464d1e67447c0", + "da45d452a1759528bc6aaa466033804fe62cdfe8", "manual" ], "html-media-capture/capture_fallback_file_upload-manual.html": [ - "9795fbe923e4592924475ed639a8cd59be5d8289", - "manual" - ], - "html-media-capture/capture_image-manual.html": [ - "a31d06ee9e392dca38ac465e590fba7b01fe1a92", + "ca8753c7df7027ac899a3056c828dc095e07cb55", "manual" ], "html-media-capture/capture_image_cancel-manual.html": [ - "c6dc98923dc96e61154229fc5354e822899a8a7d", + "27e629176c546007bc3e5b1454e33a9624d3ddda", + "manual" + ], + "html-media-capture/capture_image_environment-manual.html": [ + "d158d667ecd004ab145cbe5b4fc4689b61fc1e51", + "manual" + ], + "html-media-capture/capture_image_invalid-manual.html": [ + "c51ad170a479f9656abf493c93ec503d91b93baf", + "manual" + ], + "html-media-capture/capture_image_missing-manual.html": [ + "257544fbac5d85326940c8f6b11e23d278d4dc7f", + "manual" + ], + "html-media-capture/capture_image_user-manual.html": [ + "16a810530a8101a0c672bad9c425ca0e8f1e16cc", "manual" ], "html-media-capture/capture_reflect.html": [ - "0f8a2aa88b35610b9591cd601e366a46a92ac095", + "81518a10ed38fa5e077430ce6fdf8ed844297a01", "testharness" ], - "html-media-capture/capture_video-manual.html": [ - "5f6257d736861b91bbc30b3c0a6703aa323137f6", + "html-media-capture/capture_video_cancel-manual.html": [ + "14d23724a4987da8996e82d57e09aeeb458c1cc5", "manual" ], - "html-media-capture/capture_video_cancel-manual.html": [ - "ea3aaee0458b374b9a6affb3d7af09f18099fcb1", + "html-media-capture/capture_video_environment-manual.html": [ + "2e39f6ea0ff308c022aea53d8b64b32ba1718200", + "manual" + ], + "html-media-capture/capture_video_invalid-manual.html": [ + "0188e58ba819aad219e2f82a0ca4e7eec3265e9a", + "manual" + ], + "html-media-capture/capture_video_missing-manual.html": [ + "243f7bd28f26bbd5a85e79360da7dbc739fd4bab", + "manual" + ], + "html-media-capture/capture_video_user-manual.html": [ + "acef04c2541d30fdff411c74ccce81ee2086c9d2", "manual" ], "html-media-capture/idlharness.html": [ - "2e5050d4e1a58a14131809f1acdcd263729918ae", + "32b3d387100f0e7ecda93d1fb88351680b259df0", "testharness" ], "html-media-capture/support/upload.txt": [ @@ -171745,6 +177043,10 @@ "923e6d0e13f71e2e79799005ac0bcd6415ad1ffa", "manual" ], + "html/browsers/history/the-location-interface/per-global.window.js": [ + "04de6e863ec1816fccda38e50b81d67bbcedb125", + "testharness" + ], "html/browsers/history/the-location-interface/reload_document_open_write-1.html": [ "464fa292c3fa04da8594401bbdb7cbe2a30b41dc", "support" @@ -172054,7 +177356,7 @@ "testharness" ], "html/browsers/origin/cross-origin-objects/cross-origin-objects.html": [ - "a49a73b44a8484a240b14fc3877b0abed64e16dc", + "02e290c300057b9520390e55833194908d74ca76", "testharness" ], "html/browsers/origin/cross-origin-objects/frame.html": [ @@ -172077,6 +177379,14 @@ "9839a9c24ce78ec42da8a60d2175df06e19983c1", "testharness" ], + "html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter.html": [ + "1f0408464d8d98341c9537c3e3356cacbcf2f489", + "testharness" + ], + "html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_iframe.html": [ + "d33427abcc87693bce1f5610f460aad12cb99759", + "support" + ], "html/browsers/sandboxing/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -172209,6 +177519,82 @@ "c4f0da17299d37f70b316d709dbde0ff6a1f62fb", "support" ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-innerwidth-innerheight.html": [ + "b86f249223db3ef579e8d976f6b586d43e26a94d", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-screenx-screeny.html": [ + "38921fe3656a4b08aa44a37ff4829a8b4d9b6213", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-top-left.html": [ + "049dd60f6397e87da17edf9ddb96c10fc08e57d4", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-width-height.html": [ + "3fddee5842259433e1158eb326e51d037dd42774", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-height.html": [ + "caaede75e5c16cc78023ce410f48e37e612cffbb", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerheight.html": [ + "94c1f2f19317d039e4c30e30fcdc41da20fe402f", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerwidth.html": [ + "30ef1e2913e78f0fde1794bdf5bceef435a7101a", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-left.html": [ + "711ef5c371aec8b494aa7c5bb0541ba264acb1e0", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screenx.html": [ + "420386e4df736ffd925d3c813c92f65e02d0b514", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screeny.html": [ + "e7aaee702eb277266bee64889507cd1d38cb5c27", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-top.html": [ + "4164cdfee8733cd242f7e51089e3106556f0b359", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-width.html": [ + "a73e68d7017e7f27609cc10427a7a6c86c130fb1", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-innerheight-innerwidth.html": [ + "61aefe4aade30ca7a696450ccb5a9330bd0c9ccb", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-noopener.html": [ + "0d37066f498228705c175d7d7a15e4d2ac279397", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-screenx-screeny.html": [ + "736fcd9bbe559184b7e11239a9c10816e30db4f2", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-top-left.html": [ + "50cb5c7ee38e12d067661b40706d244ca5cabe8b", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-width-height.html": [ + "637bbe2d587b4422a3d935cffac24807bc0fffaa", + "testharness" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/close-self.html": [ + "7be5d6853d829e7af8baaf96c4ef42cf858a3526", + "support" + ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/message-opener.html": [ + "37afff594d1448656b233c347db88dafafc01f8f", + "support" + ], "html/browsers/the-window-object/browser-interface-elements/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -172362,11 +177748,11 @@ "testharness" ], "html/browsers/the-window-object/window-indexed-properties-strict.html": [ - "57a32c2a9c636762b2d77301c9a6258a4773190c", + "ac9d401368b75e00adbdf80ee42dd8dce1e48e13", "testharness" ], "html/browsers/the-window-object/window-indexed-properties.html": [ - "bf31e152c35b33c32366950fa84837fab74a6bec", + "22d5cb06bfc4724d27f565b8ffa2280bf2e8538b", "testharness" ], "html/browsers/the-window-object/window-named-properties.html": [ @@ -172461,112 +177847,144 @@ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" ], - "html/browsers/windows/browsing-context-names/001-1.html": [ - "7f9396d2baeeafd98832c7fe5a0a1474fc358e98", - "support" - ], - "html/browsers/windows/browsing-context-names/001.html": [ - "1b127e23e7991080fc01b24c1924822642480744", - "testharness" - ], - "html/browsers/windows/browsing-context-names/002-1.html": [ - "f70339fff42414af8441fdf4be42151839989839", - "support" - ], - "html/browsers/windows/browsing-context-names/002.html": [ - "ed586ee147452ba6cb8d90782b266807f8b7975e", - "testharness" - ], - "html/browsers/windows/browsing-context-names/browsing-context-_blank.html": [ + "html/browsers/windows/browsing-context-names/choose-_blank-001.html": [ "4a1a9ff6c913291edce2339faa443b6da2e5fe74", "testharness" ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html": [ - "381a1a09c09e8c43849a7b8f4d120507b2196aeb", + "html/browsers/windows/browsing-context-names/choose-_blank-002.html": [ + "37fffaad1ad4136a759507ab0565896e8ed7e0c5", "testharness" ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-parent-001.html": [ - "4767179a7c78a8e0798997dace46b47ec5d902ad", + "html/browsers/windows/browsing-context-names/choose-_blank-003.html": [ + "e3f7b085257c45bb2a8a86d6a7d7ff9b5191dbf4", "testharness" ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-parent-002.html": [ - "7d1692f649951585d8ce60bd7cc9c4470f255b95", + "html/browsers/windows/browsing-context-names/choose-_parent-001.html": [ + "a03843100fba5a753ae3a4451cd5b03ec8808e56", "testharness" ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-parent-003.html": [ - "61ebac870a8c1e030468f5cfd4f6e22171c015e7", + "html/browsers/windows/browsing-context-names/choose-_parent-002.html": [ + "7ef76d4690da42586f3e673413d943da12527001", "testharness" ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-parent-004.html": [ - "6341211c1c38b6b3e3b09329c71bd0b8e79e2f2f", + "html/browsers/windows/browsing-context-names/choose-_parent-003.html": [ + "b12b3005f9227e45f2c92dd7ca5aad339cbdae25", "testharness" ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html": [ - "f957a910476b1294de97ef69e671e84d201ca5c0", + "html/browsers/windows/browsing-context-names/choose-_parent-004.html": [ + "7ecba630d8fa01fde65abc0f6b135363707b91df", "testharness" ], - "html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html": [ - "c445f1397eb5e95a25aa7ae64f677cbfa63cb049", + "html/browsers/windows/browsing-context-names/choose-_self-001.html": [ + "04add262884e7e19a290ebd40ddb90107055e906", "testharness" ], - "html/browsers/windows/browsing-context-names/browsing-context-default-name.html": [ - "12ab8a79c7239a712cebfa171c4271fae4a49b0e", + "html/browsers/windows/browsing-context-names/choose-_self-002.html": [ + "4804c851ba55a65d24e88456c0021b32b13fae44", "testharness" ], - "html/browsers/windows/browsing-context-names/existing.html": [ - "eb695cb2f8a126f0c32347d8716936fc288d0858", + "html/browsers/windows/browsing-context-names/choose-_top-001.html": [ + "b85f6e0bdcddba5cde28bc088ee0b81d6506fde8", + "testharness" + ], + "html/browsers/windows/browsing-context-names/choose-_top-002.html": [ + "8ec181327440e8ef5516b1cd23d1733355015ac5", + "testharness" + ], + "html/browsers/windows/browsing-context-names/choose-_top-003.html": [ + "6c1fb058b4ce37789baf8bdf6dd6ab6695e54f78", + "testharness" + ], + "html/browsers/windows/browsing-context-names/choose-default-001.html": [ + "cebca758b8fc07fbbf9a99700acc464cd67d397e", + "testharness" + ], + "html/browsers/windows/browsing-context-names/choose-default-002.html": [ + "0a6b8b82b44289c5ff6212857a1a174cf7d9d9d7", + "testharness" + ], + "html/browsers/windows/browsing-context-names/choose-existing-001.html": [ + "175492ca2ea7d2ce000466e895ff22f29b77df93", + "testharness" + ], + "html/browsers/windows/browsing-context-names/resources/choose-_parent-001-iframe-1.html": [ + "a3c60408fc0d545e3a7ca8161f04d095ebdba02a", "support" ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-1.html": [ - "6b1687e52c5b53e6d7a0bb4fed5bed7291154ff2", + "html/browsers/windows/browsing-context-names/resources/choose-_parent-002-iframe.html": [ + "8df4501c8bf73f5c1daed2986eba8adeb211a6cc", "support" ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-2.html": [ - "95f916c7b914088b59ce6addb5c639f4dc158de1", + "html/browsers/windows/browsing-context-names/resources/choose-_parent-002-window.html": [ + "85ad3ee8ec0e3028f993fd776de6ddb5948f750a", "support" ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-3.html": [ + "html/browsers/windows/browsing-context-names/resources/choose-_parent-003-iframe.html": [ "169dc483de493c5c4f0383063dc1d9aad2b41073", "support" ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-1.html": [ - "638ed0ec62a27b3acc1d0acb60bd5113a1c2988c", + "html/browsers/windows/browsing-context-names/resources/choose-_parent-003-window.html": [ + "e8f5e55f930899229252a04b2d698abddf73ffb2", "support" ], - "html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-2.html": [ - "e6ab1f0e5aa36e69467ae1f69e4682d40ae692a7", + "html/browsers/windows/browsing-context-names/resources/choose-_parent-004-iframe-1.html": [ + "050927f475859690243f6039036bd8dd5bc72992", "support" ], - "html/browsers/windows/browsing-context-names/resources/parent-top-nested.html": [ - "03b7ece0831f8059f687135be899f4de2831568d", + "html/browsers/windows/browsing-context-names/resources/choose-_parent-004-iframe-2.html": [ + "39aa44e0efbea17158e4aeea731a22f8b4946006", "support" ], - "html/browsers/windows/browsing-context-names/resources/parent-top-replace.html": [ - "1f3d056bbb472a730ee2f40085c51fbb279ad52f", + "html/browsers/windows/browsing-context-names/resources/choose-_self-001-iframe.html": [ + "3ad6ddf88d32b0733fe1041636081c33c4611ecc", "support" ], - "html/browsers/windows/browsing-context-names/resources/parent-top.html": [ - "e2247fbb30c24e014d1743cd9df91bf0195fbfe0", + "html/browsers/windows/browsing-context-names/resources/choose-_self-002-iframe.html": [ + "adc1c8ac78adbdd1455f8e22289a9bfef079ca5c", + "support" + ], + "html/browsers/windows/browsing-context-names/resources/choose-_top-002-window.html": [ + "be64018ffa35bf3dc1200111fc25f7d1b520fc41", + "support" + ], + "html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-1.html": [ + "dd62814246f87a9847b5c2de1a6537a7daa81bf4", + "support" + ], + "html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-2.html": [ + "8e940565ae03d662d1dc878115d9665a5f01a837", + "support" + ], + "html/browsers/windows/browsing-context-names/resources/choose-default-002-iframe.html": [ + "b4fddf4509e4922bc2baad24247d72f4fc41f718", + "support" + ], + "html/browsers/windows/browsing-context-names/resources/choose-existing-001-iframe.html": [ + "7e71b6f0835a78ffbd7e0731ce271d78b20890c8", + "support" + ], + "html/browsers/windows/browsing-context-names/resources/open-in-_parent.html": [ + "95f916c7b914088b59ce6addb5c639f4dc158de1", + "support" + ], + "html/browsers/windows/browsing-context-names/resources/open-in-_top.html": [ + "6fad2b581eb588c91923bad0e3b780089e5849df", "support" ], "html/browsers/windows/browsing-context-names/resources/post-to-opener.html": [ "a724ee03afea915ba9a3636e6915db8bda801212", "support" ], - "html/browsers/windows/browsing-context-names/resources/post-to-top-or-close.html": [ - "83eae63250fb3ad9f146283e9387b0e18284d4f7", - "support" - ], "html/browsers/windows/browsing-context-names/resources/post-to-top.html": [ "c2b557ab78403aa520346da294e1c406dd37ebda", "support" ], - "html/browsers/windows/browsing-context-names/self1.html": [ - "7c86c871972f456c6b97be7b46fa7d6ce87a3a80", + "html/browsers/windows/browsing-context-names/resources/report-has-opener.html": [ + "8cc69db12b379eb57c2a1d3d3321a4034fa2e301", "support" ], - "html/browsers/windows/browsing-context-names/self2.html": [ - "fd91e9250c182da49ab39220a656348c29c84048", + "html/browsers/windows/browsing-context-names/resources/report-is-top.html": [ + "e65bff43b66ee9f7b6aa5b061fff835b199e1745", "support" ], "html/browsers/windows/browsing-context-window.html": [ @@ -173482,7 +178900,7 @@ "support" ], "html/dom/elements-metadata.js": [ - "bcd86ba6bbe3ce770091279ec4c3005b16dbc633", + "059d2c83a4354f173056ca489412d19ab77ef110", "support" ], "html/dom/elements-misc.js": [ @@ -173498,7 +178916,7 @@ "support" ], "html/dom/elements-tabular.js": [ - "929e628d165561489a2b68b2faf44a47a7f856d7", + "db69341821cb76750da473664d806b4649c9b606", "support" ], "html/dom/elements-text.js": [ @@ -174302,7 +179720,7 @@ "support" ], "html/dom/interfaces.html": [ - "1f34a3ba45166c0d0c14cebb7846408ec120b9f1", + "4c0db96824033d94b98123954254930fb742d7e3", "testharness" ], "html/dom/interfaces.worker.js": [ @@ -174358,27 +179776,19 @@ "testharness" ], "html/dom/reflection.js": [ - "d952a2936d184f18f3de4c00c5a871ce303b3963", - "support" - ], - "html/dom/resources/interfaces.idl": [ - "c712b0532395b08c2e6b3c68b8580f560b47a594", + "c05afee11097eac0e05c8299c1ad8322afc47421", "support" ], "html/dom/resources/self-origin-subframe.html": [ "a94fee503c6ad28fdedf1f62fcd96465f7b88e71", "support" ], - "html/dom/resources/untested-interfaces.idl": [ - "1165f9e91f3c81876398211db67483fa16c62e55", - "support" - ], "html/dom/self-origin.any.js": [ "187b3657775b815f9360c01d2ddb358a53e1f920", "testharness" ], "html/dom/self-origin.sub.html": [ - "d821d4b41ac8517d345f86a9f8298f67284d1967", + "ad9aadfb350cee1613a0884154706c632b0a8fe8", "testharness" ], "html/editing/.gitkeep": [ @@ -178217,6 +183627,50 @@ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" ], + "html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html": [ + "a21ca78b9c6a8795eb4e2fa95f30a51a553a3e52", + "support" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html": [ + "5c20688ee9f871cdc0b1553287dfe6d4d64dcf15", + "reftest" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html": [ + "80318bc3c90f72803255831a95c482bf99105d29", + "reftest" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html": [ + "ae4f1d7e6c954fd1f3fa53fcd77833954bcdf6d9", + "reftest" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html": [ + "ace6101644d2c0e426d611016a3cb3dc30968f4a", + "reftest" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html": [ + "5aae7d56aa63f90160ba1e296378b0a0832c07f0", + "reftest" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html": [ + "e329657b5ebf7211237fa7712a3c710d3ea4b956", + "reftest" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html": [ + "10c986cf6e428c782a09572be5c5438d256b17c1", + "reftest" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html": [ + "c026d35ec89818f5624daad20163fb4ceed62828", + "reftest" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html": [ + "68e7e27bc3777a8fe0807380a28c1ce60aa3becc", + "reftest" + ], + "html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html": [ + "0320abd956316beff38f2ff06e0f32ee2b2e9887", + "reftest" + ], "html/editing/editing-0/spelling-and-grammar-checking/user-interaction-editing-spellcheck.html": [ "228e52ef1987df94158305799dc53086e435b24b", "testharness" @@ -178585,6 +184039,150 @@ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html": [ + "8375e9daeb9a11e53a9841874fef50677f0970dc", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success.html": [ + "12bd51a62830514325b89263abc5710bbe6b510f", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html": [ + "594d11e18e7ef8e9aaa0eca3dc2865033827ce7c", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-dedicatedworker.html": [ + "1fa9a3ae8d33bfd08d37a18853d511b9de66889b", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-sharedworker.html": [ + "c93bd6d985380cde5e3309897ad56fccd0a73709", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.js": [ + "42b788cb6d8a9509239bbb5c141c1f014dd9a6bf", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html": [ + "17b67f8d75e558be808493f5cba82f978a0b6822", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/blank.html": [ + "c4461f454a7dfd85e9345832ecaabd9cbf6e6cda", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html": [ + "f6102979837864b2d472a71e425f021a29d76184", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-sharedworker.js": [ + "afbfe4d0178bd33062ccb9b05f27f8643ed9cad8", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-worker.js": [ + "4c253242a8b665d04deb00825e9a81662665ead7", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-iframe.html": [ + "6284dea4f647cce02cc8b54fc5e8c6bedc0b633b", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-worker.js": [ + "7e7480dc1cc966ad2fef985a7d5d4dbdfa0e24e9", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe-domain.sub.html": [ + "18185b1c53475814cb8f4d9ad820a2d85a283b1f", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe.html": [ + "d3d2dd8c8a277386a550cafd91a4b068daa035e0", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-popup.html": [ + "a27679e95d330e2a2efbc62b80fca999a3aa672e", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker-with-channel.js": [ + "ddc07ed4ef35ce73744506cbd11817e48b65e976", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker.js": [ + "f89bea23edb1ebddb02c5f83c1bd36d30b5b48c6", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-1.html": [ + "635658ddc3fa586abc078211842b4bc43b4a53d7", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-2.html": [ + "4ddb26b10fea29e35068e5854009b6ae848fe032", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-3.html": [ + "c112135e61cb799953b6009db7017952266bbaa1", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-4-incrementer.html": [ + "fd947afdad730f4826cc893ea5516fc20a08b87e", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-failure.js": [ + "ff16d63cc344365df0e6c0f30d4d30b82d1df2e4", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/sharedworker-failure.js": [ + "f5614900f151d8c4c659979b67bf8ac128efa3cb", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-incrementer.js": [ + "9f0a9648c72af785c3a7f44f26d6509f1a4f81f7", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-sab.js": [ + "a8d3ce61436cb0d5b23c275820fcde7d63cdafec", + "support" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html": [ + "8f66e9b640ba812f3846a8fb0dc8f29fcf502f1e", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.js": [ + "a6e82ee3583bbf2667c59cb04460c1fd9aea4aee", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-notifications-api.any.js": [ + "bba8979a9270460b976f8c2ca6912c1b3dedeab2", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html": [ + "dac4b1fd873c3ec42d05e24166e77424b15377d4", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html": [ + "298b5dba54eafaee6dafe5356b5196ed37f59b21", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-failure.https.html": [ + "11794f2d67e97eb97ad1871027b4a19e017e9624", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html": [ + "735bfeda2e72815f331766b32ac02af71179902b", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html": [ + "5d30957d37646bd4ebc7112db8c055bae8cc6e23", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html": [ + "7c0b8b2e411236aeeed3a8b7962dc70d8a94969f", + "testharness" + ], + "html/infrastructure/safe-passing-of-structured-data/structured_clone_blob.html": [ + "2a3deba2534cad6f5e0aa85cfc3c90debcead20a", + "testharness" + ], "html/infrastructure/terminology/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -179421,6 +185019,22 @@ "0dd816530943f3a6fa3235b1d481f70ca578b6e6", "reftest" ], + "html/rendering/non-replaced-elements/the-page/iframe-body-margin-attributes.html": [ + "68e9c15f160415a652650331f403dd324cd402e9", + "testharness" + ], + "html/rendering/non-replaced-elements/the-page/iframe-marginwidth-marginheight.html": [ + "db8b96ffd3b16bc78d937b46860de8c22d857947", + "testharness" + ], + "html/rendering/non-replaced-elements/the-page/support/body-marginwidth-marginheight.html": [ + "d75fd3830c23860db68fe23589f74a7bdc95be91", + "support" + ], + "html/rendering/non-replaced-elements/the-page/support/body-topmargin-leftmargin.html": [ + "1c31ddd13c97504f59d1e403f6ab90252fa68e0c", + "support" + ], "html/rendering/non-replaced-elements/the-page/test-body.xhtml": [ "7a229199399e678847280e6e88e40e5b37bfdd11", "support" @@ -179474,7 +185088,7 @@ "support" ], "html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html": [ - "29e2eedb67a0a8e80c5bc09cbda5acb3d74bed74", + "2eaa79128917a0d0888b7155adfa0fb83bcb7c1f", "reftest" ], "html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_scale.html": [ @@ -179725,10 +185339,18 @@ "285208d6cf3113ec16bedd107c0740b8c7c8a9d8", "testharness" ], + "html/semantics/document-metadata/the-link-element/resources/bad.css": [ + "b968e6422a283acc772561f8950171b3a5e00397", + "support" + ], "html/semantics/document-metadata/the-link-element/resources/empty-href.css": [ "1dcc57d4f3363562322937979cb7828b0c298daa", "support" ], + "html/semantics/document-metadata/the-link-element/resources/good.css": [ + "04a3a89fe805fc930dc3adfa3a4134b950779697", + "support" + ], "html/semantics/document-metadata/the-link-element/resources/stylesheet.css": [ "2829167c82bafef6cfea06071007a231aa4277f6", "support" @@ -179737,6 +185359,14 @@ "e4a66764ea94d51b42d485d75a3305ea2ab79226", "support" ], + "html/semantics/document-metadata/the-link-element/stylesheet-change-href-ref.html": [ + "cca943d35bd18e99249d50c6d40cc6fe2e328354", + "support" + ], + "html/semantics/document-metadata/the-link-element/stylesheet-change-href.html": [ + "6083446e9ef1b70f044a353ef96b459956afb1ef", + "reftest" + ], "html/semantics/document-metadata/the-link-element/stylesheet-empty-href-ref.html": [ "1ac8e070630e58df8489b779bdd75cb2b38c25ef", "support" @@ -180961,6 +186591,10 @@ "38b6f3c5707b360427854b82054d86f5364dc0b8", "testharness" ], + "html/semantics/embedded-content/the-canvas-element/imagedata.html": [ + "e685ab0d76bdd1b60a5d6f1e2126ea1a89db97d1", + "testharness" + ], "html/semantics/embedded-content/the-canvas-element/initial.colour.html": [ "22ddb77f5a18a19edc409d36532120f852bfbc57", "testharness" @@ -181594,7 +187228,7 @@ "reftest" ], "html/semantics/embedded-content/the-iframe-element/iframe_harness.js": [ - "c5db7a8f3c32f79a4e24d176cb95563a999240e5", + "2f22f494c69854a79af94ccf90215ece7bb4a130", "support" ], "html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm": [ @@ -181733,6 +187367,14 @@ "bdbfbe9a5908c6233bd7b9697a0762bd2e0f6ede", "testharness" ], + "html/semantics/embedded-content/the-img-element/delay-load-event.html": [ + "e4782535af755b29864fd3de67bbdd0de13f19d7", + "testharness" + ], + "html/semantics/embedded-content/the-img-element/document-adopt-base-url.html": [ + "a4b542eb344cca6bdcceceb3aa7006e900f5400f", + "reftest" + ], "html/semantics/embedded-content/the-img-element/document-base-url-ref.html": [ "add78257076d22891334b93c8072d098ace9b6eb", "support" @@ -182109,6 +187751,18 @@ "bfd11561a2e568668b6aaf94bc6da9e42fccdf55", "testharness" ], + "html/semantics/forms/form-control-infrastructure/form_attribute.html": [ + "b19b882091ff523e71397bfcad5dcf505e0a8f88", + "testharness" + ], + "html/semantics/forms/form-control-infrastructure/form_owner_and_table.html": [ + "7172d74bb5572091ee09abf30a4f6892b85aca3a", + "testharness" + ], + "html/semantics/forms/form-control-infrastructure/form_owner_and_table_2.html": [ + "3b1dea35bb4af384125904d69bf569109965714f", + "testharness" + ], "html/semantics/forms/form-submission-0/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -182186,7 +187840,7 @@ "testharness" ], "html/semantics/forms/textfieldselection/selection-after-content-change.html": [ - "c7f9433a664b59f59be933cdf607c158a599dff7", + "f4b7c92a9eebbfd272793ff7a5d56224220b2dd7", "testharness" ], "html/semantics/forms/textfieldselection/selection-not-application-textarea.html": [ @@ -182274,7 +187928,7 @@ "testharness" ], "html/semantics/forms/the-form-element/form-autocomplete.html": [ - "e3548e62923d62b5844f8d4d7222006bbfd3cb2a", + "c3aae63b6c007e3f39a7bf39c56bcdb7172273ad", "testharness" ], "html/semantics/forms/the-form-element/form-elements-interfaces-01.html": [ @@ -182422,7 +188076,7 @@ "testharness" ], "html/semantics/forms/the-input-element/radio.html": [ - "f80348bd3b3947eefc993323988799df13e7280e", + "e7b37335f58290c4f5a8e1a098c1cc50fb78a7b2", "testharness" ], "html/semantics/forms/the-input-element/range-2.html": [ @@ -182985,6 +188639,14 @@ "84dda1357022cd800b0663aadd3488bd04a64047", "testharness" ], + "html/semantics/interactive-elements/the-dialog-element/centering-iframe.sub.html": [ + "eb00778210365e13b33e194da1b9e870d7e39153", + "support" + ], + "html/semantics/interactive-elements/the-dialog-element/centering.html": [ + "47a8ae7ca2a2d06ee042213d0800e0da37b1fe10", + "testharness" + ], "html/semantics/interactive-elements/the-dialog-element/contains.json": [ "340924bc329569ce605ce228619d95f09f335ec5", "support" @@ -183009,6 +188671,10 @@ "a79ad27e8f1e2eee47c89fa4530f7babfbb07dd5", "support" ], + "html/semantics/interactive-elements/the-menu-element/menuitem-label.html": [ + "d11f6d0ef667da33d7981860b47e6d02f8c0ad24", + "testharness" + ], "html/semantics/interactive-elements/the-summary-element/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -183381,6 +189047,14 @@ "997cee37dcd202498196e63e0f66035979121b7f", "testharness" ], + "html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html": [ + "87e7f790edf2ef9de702f3e9b45a42d6fedae857", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/module/instantiation-error-1.js": [ + "f2a20180b6bf5f9c89f5b9541885d55dc8a8ade6", + "support" + ], "html/semantics/scripting-1/the-script-element/nomodule-reflect.html": [ "ac2b3c16e9e9263cd4c14de205b63709c14ec2e3", "testharness" @@ -183893,6 +189567,10 @@ "2bee37bc667b7aaf9ffc2be912288540896e3f03", "support" ], + "html/semantics/tabular-data/processing-model-1/span-limits.html": [ + "221803eac571dfc67c97122467743be20b1d17c0", + "testharness" + ], "html/semantics/tabular-data/the-caption-element/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -184049,6 +189727,14 @@ "93f820588f813b3e340188c88be1532d6e549757", "testharness" ], + "html/semantics/text-level-semantics/the-a-element/a.rel-getter-01.html": [ + "c207792ee550d653bc0734f6ef457c7c0e2749d8", + "testharness" + ], + "html/semantics/text-level-semantics/the-a-element/a.rel-setter-01.html": [ + "ea922ee6e02e02349ad56d1e8f69d6555d142883", + "testharness" + ], "html/semantics/text-level-semantics/the-a-element/a.text-getter-01.html": [ "ed1c631e5573192fc85f4234d76e5979a32bb44b", "testharness" @@ -184890,7 +190576,7 @@ "testharness" ], "html/syntax/serializing-html-fragments/serializing.html": [ - "dfc037432227ab79b9ce795547fb370594651b9e", + "cd9e3b8412231aa393081a6234efc7476e00c48e", "testharness" ], "html/syntax/serializing-xml-fragments/outerHTML.html": [ @@ -185373,6 +191059,30 @@ "6427c8ff06c11f2877f026124d46748b5270bc8e", "support" ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-dedicatedworker.html": [ + "e9ef057de8593404b63e34c8c2ff038236f26d7b", + "testharness" + ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-serviceworker.https.html": [ + "f6cdef79aefb4739025c0c805dfc1ee7fcddef52", + "testharness" + ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-sharedworker.html": [ + "6927215d83fc6562dabf74b1a089531556256f5c", + "testharness" + ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-window.html": [ + "5aab1e791ad444eb73383e06f4e2fbb1fb512072", + "testharness" + ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-failure.js": [ + "8a24096d84baf51c6d2e3c26131093dccec74195", + "support" + ], + "html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-success.js": [ + "e4c2b99ca0379bfe0531ede9d2da46832f2c95dc", + "support" + ], "html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setInterval.html": [ "c8c4ba120b74c1beb6d24901e3d1b8a87e5b8837", "testharness" @@ -185462,7 +191172,7 @@ "testharness" ], "html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events-onerror.html": [ - "be6f591b06b633d7a4e04003bd6b79788c146c16", + "779323f3ef1f53f112c9eec3f1349d5c467381d7", "testharness" ], "html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.dedicatedworker.html": [ @@ -185529,18 +191239,6 @@ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" ], - "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html": [ - "61f05d56702a02acf80809605c46a31033192df9", - "testharness" - ], - "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js": [ - "37f13d24527fcdb5ded608b2ce58e1b51343cf96", - "support" - ], - "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js": [ - "f08f131c44189e8aaf6c9bb34479a7cfaf6b586d", - "testharness" - ], "html/webappapis/system-state-and-capabilities/the-navigator-object/contains.json": [ "2c41fa08c5296f814d286d8b459424c5c488e3e1", "support" @@ -185581,6 +191279,10 @@ "3a478a2d6f508242244308641a2d57d4eb00798b", "testharness" ], + "html/webappapis/system-state-and-capabilities/the-navigator-object/navigator.any.js": [ + "defa186d15df9349c70ca1c2b4f4877e06f63d3e", + "testharness" + ], "html/webappapis/system-state-and-capabilities/the-navigator-object/navigatorlanguage.html": [ "8f141c495c1b4444c8e25ba57924d7917f97d1b9", "testharness" @@ -185633,6 +191335,22 @@ "49fd55dbbf64c6973a0e76284c0e3d8b7bf0ef3c", "testharness" ], + "html/webappapis/timers/negative-setinterval.html": [ + "405046cab9cd15a88d57eace1f293ebdd7b1b3e2", + "testharness" + ], + "html/webappapis/timers/negative-settimeout.html": [ + "e5673e7cca2b006afd3e2e4e5dd3e56fb10efa4e", + "testharness" + ], + "html/webappapis/timers/type-long-setinterval.html": [ + "83e3c7536d163ead98a008c7d9ff8cf41826371d", + "testharness" + ], + "html/webappapis/timers/type-long-settimeout.html": [ + "7945f54f8ab924c85f337ad5a50b02677d48e526", + "testharness" + ], "html/webappapis/user-prompts/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -185709,6 +191427,10 @@ "c8337ab192542438d854f6cefdd94fd21f066d94", "support" ], + "images/apng.png": [ + "712e995068510d2a77771d34b37f3e9535572839", + "support" + ], "images/background.png": [ "aa8810c8893fdcefac46909a43dc4d58235a30c1", "support" @@ -185885,6 +191607,30 @@ "cd25518dd402033694667ccd1982fd3b85faa412", "testharness" ], + "interfaces/cssom.idl": [ + "bb17bbe93776dbeb33f061a7a90889e922e3138e", + "support" + ], + "interfaces/dom.idl": [ + "86f2e15d4b32af7b5127283eb3cfab5a78b46c0a", + "support" + ], + "interfaces/html.idl": [ + "8dc9bcafffab4ee66a806308b3cf5888af7cebba", + "support" + ], + "interfaces/touchevents.idl": [ + "6ce4f601cda6cd3b99a300e0b28d2886647f06d3", + "support" + ], + "interfaces/uievents.idl": [ + "3fabcfa40caf9c66bc74bcd83663eddb0f385051", + "support" + ], + "interfaces/webrtc-pc.idl": [ + "4f94c4236168ed722f71d81bd957e0da72b29c71", + "support" + ], "js/behaviours/SetPrototypeOf-window.html": [ "92efe1a4f3910a32097fb3cbeef0019d82a0e78a", "testharness" @@ -185953,6 +191699,26 @@ "581702f5f6b8f6e547918ae8f8a8547b103a9b6c", "testharness" ], + "keyboard-lock/idlharness.https.html": [ + "8b2fe1d77e8c4cc8a759a31bfb6f3d962f24992e", + "testharness" + ], + "keyboard-lock/navigator-cancelKeyboardLock.https.html": [ + "5109eb45591bba9ce48d3db91fa02c0590397886", + "testharness" + ], + "keyboard-lock/navigator-requestKeyboardLock-two-parallel-requests.https.html": [ + "6a05080698fbeff768c4f5c85dbbc89cf3cfa09a", + "testharness" + ], + "keyboard-lock/navigator-requestKeyboardLock-two-sequential-requests.https.html": [ + "79ed9f93e2f72bf8e11d04e25c6fa847c91971e4", + "testharness" + ], + "keyboard-lock/navigator-requestKeyboardLock.https.html": [ + "6f8091035f4aa18131c548a81cbe80ba328169c9", + "testharness" + ], "longtask-timing/longtask-attributes.html": [ "a88bd658adcb9ef3dcbfa803397910e531bc864b", "testharness" @@ -186001,14 +191767,30 @@ "4acb6764c2fb60ad55733c420dfd7c1946542f17", "support" ], + "magnetometer/Magnetometer.https.html": [ + "4e7d890f37469aecbce415187bb0bcf239dac37b", + "testharness" + ], + "magnetometer/Magnetometer_insecure_context.html": [ + "9708569b2e2764c973efe31e9f2f4e3de7f7a449", + "testharness" + ], + "magnetometer/Magnetometer_onerror-manual.https.html": [ + "6adfb807ff2c1b24dad702b21f636e7805543704", + "manual" + ], "magnetometer/OWNERS": [ "36770a71443523aa2f91f9958ba24066f0b4dcec", "support" ], "magnetometer/idlharness.https.html": [ - "0a9194605503377bad3f8e66dd60959d2ac5c909", + "b21217da9dc986e605d172d72a5f4f3e7b2aa216", "testharness" ], + "magnetometer/support-iframe.html": [ + "4afaea574bcbd68422278c5e093cf6d37ab4f9f1", + "support" + ], "mathml/README.md": [ "9a0f19770c7f633e06913d9d138e8f3a6d1a1104", "support" @@ -186465,12 +192247,12 @@ "7d6ceec9a74d5485a6f7d51504f22e5eaf81bfee", "support" ], - "media-capabilities/idlharness.html": [ - "d9a80463af2e0fc7bda0a4370a3ba0bbbb791897", + "media-capabilities/decodingInfo.html": [ + "1d8f79cb9e47042aa7eff1b63fe72af4941830e2", "testharness" ], - "media-capabilities/query.html": [ - "a83f2c7a7d9c38c707c4f96c3cd74f77185b7e43", + "media-capabilities/idlharness.html": [ + "0c34bb1872cc16b21c8c1f33d6dfd796f59500c8", "testharness" ], "media-source/OWNERS": [ @@ -186913,12 +192695,8 @@ "cb9a48e1d53911d5be214320adfbf7596632a316", "support" ], - "media/CanvasTest.ttf": [ - "10a7017b4caead6817aa08b25f14950e6402dd95", - "support" - ], "media/OWNERS": [ - "f478084fb2b04fe93435b3c33e9791bf613ba7f8", + "30004bfb49495e067cf71c702ac5985d24589c06", "support" ], "media/foo.vtt": [ @@ -186977,6 +192755,10 @@ "ceeb48e7982eb88561f4c1630cb0fcf15d9cf73c", "testharness" ], + "mediacapture-image/idlharness.html": [ + "7ccf7fcab0344a2e1893e89d7689e2312287b64d", + "testharness" + ], "mediacapture-record/BlobEvent-constructor.html": [ "29d5649ff97ca0631f8c841425a88248525f9774", "testharness" @@ -188461,6 +194243,10 @@ "6a0548ef4b906e539d89940aa791a78bba905262", "support" ], + "mixed-content/imageset.https.sub.html": [ + "e2005b813384f38b64baec9bc431e25aa61f417f", + "testharness" + ], "mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html": [ "9219890ab0efa31e4f2db0646e12882da3a5443d", "testharness" @@ -188817,6 +194603,14 @@ "22ff29845d8417ccbae58123efe8e1c9b9c81eaf", "testharness" ], + "navigation-timing/nav2_test_document_replaced.html": [ + "b36ccb9a595ea5ab318f53dbff75b3c8f7c5b044", + "testharness" + ], + "navigation-timing/nav2_test_frame_removed.html": [ + "8ed53df25ff06d2affa9c438e3bb85d6dc9f34a1", + "testharness" + ], "navigation-timing/nav2_test_instance_accessible_from_the_start.html": [ "79bd2cff7e144ef3d1b093c542ad69302a0138b3", "testharness" @@ -188902,11 +194696,11 @@ "support" ], "navigation-timing/resources/webperftestharness.js": [ - "277312011faf560c6333a0810391e0cf50fdb61d", + "670154a84de50de0c6b310edfeb23a1f3d0d72d1", "support" ], "navigation-timing/test_document_open.html": [ - "13e0ed36e865e06060cfb4cf0d3efc6dfc09d684", + "627ec3a534f3e6ce030a7f5824a67f26f458b091", "testharness" ], "navigation-timing/test_document_readiness_exist.html": [ @@ -188914,71 +194708,71 @@ "testharness" ], "navigation-timing/test_navigate_within_document.html": [ - "c2a4e7340d17ed4dfbe0899e827a96a733997b7d", + "ee8c8581c79be154437e9765885c125d22593b9c", "testharness" ], "navigation-timing/test_navigation_attributes_exist.html": [ - "1dcf7144e6feb00f58fcfdf3c93b6bc65f49ff09", + "a1a9b3ebb814de031920729019d8917ddf906b12", "testharness" ], "navigation-timing/test_navigation_redirectCount_none.html": [ - "5b6f58efd9837f60f47d5ad1a691c8a183b6020b", + "d1308890904883b0a5d684f56b8201f30f8633ff", "testharness" ], "navigation-timing/test_navigation_type_backforward.html": [ - "39bafd06aab6f52e2e61181554cd5d1c0366c6d6", + "5a87b34ea921ef05ee43fe7cc3bdc4d2be56e2fd", "testharness" ], "navigation-timing/test_navigation_type_enums.html": [ - "65927fa5f352377fee57ff4ed86518f36efc4777", + "ca1a454659dd9b0790905ec4ebaa67fee16229c0", "testharness" ], "navigation-timing/test_navigation_type_reload.html": [ - "861072d2026f3fc4e35c7d3caf568eac2c8225a9", + "8b4e1b729a2f97932fe54018c8ea07629fb8ed00", "testharness" ], "navigation-timing/test_no_previous_document.html": [ - "7cf63a018da4a387b7c1f4599f786b6e0cf3211b", + "728aea673231311336585484140f975993198c9b", "testharness" ], "navigation-timing/test_performance_attributes_exist.html": [ - "93bb823553d23292d6f07b24d8d2e99135b5e75f", + "77ce7940ef510aad4545975e717bf5557dbfc948", "testharness" ], "navigation-timing/test_performance_attributes_exist_in_object.html": [ - "f20d7fca8a279f8df8ba221bf229374a387ce29d", + "2ab286b7504e1976d02e6880b758c22fba10ba17", "testharness" ], "navigation-timing/test_readwrite.html": [ - "f210f135fc9eb2040d81b3855eeccf34cfd81a35", + "20507630ddb21872b8eb5f0bca5d62064b8bd0ff", "testharness" ], "navigation-timing/test_timing_attributes_exist.html": [ - "c7d2b16b357482f0da04662d81f0bc1d9ff6696e", + "199aa3389a6a0adf6cb5b18d133c889728cb4411", "testharness" ], "navigation-timing/test_timing_attributes_order.html": [ - "db411d2ac783d49f059d24697fb0bea5e1b382d0", + "7719f088b9ff3bdedb8567ab9eab3f6ca776ecae", "testharness" ], "navigation-timing/test_timing_client_redirect.html": [ - "6d747b5ea0c0f56bbfa4fdbf44924b40fec39b04", + "c6aed0cb03b941e0b8c62a0b086099759b4b25ef", "testharness" ], "navigation-timing/test_timing_reload.html": [ - "8daff711c794f7e4f9d3f4fb4d2ef6df08df8ff9", + "57ba3573d672dbbc60695d049dec39efd5e1feb9", "testharness" ], "navigation-timing/test_timing_server_redirect.html": [ - "199cd011e687ac74b647c7f1fe5214f965d8f85c", + "10b7f221c4667e92a993f0aae70820a95ea445aa", "testharness" ], "navigation-timing/test_timing_xserver_redirect.html": [ - "f0ff9c47a25b6c6a93c6b5e0ffddc3b78444df14", + "a08120e4302c51307fa97de3d521c85c82adb53f", "testharness" ], "navigation-timing/test_unique_performance_objects.html": [ - "c7d89bf7a3119dbfe9a581f82b5ac43ff6645a64", + "b9d933d6a33eabc0b9c9f856c91b802677fa1094", "testharness" ], "notifications/OWNERS": [ @@ -196889,6 +202683,14 @@ "6948dbbdc88ffd9aa84ad5a6c822b354809561b2", "manual" ], + "orientation-sensor/OWNERS": [ + "36770a71443523aa2f91f9958ba24066f0b4dcec", + "support" + ], + "orientation-sensor/idlharness.https.html": [ + "049b5e9505165723cec70237e2ae5f0e2c7948f0", + "testharness" + ], "page-visibility/OWNERS": [ "b82f9756b15ef3ea45fb250e304031d9ceaee9c7", "support" @@ -196897,6 +202699,10 @@ "6bbcc548a783a56340aa256e5f51ca51c1b3f4d3", "testharness" ], + "page-visibility/prerender_call.html": [ + "17f8962a145f6bd7047f236b5b4eb7f825769004", + "testharness" + ], "page-visibility/resources/blank_page_green.html": [ "2d6d55d85e17a9fe978db6dbe25ae35a599d5683", "support" @@ -196905,6 +202711,10 @@ "63604473eabaa8d3b9b410a1a0087d9b4b2e7b90", "support" ], + "page-visibility/resources/prerender_target.html": [ + "9031b355d5f443b5b2f241c471823340a6d501a3", + "support" + ], "page-visibility/test_attributes_exist.html": [ "1fa7511396a6c7f114e31298b8c8ee72e5aac949", "testharness" @@ -196997,10 +202807,18 @@ "29af302db74de64e2bd1352ad92092a309d28c92", "testharness" ], + "payment-request/payment-request-id.https.html": [ + "3e74f97fdf39bb1ca9f2cb5596155705cd15b5b0", + "testharness" + ], "payment-request/payment-request-in-iframe.html": [ "26f2715d33e6d00e5ce03d7b07f35db2ac027acf", "testharness" ], + "payment-request/payment-request-response-id.html": [ + "88df88efdb1d44b56ac9758295f2e2920ae6c9ff", + "support" + ], "performance-timeline/OWNERS": [ "b82f9756b15ef3ea45fb250e304031d9ceaee9c7", "support" @@ -197062,7 +202880,7 @@ "testharness" ], "pointerevents/extension/pointerevent_coalesced_events_attributes-manual.html": [ - "3e8cfad251f604125c570c923b8fbe441f2b5d5b", + "f0393e603c25eb52d5144c95e808f2ab96cbe1f7", "manual" ], "pointerevents/extension/pointerevent_constructor.html": [ @@ -197162,7 +202980,7 @@ "manual" ], "pointerevents/pointerevent_pointerleave_pen-manual.html": [ - "084c13aa90b9cd0e542f3d8d9897964fa1ea01e0", + "6ea8a1bc811c6222ce5dc2c7102d67137152ce41", "manual" ], "pointerevents/pointerevent_pointermove-manual.html": [ @@ -197254,7 +203072,7 @@ "manual" ], "pointerevents/pointerevent_suppress_compat_events_on_drag_mouse-manual.html": [ - "b191ba60977fa384568def97c23d35c204a9ea73", + "074ac2e1e75c974a49f4615924986c7695656094", "manual" ], "pointerevents/pointerevent_touch-action-auto-css_touch-manual.html": [ @@ -197426,7 +203244,7 @@ "testharness" ], "preload/download-resources.html": [ - "f7e3c1ebfbb2b018dd0e5af4a81b0ab0eecac15c", + "c41bf773f52547e930503c588864c42c14416b86", "testharness" ], "preload/dynamic-adding-preload.html": [ @@ -197458,7 +203276,7 @@ "testharness" ], "preload/onload-event.html": [ - "a28bdbf41a8e74bee92ef00e77d283d198a77cfc", + "d00ad51acfea81056a2426d396c3a73d5f15120b", "testharness" ], "preload/preload-csp.sub.html": [ @@ -197470,7 +203288,7 @@ "testharness" ], "preload/preload-with-type.html": [ - "dbae18f696990e4f5b76ca1324141df8ae190fb8", + "b15b6022d8fd4bdc88e7a54429667eb223bc2464", "testharness" ], "preload/resources/dummy.css": [ @@ -197506,7 +203324,7 @@ "testharness" ], "preload/single-download-preload.html": [ - "e83015080694026c96466863c385e3425982479b", + "3ee15736925ad7eed449ff3074353140598461bd", "testharness" ], "presentation-api/OWNERS": [ @@ -197538,7 +203356,7 @@ "manual" ], "presentation-api/controlling-ua/PresentationConnection_send-manual.https.html": [ - "a2c002edf9dcc302390c8695afe1fc04025c32ee", + "4f34387b135ee40a6f8fc363659096409a1eb0bd", "manual" ], "presentation-api/controlling-ua/PresentationRequest_error.https.html": [ @@ -197554,7 +203372,7 @@ "testharness" ], "presentation-api/controlling-ua/PresentationRequest_onconnectionavailable-manual.https.html": [ - "b807b3936cec14007e739de3fc4e5077f67bbd56", + "7fb8f30c04407693c3bf9da9d1ae11937fc1f5c3", "manual" ], "presentation-api/controlling-ua/PresentationRequest_sandboxing_error.https.html": [ @@ -197566,19 +203384,23 @@ "testharness" ], "presentation-api/controlling-ua/PresentationRequest_success.https.html": [ - "b8c26ec718a198562154e75cb32eedfd1778cb01", + "74cc007c2472f11bdc08410f870f270e8e4b0f4a", "testharness" ], "presentation-api/controlling-ua/common.js": [ "6b788aa76cb93a0454839209bb84aa25cd38011f", "support" ], + "presentation-api/controlling-ua/defaultRequest.https.html": [ + "a2e430e3413075293534bf62b23ff0c8c5360282", + "testharness" + ], "presentation-api/controlling-ua/defaultRequest_success-manual.https.html": [ "a09556d22f83c79789942bc3cf316459175aede0", "manual" ], "presentation-api/controlling-ua/getAvailability.https.html": [ - "4a857ebc68eb00bde37206a01f7eae43fe5c1e01", + "80884de4235d7e98137a76c90fcc414efc8d1ac6", "testharness" ], "presentation-api/controlling-ua/getAvailability_sandboxing_success.https.html": [ @@ -197598,7 +203420,7 @@ "testharness" ], "presentation-api/controlling-ua/reconnectToPresentation_success-manual.https.html": [ - "c6fac0eba8eccf9697cc46bcc57e312ab4ab8ac2", + "645e6e6a5a8261c9f3f61c356d6e127aac8223da", "manual" ], "presentation-api/controlling-ua/startNewPresentation_displaynotallowed-manual.https.html": [ @@ -197626,7 +203448,7 @@ "manual" ], "presentation-api/controlling-ua/support/iframe.html": [ - "a827113e644e65e97085658d445a31d0341fa0ef", + "00156d2e5443ad4028af43e1a66ba2fbd226de14", "support" ], "presentation-api/controlling-ua/support/presentation.html": [ @@ -197641,8 +203463,28 @@ "f64f2ab5d0afa93e5adfa327e478936c0e295823", "support" ], + "presentation-api/receiving-ua/PresentationConnectionList_onconnectionavailable-manual.https.html": [ + "ac16b8b189403d4b3c520f69c1675b6acd979e18", + "manual" + ], + "presentation-api/receiving-ua/PresentationConnection_onclose-manual.https.html": [ + "e44406efbfe55bb74ac62d5fae7700102ce8e706", + "manual" + ], + "presentation-api/receiving-ua/PresentationConnection_onmessage-manual.https.html": [ + "3c98bfaf0bc18436501f724210a1f33d9f273573", + "manual" + ], + "presentation-api/receiving-ua/PresentationConnection_send-manual.https.html": [ + "4c699e42e5f19e0b47145b8ce1f235bc14c7cadf", + "manual" + ], + "presentation-api/receiving-ua/PresentationConnection_terminate-manual.https.html": [ + "0a3a7c6265cfd941ea2d394907bb577836bcd49b", + "manual" + ], "presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html": [ - "fc5a9cd4202866b171c74f77c86272fae61ca919", + "1830e4420c668b77dbd835912f518920743c5592", "manual" ], "presentation-api/receiving-ua/cache.txt": [ @@ -197654,15 +203496,35 @@ "support" ], "presentation-api/receiving-ua/idlharness-manual.https.html": [ - "8670eb19b871b3e0f9c04b6f77bf6b313210d0bc", + "fdabdbe847d78dd22754d72ed62f293cd55227ee", "manual" ], "presentation-api/receiving-ua/serviceworker.js": [ "0aeff382c23d0ade231af0f478c40c7aeda626f7", "support" ], + "presentation-api/receiving-ua/support/PresentationConnectionList_onconnectionavailable_receiving-ua.html": [ + "8386247f99e2ef4e1a3378d499a8245d5ff3a5c8", + "support" + ], + "presentation-api/receiving-ua/support/PresentationConnection_onclose_receiving-ua.html": [ + "d925897d1ce2a15545e425d908ed7122ee657137", + "support" + ], + "presentation-api/receiving-ua/support/PresentationConnection_onmessage_receiving-ua.html": [ + "8dc8d4229c03ccc1575ccc2206f85574bbd79500", + "support" + ], + "presentation-api/receiving-ua/support/PresentationConnection_send_receiving-ua.html": [ + "0010c0a25797031ec9f2a3f56864329a43c84f34", + "support" + ], + "presentation-api/receiving-ua/support/PresentationConnection_terminate_receiving-ua.html": [ + "605596c4e21c4b1553fc5d9f26604aa81223ed42", + "support" + ], "presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html": [ - "77e1d610f4cf30f0c9057870e0f4539f83f08222", + "84f37932fc911d5dbf692b42569b564ebf9b8e7d", "support" ], "presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua_child.html": [ @@ -197673,16 +203535,20 @@ "d905cb811f8edb467dc76775fa7ae250c5d9428e", "support" ], - "presentation-api/receiving-ua/support/idlharness_receiving-ua.https.html": [ + "presentation-api/receiving-ua/support/idlharness_receiving-ua.html": [ "adffe1f696cf03f0041383992ab59e47db0ab8c0", "support" ], + "presentation-api/receiving-ua/support/iframe.html": [ + "d52f10c9971a36350150b39c8d3e800c24c941ac", + "support" + ], "presentation-api/receiving-ua/support/serviceworker.js": [ "6aec0aa7cee4f7a63951a41bec757acc6e486397", "support" ], "presentation-api/receiving-ua/support/stash.js": [ - "abaa736a325dd7e7ce12b092e8ee0162122f584d", + "f7a354462a5159ac11e56d13c5972ddfa5af0a70", "support" ], "presentation-api/receiving-ua/support/stash.py": [ @@ -205273,6 +211139,42 @@ "b5c7951856ebacd27c11a0685bb7730f02487fcb", "support" ], + "resource-timing/resource_TAO_match_origin.htm": [ + "32faacb791313be60380fa744608853b24442f42", + "testharness" + ], + "resource-timing/resource_TAO_match_wildcard.htm": [ + "f21fa1fac755e91b21293abfd738a1220cec57c2", + "testharness" + ], + "resource-timing/resource_TAO_multi.htm": [ + "1325e992dd31943fde96038c215a73db1c382ce6", + "testharness" + ], + "resource-timing/resource_TAO_null.htm": [ + "020acb6ea74fec2582c5d3320d91a2f647625f44", + "testharness" + ], + "resource-timing/resource_TAO_origin.htm": [ + "bd7572f9790c69cf76e31c2c1cc7d4c3bd35da4c", + "testharness" + ], + "resource-timing/resource_TAO_origin_uppercase.htm": [ + "83bb18cf7ec915595ad716b2b24e0bb01b7c4047", + "testharness" + ], + "resource-timing/resource_TAO_space.htm": [ + "5e4bf4e71b9b99db494896b1708600224e271fe8", + "testharness" + ], + "resource-timing/resource_TAO_wildcard.htm": [ + "2fbaf85feeb4e621f6e13d67232cc31e221da5d8", + "testharness" + ], + "resource-timing/resource_TAO_zero.htm": [ + "174444cc2f9b8e505bcf35343522f74c792bd997", + "testharness" + ], "resource-timing/resource_cached.htm": [ "819ac54de6901a911a34d63629b9f22be4502f42", "testharness" @@ -205285,6 +211187,10 @@ "1b6e111056101c88623eda6148042c310a5b7a6d", "testharness" ], + "resource-timing/resources/TAOResponse.py": [ + "9e8051a2ff8fff72b36ed1cecb61f9e7bba29071", + "support" + ], "resource-timing/resources/fake_responses.html": [ "c942abc1e8c1672935ffc8ce34821891345bacb9", "support" @@ -205297,6 +211203,42 @@ "dfddf3eb3e80d77163ae12a5df71ed3e9559722a", "support" ], + "resource-timing/resources/iframe_TAO_match_origin.html": [ + "9a3adace2991c7bd1876a904b6c4389633b9828f", + "support" + ], + "resource-timing/resources/iframe_TAO_match_wildcard.html": [ + "243dca266e68cd7a0e42d22a6336026b79849718", + "support" + ], + "resource-timing/resources/iframe_TAO_multi.html": [ + "58394e0163e68665b594d2d73cfccfdf28306e5f", + "support" + ], + "resource-timing/resources/iframe_TAO_null.html": [ + "3a244b286861c68a20ff44c05f7f8590e96cf6d0", + "support" + ], + "resource-timing/resources/iframe_TAO_origin.html": [ + "cf7447fe31cf12d488c432c4c3b93b990949c5ec", + "support" + ], + "resource-timing/resources/iframe_TAO_origin_uppercase.html": [ + "b29b2861966f0a8d0a8827b28885adc48522a324", + "support" + ], + "resource-timing/resources/iframe_TAO_space.html": [ + "80989e08c952b7598a44e73e17f655c0f59ca917", + "support" + ], + "resource-timing/resources/iframe_TAO_wildcard.html": [ + "62e23926dec6ab2bbb1f845582ea488b2619144f", + "support" + ], + "resource-timing/resources/iframe_TAO_zero.html": [ + "9fd73766be85d71a0456cf54dc2407ee74c3d1b8", + "support" + ], "resource-timing/resources/inject_resource_test.html": [ "f53513f6f47fd4a6d4994a4ef7d6e37d1777ea57", "support" @@ -205530,15 +211472,23 @@ "support" ], "selection/collapse-00.html": [ - "6c06617a84c3d4e5f121e4ccf8f7761ba1be1ceb", + "5254f4f69e12405381b474cbdd16725a5f7df599", + "testharness" + ], + "selection/collapse-15.html": [ + "abb690493dd6526a12587cecf43eafb59dc357fd", "testharness" ], "selection/collapse-30.html": [ - "943e7d8960212bc5d5eadb45ff641b9d9525a44a", + "042baecceea3be9b1b828e98e7738a454bf3f8f2", + "testharness" + ], + "selection/collapse-45.html": [ + "a66ab339d964529b3ba8a9af48eb26a4b9b55028", "testharness" ], "selection/collapse.js": [ - "4cd755764b43e348b2dcf23d1c800953ee28f059", + "fdeaf514b240bdeadd89829e3321465d3e376926", "support" ], "selection/collapseToStartEnd.html": [ @@ -205590,7 +211540,7 @@ "testharness" ], "selection/removeAllRanges.html": [ - "23385a72a586db288b282eb251f9384048532666", + "bd203d8878c4de59de476fe6fa7417bd2678dfcc", "testharness" ], "selection/removeRange.html": [ @@ -205609,14 +211559,10 @@ "3803c785b4a2fe2bbf9ecb895e6d3e1ae9e40164", "support" ], - "selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html": [ - "abb13a7744101652436171cf8b62b0722ec71b65", + "selection/type.html": [ + "01ae6e757d428800555012783e290ebba575bcab", "testharness" ], - "selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.js": [ - "a7e8a78780937ab0b83081bba9914aefd931a355", - "support" - ], "selectors/attribute-selectors/attribute-case/cssom.html": [ "a7d352c93c9727bbdae2d44df7ea84baabf16252", "testharness" @@ -205642,13 +211588,37 @@ "testharness" ], "selectors/attribute-selectors/attribute-case/syntax.html": [ - "91d27c834a389e498f2e9c377bdb78eae7130c9e", + "dfb854d30a881f8765c6ee30bc334a440eb59dc2", "testharness" ], "selectors/child-indexed-pseudo-class.html": [ "cdf340dd83ea3a32d0d7edc31b5ded294585ef83", "testharness" ], + "server-timing/resources/blue.png": [ + "7de5cdb5ad04ac365430b3b5f5ba01d2ba57ea23", + "support" + ], + "server-timing/resources/blue.png.sub.headers": [ + "d14ff7ce6dce67417c14192a89f4fe2d31c099a7", + "support" + ], + "server-timing/resources/green.png": [ + "ef91d21307a12b2cfaf33a90dffe16aa1cba42c9", + "support" + ], + "server-timing/resources/green.png.sub.headers": [ + "e2fca01ea5a9c31731a1d5c4199849bf728da892", + "support" + ], + "server-timing/test_server_timing.html": [ + "eab2a2be6984346d7fd83c8f3dcc99b2f3e09a08", + "testharness" + ], + "server-timing/test_server_timing.html.sub.headers": [ + "c49030e9c6dabb55bff24b633b6660212bd2ecca", + "support" + ], "service-workers/OWNERS": [ "b74dce201157af7f50d382583674e1b979237f9b", "support" @@ -205690,27 +211660,31 @@ "support" ], "service-workers/cache-storage/resources/test-helpers.js": [ - "ba4146604450df04ac28946ca886ca90b2883843", + "fc315489c4d337f7cf8395beb4005be9c12da9d6", "support" ], "service-workers/cache-storage/script-tests/cache-add.js": [ - "286214ba5eda836e06f19c2bbc1d6c1fc42cc4fd", + "5807ce231254f89d9e5f2fc43955a8dda5bd865d", "support" ], "service-workers/cache-storage/script-tests/cache-delete.js": [ - "7af12ed2fc082b7efae95f3fb7b241410d2d640f", + "997017dfefc7c1f55cdc3122c2a58ff3d70b8141", + "support" + ], + "service-workers/cache-storage/script-tests/cache-keys.js": [ + "b21b2dda441fcd8fd7e3ae3d60de91bfef0b5f15", "support" ], "service-workers/cache-storage/script-tests/cache-match.js": [ - "7c5daf1029acb604383f20f8bff92db66af0ef51", + "0204ef8205dd31a9af01b3dacd0f2608fa6eb35d", "support" ], "service-workers/cache-storage/script-tests/cache-matchAll.js": [ - "4b4cb079f28e4bcede4b07901f58882d8d2ffcdc", + "381765d1ce951a62d42d7a565f6e856e91ba3f55", "support" ], "service-workers/cache-storage/script-tests/cache-put.js": [ - "3c2022f877364cdd9cd60beec8c7d2e3037a5a4c", + "00d90c0901aef4fd65811cde2daa7da027b46251", "support" ], "service-workers/cache-storage/script-tests/cache-storage-keys.js": [ @@ -205718,11 +211692,11 @@ "support" ], "service-workers/cache-storage/script-tests/cache-storage-match.js": [ - "40856b0d38cdc409e3245a12506ae2c9521625a6", + "e3cc14ea5d0587c43a5b142fca84788383b549cb", "support" ], "service-workers/cache-storage/script-tests/cache-storage.js": [ - "f31eb0025fd3feb3e12c7428c3a048553cdb0492", + "43a44ad35e90ce759de7a855f75b149b756029b4", "support" ], "service-workers/cache-storage/serviceworker/cache-add.https.html": [ @@ -205733,6 +211707,10 @@ "6484fca817f556be3ffead18f162649c0fbfba30", "testharness" ], + "service-workers/cache-storage/serviceworker/cache-keys.https.html": [ + "c1f638bea1f897b086ce403b7a87fe4fd7b77b25", + "testharness" + ], "service-workers/cache-storage/serviceworker/cache-match.https.html": [ "385a521cd183a11c3ab88c8c9e8e22e109691764", "testharness" @@ -205769,6 +211747,10 @@ "8b02db13f96f2d9328e5a7cc4c55dd58bd23618c", "testharness" ], + "service-workers/cache-storage/window/cache-keys.https.html": [ + "be44bcee176090ffc0380cce2611a6e1350bbad7", + "testharness" + ], "service-workers/cache-storage/window/cache-match.https.html": [ "511502a763c53d3fd642aca9e1e1c0c4b610f8ce", "testharness" @@ -205805,6 +211787,10 @@ "6e75a546b1646e8a97aa43aa9cf5434402dca064", "testharness" ], + "service-workers/cache-storage/worker/cache-keys.https.html": [ + "b1a90bfc9676e2cb20316a7a6852a5df016ef797", + "testharness" + ], "service-workers/cache-storage/worker/cache-match.https.html": [ "8149bf9fc2756cdbedbe48d2d5184713d1623ecc", "testharness" @@ -205853,6 +211839,10 @@ "559815205e99f825fdc0a0f2564e7e25586f3c05", "support" ], + "service-workers/service-worker/ServiceWorkerGlobalScope/resources/error-worker.js": [ + "41b92697bbc0b75ce1087f8437afefb52ea7ce7a", + "support" + ], "service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-constructor-worker.js": [ "1ac8fb8c675c398257be0be676872b2944418aa8", "support" @@ -205909,6 +211899,10 @@ "93d2aace8471bcb120a3d7c2029af360220e9b91", "support" ], + "service-workers/service-worker/ServiceWorkerGlobalScope/service-worker-error-event.https.html": [ + "f5f263a3c0f9e154f8b43425f3f42cb792f483a3", + "testharness" + ], "service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html": [ "9fe4c10b921a84dc086cea47d48bb34fdbb28eee", "testharness" @@ -205957,20 +211951,28 @@ "dac61fcadc94d01fa1f46ac65d81c0405d90ecd3", "testharness" ], + "service-workers/service-worker/client-id.https.html": [ + "bc07ff54eaf1fecc2a46ebcf34059590ac8c866d", + "testharness" + ], "service-workers/service-worker/client-navigate.https.html": [ "c0403a4538bf063745a59f5848e30b13d1b3afc1", "testharness" ], + "service-workers/service-worker/clients-get-client-types.https.html": [ + "e86b86beb47802f4204510c44edc1465cab5d5f2", + "testharness" + ], "service-workers/service-worker/clients-get-cross-origin.https.html": [ - "21ed1eab21bb6f0b342895c8185ecb92afe93b79", + "56d9095dde507aadbd47d3b27d304825b5b8198e", "testharness" ], "service-workers/service-worker/clients-get.https.html": [ - "32ccf7734a7d0d40205c4fd30b393b175e6507bd", + "3627915a40ca2903f979560209f9a169a41429e2", "testharness" ], "service-workers/service-worker/clients-matchall-client-types.https.html": [ - "aaca38d0ad5e6a03775632fcef1657dd40753ae0", + "02003bd248ffb0d54238339179105836ac7c4e14", "testharness" ], "service-workers/service-worker/clients-matchall-exact-controller.https.html": [ @@ -205981,6 +211983,10 @@ "a4f4cb575ffea826c642aa3de424c0a0f986fdd0", "testharness" ], + "service-workers/service-worker/clients-matchall-on-evaluation.https.html": [ + "9737491d653de76a70f9c0143baa70760f2f95c4", + "testharness" + ], "service-workers/service-worker/clients-matchall-order.https.html": [ "b2617b7dce0dce64c1a354a3dc07c67f1fa0adf2", "testharness" @@ -206006,7 +212012,7 @@ "testharness" ], "service-workers/service-worker/extendable-event-waituntil.https.html": [ - "9232c93bc437aa6c32a2a82db03e622b96d23395", + "401235c18e1594c7248b22eb6881d54801de9809", "testharness" ], "service-workers/service-worker/fetch-canvas-tainting-cache.https.html": [ @@ -206022,7 +212028,7 @@ "testharness" ], "service-workers/service-worker/fetch-csp.https.html": [ - "97fff975592937acda3e8f363685dc9a835c12be", + "acf1f933e5c399812c767b0ee0fc4aa9fbd08bab", "testharness" ], "service-workers/service-worker/fetch-event-after-navigation-within-page.https.html": [ @@ -206030,19 +212036,23 @@ "testharness" ], "service-workers/service-worker/fetch-event-async-respond-with.https.html": [ - "6ea721f98b2d145eeeb07b762901b9cfa1b51fbd", + "00c90429203c85ae8f10a6a6604cdf9619524f06", "testharness" ], "service-workers/service-worker/fetch-event-network-error.https.html": [ - "ee1cd2ed2c3204af53422116289c558f5eff68d9", + "07b81a0af207ee0723a9abae90e49482701f8935", "testharness" ], "service-workers/service-worker/fetch-event-redirect.https.html": [ "2a6f2d4f818ac325edd9c69c1b08801961728b20", "testharness" ], + "service-workers/service-worker/fetch-event-respond-with-argument.https.html": [ + "ce7e7cf76aace24a92d455cdb6b54fc9048960e8", + "testharness" + ], "service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html": [ - "2feaa5022ee31fb980f97075d932b0d87d6efe75", + "7d9e18d316c74f2b887f01a4576eb14b10d99b14", "testharness" ], "service-workers/service-worker/fetch-event-throws-after-respond-with.https.html": [ @@ -206058,7 +212068,7 @@ "testharness" ], "service-workers/service-worker/fetch-event.https.html": [ - "fb2b3ea20415d9148cfda983ac785f0de16e6889", + "9f991210c315a2d436f760b099a43871692c64c4", "testharness" ], "service-workers/service-worker/fetch-frame-resource.https.html": [ @@ -206134,7 +212144,7 @@ "testharness" ], "service-workers/service-worker/getregistrations.https.html": [ - "d76c66c08bd5c1addbdb149447f2268ac52ffcb2", + "15c2be991ec5b02a0aecf54e6c7bb455f240141d", "testharness" ], "service-workers/service-worker/indexeddb.https.html": [ @@ -206150,7 +212160,7 @@ "testharness" ], "service-workers/service-worker/interfaces.https.html": [ - "9153cc6536203170ba8d2189d7646200a1ded72e", + "f5e18c249ad8264548923f3c875ffeff523ab424", "testharness" ], "service-workers/service-worker/invalid-blobtype.https.html": [ @@ -206229,6 +212239,10 @@ "fd50f2fd601e136d12fe815e6c1b8d5803663449", "testharness" ], + "service-workers/service-worker/navigation-preload/resource-timing.https.html": [ + "837273105d7a1521feff32338cdef7185a6786e3", + "testharness" + ], "service-workers/service-worker/navigation-preload/resources/broken-chunked-encoding-scope.asis": [ "d1fd50a8f194803dcc0c0f6d74bdc57197c3d6e5", "support" @@ -206281,6 +212295,14 @@ "0c02f9eb1f83a96f16d1d0f82669c78cc26e662d", "support" ], + "service-workers/service-worker/navigation-preload/resources/resource-timing-scope.py": [ + "817076c96f471bbdd8795478c70c7141cb1a5d24", + "support" + ], + "service-workers/service-worker/navigation-preload/resources/resource-timing-worker.js": [ + "8eb75e9bb7e3aaec818427b5f101a5d2353e65bf", + "support" + ], "service-workers/service-worker/navigation-preload/resources/wait-for-activate-worker.js": [ "a6ac7ce51f0c0ea47f2d9bbeb44d8db7d3f7864f", "support" @@ -206417,6 +212439,10 @@ "e779a28c42928ff10219073171c1216c6623b4d4", "support" ], + "service-workers/service-worker/resources/client-id-worker.js": [ + "7acc5dacbe27fb1a75bf8f5e4b6266c783368056", + "support" + ], "service-workers/service-worker/resources/client-navigate-frame.html": [ "ecad40948e5d00ca737ea91b702ebbecc268e53b", "support" @@ -206429,6 +212455,18 @@ "efb9dd2b3468305396a3767fc780d07525bd8e61", "support" ], + "service-workers/service-worker/resources/clients-get-client-types-frame.html": [ + "b41374d117b96fd2a702b7de3b6df08365032c95", + "support" + ], + "service-workers/service-worker/resources/clients-get-client-types-shared-worker.js": [ + "801473dd69333f8081201ed0f3d7f53cca30753b", + "support" + ], + "service-workers/service-worker/resources/clients-get-cross-origin-frame.html": [ + "a883adc270b47c6a104d10fd7dd9e6bc32c31315", + "support" + ], "service-workers/service-worker/resources/clients-get-frame.html": [ "2a34fdfb584674ef7b534fb91b313fc630ac0ffa", "support" @@ -206438,19 +212476,23 @@ "support" ], "service-workers/service-worker/resources/clients-get-worker.js": [ - "cab646738d3d9662756dcd337718ae02ea234313", + "7b9493735cdb2d06bab7331d1840c34631e04e32", "support" ], "service-workers/service-worker/resources/clients-matchall-client-types-iframe.html": [ - "3c8866699d99cfaf61c52ca7a5dafc058a8c349d", + "267de6ff27e4227682bbfdb86aeb3111d36d62cb", "support" ], "service-workers/service-worker/resources/clients-matchall-client-types-shared-worker.js": [ "5478ccfd9942f5ccb8335e6e13b52722b22e06d8", "support" ], + "service-workers/service-worker/resources/clients-matchall-on-evaluation-worker.js": [ + "e92684d1db4e8aef274fdd5e30abea48490b5659", + "support" + ], "service-workers/service-worker/resources/clients-matchall-worker.js": [ - "88326b2119c68ba656c62a74b9c1af201bca1548", + "1557f173e6cc5d1540ed9d78e8c9216b312fabb5", "support" ], "service-workers/service-worker/resources/dummy-shared-worker-interceptor.js": [ @@ -206506,7 +212548,7 @@ "support" ], "service-workers/service-worker/resources/extendable-event-waituntil.js": [ - "f3506e9043b7d2163f486ae8461caecca3b63320", + "99b76538a42556ac6e588a246b6a25bf7aec9cc5", "support" ], "service-workers/service-worker/resources/fail-on-fetch-worker.js": [ @@ -206530,7 +212572,7 @@ "support" ], "service-workers/service-worker/resources/fetch-csp-iframe.html": [ - "0c82ccc773dc644bac0cef39faadcb3280c0c6f4", + "2c5420e191b2b891233d0c99624f022c1bb936fa", "support" ], "service-workers/service-worker/resources/fetch-csp-iframe.html.sub.headers": [ @@ -206557,12 +212599,20 @@ "f24007259baeab7e9a6932d35e0b2a5305b159a4", "support" ], + "service-workers/service-worker/resources/fetch-event-respond-with-argument-iframe.html": [ + "4a9d7e189909b5adfdd4d1c0ebddb7cd90fde159", + "support" + ], + "service-workers/service-worker/resources/fetch-event-respond-with-argument-worker.js": [ + "b58b92a145a89f71c414de5e837c1db026beb1d6", + "support" + ], "service-workers/service-worker/resources/fetch-event-respond-with-stops-propagation-worker.js": [ "900fd1c2080fbb386589f7d6ee52c49da9d4fcb8", "support" ], "service-workers/service-worker/resources/fetch-event-test-worker.js": [ - "ca79da139169762737411cb6cffb66b55b901d04", + "f9eab9a493f43ec5a8a662815a979e70fb3e3900", "support" ], "service-workers/service-worker/resources/fetch-event-within-sw-worker.js": [ @@ -206681,6 +212731,10 @@ "c5f88c11333ff1faba5d57812a36553d174ab711", "support" ], + "service-workers/service-worker/resources/import-mime-type-worker.py": [ + "7881cd81f7fe54bf3be799f3549098c78b896574", + "support" + ], "service-workers/service-worker/resources/indexeddb-worker.js": [ "ed0ff45423ba74ad0b82e46debd865fdae2fbcb6", "support" @@ -206694,7 +212748,7 @@ "support" ], "service-workers/service-worker/resources/interfaces-worker.sub.js": [ - "67190b30c485fe743de1515fe5c593aad584fcb3", + "c94ee8dee0233f31c4f1577bf8b4bda5d2be2209", "support" ], "service-workers/service-worker/resources/interfaces.js": [ @@ -206862,7 +212916,7 @@ "support" ], "service-workers/service-worker/resources/registration-tests.js": [ - "5588535a80930c1d526d3b94ec7930a191d729db", + "bdb31335f8d15de455108e0186183f1acdaef41e", "support" ], "service-workers/service-worker/resources/registration-worker.js": [ @@ -207421,6 +213475,10 @@ "fa2864cbf8e88250a793beeacf737c7d9413cdf2", "testharness" ], + "shadow-dom/slots-fallback-in-document.html": [ + "eac2fee4991725b4d2ca104a586c02d109b7d721", + "testharness" + ], "shadow-dom/slots-fallback.html": [ "595bf7e71283bcf219849ebe13a1b913cd36f1b9", "testharness" @@ -207713,6 +213771,14 @@ "bc28599cea839c13daf4739168f8c1ea42526050", "testharness" ], + "staticrange/OWNERS": [ + "290c71b49f1147778f51898e114db808b4568549", + "support" + ], + "staticrange/idlharness.html": [ + "16f30a68d97edf19c5255328fd1460ac54a4c025", + "testharness" + ], "storage/OWNERS": [ "2c585ecaee5e62118d3cb98c98e12d959ebcbd50", "support" @@ -207757,6 +213823,14 @@ "98be04abdc48c76b30f90af007f214f9759083dd", "testharness" ], + "storage/resources/storagemanager-persist-worker.js": [ + "a9d24b2477938410371bae881a05a68cd56fe72e", + "support" + ], + "storage/resources/storagemanager-persisted-worker.js": [ + "a8031dd016d09d623fd438cee7e78f0a214936d9", + "support" + ], "storage/storage-estimate-indexeddb.js": [ "660d3d068314c34d215df19c0b849ec711f57854", "support" @@ -207765,6 +213839,26 @@ "dbf6e5bed3dec6ca59926c439ec9d6aca89d78b9", "support" ], + "storage/storagemanager-estimate.https.html": [ + "6319416d647f1671a7b8d36bbb4d79495e76a956", + "testharness" + ], + "storage/storagemanager-persist-worker.https.html": [ + "d51415a75f68ae5b2f8b537e25fea6f555192529", + "testharness" + ], + "storage/storagemanager-persist.https.html": [ + "88e43b4e061a7577fb0030eb0343e1e6c1cd9b6a", + "testharness" + ], + "storage/storagemanager-persisted-worker.https.html": [ + "b59e7df0e84747adbea6f281e6ecdd6d9d8435f0", + "testharness" + ], + "storage/storagemanager-persisted.https.html": [ + "a48435451fe9498f3aa7427c695c2e3407876d9b", + "testharness" + ], "streams/OWNERS": [ "5ed27d1c21178be00e972816933945e094a0e170", "support" @@ -207846,7 +213940,7 @@ "testharness" ], "streams/piping/close-propagation-forward.js": [ - "0846ba92abb8ace6c5438d918b2db23badc090b2", + "955736af478e8ec307dfe00a461f4b72949b110d", "support" ], "streams/piping/close-propagation-forward.serviceworker.https.html": [ @@ -207906,7 +214000,7 @@ "testharness" ], "streams/piping/flow-control.js": [ - "c39ecfb633e95ce4b4eac41d33d7268d3a5f768b", + "5f0665dd1618dc75423862d26debeac05caacac9", "support" ], "streams/piping/flow-control.serviceworker.https.html": [ @@ -207946,7 +214040,7 @@ "testharness" ], "streams/piping/multiple-propagation.js": [ - "c2a5c855e9abbacfe500a9339ff586a16bb8ae7a", + "8d00cd13d84d421a297bff499511d96f7b72c98c", "support" ], "streams/piping/multiple-propagation.serviceworker.https.html": [ @@ -207966,7 +214060,7 @@ "testharness" ], "streams/piping/pipe-through.js": [ - "08daa95df8e64c57f082b297ffd8bd11cda54d26", + "bf2cebbca84051b446f728d92c065869207299f2", "support" ], "streams/piping/pipe-through.serviceworker.https.html": [ @@ -208006,7 +214100,7 @@ "testharness" ], "streams/readable-byte-streams/general.js": [ - "b5d2f4c72f2e365e0716897a2fd398600e4eac6c", + "e8d971fb6491da06f9ceedb1b6cd6a5c06b6f3b4", "support" ], "streams/readable-byte-streams/general.serviceworker.https.html": [ @@ -208146,7 +214240,7 @@ "testharness" ], "streams/readable-streams/floating-point-total-queue-size.js": [ - "9e6ba92e9b69437c23f04c80fff47c951e509db1", + "905ea4815c8444a70d1fe3a2e1c2c36ff259c285", "support" ], "streams/readable-streams/floating-point-total-queue-size.serviceworker.https.html": [ @@ -208258,7 +214352,7 @@ "testharness" ], "streams/resources/recording-streams.js": [ - "64f85212b966489f92c7379e270dd0ed5a9ddb8d", + "df4bb8dab4b7e70758f87822c0472e96baec8b45", "support" ], "streams/resources/rs-test-templates.js": [ @@ -208282,7 +214376,7 @@ "testharness" ], "streams/writable-streams/aborting.js": [ - "2a0695350efde1366b5123ade654bea8a7b27e42", + "73be2b0af40871af1e2cd65d99f4591d45cee3aa", "support" ], "streams/writable-streams/aborting.serviceworker.https.html": [ @@ -208382,7 +214476,7 @@ "testharness" ], "streams/writable-streams/close.js": [ - "fce65083e9b7c69d52d696948669df92456422ed", + "a0f0183652427bdcd049eac90eb52d1ba5e09110", "support" ], "streams/writable-streams/close.serviceworker.https.html": [ @@ -208402,7 +214496,7 @@ "testharness" ], "streams/writable-streams/constructor.js": [ - "cc69b69308c1c51832488909cf962e580ff1dc3c", + "0f67e4c79f7a7d32c29b14b917e8921dbb3171c1", "support" ], "streams/writable-streams/constructor.serviceworker.https.html": [ @@ -208433,6 +214527,26 @@ "875e0dffe7710c21bfcb8f554c2216626c2eb013", "testharness" ], + "streams/writable-streams/error.dedicatedworker.html": [ + "c1876a4e28900174a13d59d82acb4e60e7b4a965", + "testharness" + ], + "streams/writable-streams/error.html": [ + "9d020a2e9a22b420997c301ca732a406ed53c21d", + "testharness" + ], + "streams/writable-streams/error.js": [ + "4d453557abcefc69168fa399e04226f37dbf1142", + "support" + ], + "streams/writable-streams/error.serviceworker.https.html": [ + "d8a0b8b68a7a59c9bf186336a6e22f34912fb7e5", + "testharness" + ], + "streams/writable-streams/error.sharedworker.html": [ + "0eaf67b6f635e95fe96a95082d4015cc9f427eef", + "testharness" + ], "streams/writable-streams/floating-point-total-queue-size.dedicatedworker.html": [ "e07b6c46f7975b76a309ac9b728e4215d5e7fe9d", "testharness" @@ -208442,7 +214556,7 @@ "testharness" ], "streams/writable-streams/floating-point-total-queue-size.js": [ - "14d4a8f5559831fb266061e75177339ba0073edb", + "33db80c0ab6a4794e26816d83e6ece39b707ed63", "support" ], "streams/writable-streams/floating-point-total-queue-size.serviceworker.https.html": [ @@ -208462,7 +214576,7 @@ "testharness" ], "streams/writable-streams/general.js": [ - "7a6fb1ccd2f77edc2077ec127716d3d2edcf8475", + "4f07b059c3b2d90ca0c08ffe014e3e77ade70be0", "support" ], "streams/writable-streams/general.serviceworker.https.html": [ @@ -208473,6 +214587,26 @@ "44f9ceaa3bfc9d8b92885997d322486bd0f237a6", "testharness" ], + "streams/writable-streams/properties.dedicatedworker.html": [ + "0d766237560b16ddb1bfcd02e701089132f1b3ec", + "testharness" + ], + "streams/writable-streams/properties.html": [ + "82a278a1e8599b5bbd1ab8abadfb13d85f45aa5e", + "testharness" + ], + "streams/writable-streams/properties.js": [ + "651d62037ceff95818e8cd33c078a31e09dafd5c", + "support" + ], + "streams/writable-streams/properties.serviceworker.https.html": [ + "2ef8fc878249c429a89e0748e6a98fac47c1a99a", + "testharness" + ], + "streams/writable-streams/properties.sharedworker.html": [ + "5c855e897d1143092ecc10b58268e6a576882184", + "testharness" + ], "streams/writable-streams/reentrant-strategy.dedicatedworker.html": [ "5d9e5a6b69fbe79183ac6e0d2c8559f13be6e386", "testharness" @@ -208502,7 +214636,7 @@ "testharness" ], "streams/writable-streams/start.js": [ - "09fcde6f0a4652c9549a6d94206e0403a7d86046", + "efd4b220ff356a542efdd57293993e5deff3a884", "support" ], "streams/writable-streams/start.serviceworker.https.html": [ @@ -210826,7 +216960,7 @@ "support" ], "svg/interfaces.html": [ - "fed926aefa9ebdf5f3972c6f1ee13af006c04545", + "0c355e7adc334d000991f4181d3bf254302eb915", "testharness" ], "svg/linking/reftests/href-a-element-attr-change.html": [ @@ -211009,12 +217143,16 @@ "bf426dc592940dbabd23db6c2343bcc5d29dc4b8", "support" ], + "uievents/auxclick/auxclick_event-manual.html": [ + "464073435190f51b2725653a0a0589e10f136d2d", + "manual" + ], "uievents/constructors/README.md": [ "771f659821e2860457b741385606f714acc01e05", "support" ], "uievents/constructors/inputevent-constructor.html": [ - "757b9777e0cd956a27f036a1524c378bd922852b", + "5af5377e8f5435b7c7bfafa2808e0a8dcf848ce4", "testharness" ], "uievents/hierarchy/README.md": [ @@ -211333,6 +217471,10 @@ "58f5c03e1f544b12e467663cc2bc0c15673f80b9", "support" ], + "uievents/mouse/mouseevent_move_button-manual.html": [ + "9cc673035fef3c2e8677e8d6679babfe8a1af854", + "manual" + ], "uievents/order-of-events/README.md": [ "3a3e6ab77d25a8fe83085e24c0934e4b63eea553", "support" @@ -211430,7 +217572,7 @@ "support" ], "url/README.md": [ - "3dacc2783865ba292f20b72bc4c3942de521d9b0", + "165b2a70da8bc2a7df3fe424a540f36b4f7be899", "support" ], "url/a-element-origin-xhtml.xhtml": [ @@ -211458,15 +217600,11 @@ "support" ], "url/failure.html": [ - "900755b25db687f1e793fe4cf18cfc456c35060a", + "908456e354703473b0806bbdac6d60216505905f", "testharness" ], - "url/historical.html": [ - "94451e509174184811374cb8f0a346e76510eb54", - "testharness" - ], - "url/historical.worker.js": [ - "d49e244853c361ad0d62269f48c8c5fe2661bc8f", + "url/historical.any.js": [ + "89dd0f84e69896c802c7a2062c9f4846cdca98c6", "testharness" ], "url/interfaces.html": [ @@ -211502,7 +217640,7 @@ "testharness" ], "url/urlsearchparams-constructor.html": [ - "81ea36ecd56373eb88984d6b488c71210ade2419", + "854e06efa9598f66705605bdef20c4a500ab2e9b", "testharness" ], "url/urlsearchparams-delete.html": [ @@ -211538,7 +217676,7 @@ "testharness" ], "url/urltestdata.json": [ - "6aa13a2c98f03031f1225a035890fc77a76efc52", + "f99eff3fa00a813fc77deaee2d2c08a19df10af9", "support" ], "user-timing/OWNERS": [ @@ -211598,7 +217736,7 @@ "testharness" ], "user-timing/measure.html": [ - "9b753ac314aabc2e4ec6aee7381b956e7f345b78", + "8374bbae73ac549b6c8b953d25948ed33b579591", "testharness" ], "user-timing/measure_exceptions_navigation_timing.html": [ @@ -211606,7 +217744,7 @@ "testharness" ], "user-timing/measure_navigation_timing.html": [ - "9bc61c9ae7d5c83f883270c98db6cd088bb0ecd2", + "b54bbb96f5c24b61e4d64a3633229781213d9cd2", "testharness" ], "user-timing/measure_syntax_err.any.js": [ @@ -211614,7 +217752,7 @@ "testharness" ], "user-timing/resources/webperftestharness.js": [ - "8b534ce21f036d46da0183bd36676c7b0a2f468d", + "b1f81236de54467168bd09d749c2a6f453c5c3e1", "support" ], "user-timing/resources/webperftestharnessextension.js": [ @@ -211686,13 +217824,905 @@ "manual" ], "wai-aria/OWNERS": [ - "16577d2283b826f0541dbc795177c7aac7e1b228", + "3a6002295ea2893ba74763e46965bd2d1291d55b", "support" ], "wai-aria/README.md": [ "fcb3247bdc42a962ad609232f3be562d13d630e3", "support" ], + "wai-aria/alertdialog_modal_false-manual.html": [ + "0de73d9a74e7f78a9476bba21b864475de8a7c8f", + "manual" + ], + "wai-aria/alertdialog_modal_true-manual.html": [ + "29a80fa8a8591c807adbb00270f0414bb698d323", + "manual" + ], + "wai-aria/application_activedescendant-manual.html": [ + "bb1908682085e0fe5e6f8f8361719c54256c06d9", + "manual" + ], + "wai-aria/application_activedescendant_value_changes-manual.html": [ + "7807dfc3aeca40e8ad49552e776f57d47e0178a9", + "manual" + ], + "wai-aria/aria-current_not_declared-manual.html": [ + "09820c997597e553a63e00c221b7e4b84f046502", + "manual" + ], + "wai-aria/aria-current_with_value_changes-manual.html": [ + "6d54a2b300e056dfcde46e9927290181feac7134", + "manual" + ], + "wai-aria/aria-current_with_value_date-manual.html": [ + "30803e78105fafc30a07c216f120364a707ebac9", + "manual" + ], + "wai-aria/aria-current_with_value_location-manual.html": [ + "4f9d6be77ffc0b23931a888de25f0a66223bcbd6", + "manual" + ], + "wai-aria/aria-current_with_value_page-manual.html": [ + "92177233e85d8fb360d0524a127a31fc6bbc22cc", + "manual" + ], + "wai-aria/aria-current_with_value_step-manual.html": [ + "f1fafedacdca36c23a612c699124efc2f0248e15", + "manual" + ], + "wai-aria/aria-current_with_value_time-manual.html": [ + "8b88be430db3fd4b9b05ab214a38389448150521", + "manual" + ], + "wai-aria/aria-current_with_value_true-manual.html": [ + "f9df9114542cd0fc91325634ec29db307ca101a6", + "manual" + ], + "wai-aria/aria-current_with_value_unspecified-manual.html": [ + "03743f07be87703262043f210f7ec2befc11ebd0", + "manual" + ], + "wai-aria/aria-details_pointing_to_details_element-manual.html": [ + "ad05a971809cfd9cd5e6d63ab886c481323ebdc6", + "manual" + ], + "wai-aria/aria-details_pointing_to_div_element-manual.html": [ + "f2d2d715de30a4edc1ef3d4d75a13ec02562ced8", + "manual" + ], + "wai-aria/article_in_feed_posinset_and_setsize-manual.html": [ + "8cba7e2c8d9fa2790bca392da39d14c7402ca6e4", + "manual" + ], + "wai-aria/article_in_feed_setsize_-1-manual.html": [ + "2a3820bd35c9de6efdbdd8944e66e1c129522abe", + "manual" + ], + "wai-aria/article_not_in_feed_posinset_and_setsize-manual.html": [ + "5074dfe55d125288b51081b9fdd78c78400b563d", + "manual" + ], + "wai-aria/button_haspopup_dialog-manual.html": [ + "c31b9e0b6f4a0ecebfb0ced36198110b8481167d", + "manual" + ], + "wai-aria/button_haspopup_emptystring-manual.html": [ + "526ed0373a6730ff4c2aad3bdb644029f673d046", + "manual" + ], + "wai-aria/button_haspopup_false-manual.html": [ + "c2b1e86859ef7cd770a0f2fd7de82155a3968315", + "manual" + ], + "wai-aria/button_haspopup_foo-manual.html": [ + "4f3c0d8f93cf46ec8ff58d7ff33fe61146f1f73f", + "manual" + ], + "wai-aria/button_haspopup_grid-manual.html": [ + "147b1fa883ecf96f992a24bf6aee032a69ce14c7", + "manual" + ], + "wai-aria/button_haspopup_listbox-manual.html": [ + "139d8ebf9b91bc019da5a14656d7f9e5a26f4ae5", + "manual" + ], + "wai-aria/button_haspopup_menu-manual.html": [ + "524f95729ccb3ec81450f3b5c112efa7ccdc1357", + "manual" + ], + "wai-aria/button_haspopup_tree-manual.html": [ + "a21792deec4d3448f0110f1b88bcd87611ca9213", + "manual" + ], + "wai-aria/button_haspopup_true-manual.html": [ + "e48345755b57d0d4d8b08ba1d2805ce51835c020", + "manual" + ], + "wai-aria/button_haspopup_unspecified-manual.html": [ + "5433922f0ab71e390ca9e0e7a46551ebfd44dc87", + "manual" + ], + "wai-aria/button_roledescription_empty-manual.html": [ + "066f803e5809813e84a2fffecb39142429191f3e", + "manual" + ], + "wai-aria/button_roledescription_valid-manual.html": [ + "6d18a279c9a9e471fad81c1313db3b9d04999ea0", + "manual" + ], + "wai-aria/button_roledescription_whitespace_only-manual.html": [ + "b8a231f8bad4cb5626b7b687d81067ebe891b961", + "manual" + ], + "wai-aria/cell-manual.html": [ + "1ea5f605642328e07a67d78d96a59849b3439120", + "manual" + ], + "wai-aria/cell_aria-colspan_2_on_div-manual.html": [ + "dea621a29ab297b8ea3035806a7d86265faa0976", + "manual" + ], + "wai-aria/cell_aria-colspan_2_on_td_html_colspan_3-manual.html": [ + "fe72cecdfd9b60e0f5346a1848e19c7b1adbcd62", + "manual" + ], + "wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_headers_and_border-manual.html": [ + "524d5318a2fb71e71979679647219ccdf59de427", + "manual" + ], + "wai-aria/cell_aria-colspan_2_on_td_with_html_colspan_not_specified-manual.html": [ + "7b444106d30350596a9fb81c54845754a806077b", + "manual" + ], + "wai-aria/cell_aria-rowspan_2_on_div-manual.html": [ + "83af1369b5ea45e943d59deeca46a4b517436850", + "manual" + ], + "wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3-manual.html": [ + "a2d5c2e0c438ce16ae5a4b6ef5032e738d3bac7a", + "manual" + ], + "wai-aria/cell_aria-rowspan_2_on_td_with_html_rowspan_not_specified-manual.html": [ + "c92a991cb963082cdcbf2d90489e8d01d34f880e", + "manual" + ], + "wai-aria/cell_colindex_4-manual.html": [ + "03653417d9dccc42a392c3dd672fd26be29a0afe", + "manual" + ], + "wai-aria/cell_rowindex_4-manual.html": [ + "cdf0f7eb47b9d49b54bf0f4831311a47acdcddb3", + "manual" + ], + "wai-aria/checkbox_readonly_false-manual.html": [ + "fce2224ea02feb9886abd11eae61fec3eb295dd4", + "manual" + ], + "wai-aria/checkbox_readonly_true-manual.html": [ + "9ee1117041827f9ae7a720d52bd31abeefddbede", + "manual" + ], + "wai-aria/checkbox_readonly_unspecified-manual.html": [ + "ed1c64acd3f88485e7e9879848e63a7a6448f05a", + "manual" + ], + "wai-aria/columnheader_aria-colspan_2_on_div-manual.html": [ + "5cef610d8ef44e4cfb3a105dacae722f8c16924c", + "manual" + ], + "wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3-manual.html": [ + "8f7d23287ebc7a0f4fd8f538761a6fdcb8d4db70", + "manual" + ], + "wai-aria/columnheader_aria-colspan_2_on_th_with_html_colspan_not_specified-manual.html": [ + "182848b4c055b72f21b7f05802b12f07931a8936", + "manual" + ], + "wai-aria/columnheader_aria-rowspan_2_on_div-manual.html": [ + "14bcb535040d7ec7d1463f9dabb77c8d5a4579fd", + "manual" + ], + "wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3-manual.html": [ + "b89d3ad4a1452afa883969eee6b426eb42e1d7f7", + "manual" + ], + "wai-aria/columnheader_aria-rowspan_2_on_th_with_html_rowspan_not_specified-manual.html": [ + "4031b040bcda345c04073053556445019574751b", + "manual" + ], + "wai-aria/columnheader_colindex_4-manual.html": [ + "2e46afcd1e0c0c6639dde5d4bdb64829f4cd0298", + "manual" + ], + "wai-aria/columnheader_rowindex_4-manual.html": [ + "6a48e170e90a355cf9f99842f14fc178620800bc", + "manual" + ], + "wai-aria/columnheader_selected_false_not_automatically_propagated-manual.html": [ + "884096f6c1033f184d3cb8aa3c4afdfff377acf7", + "manual" + ], + "wai-aria/columnheader_selected_true_not_automatically_propagated-manual.html": [ + "92bbb16b4e4325da1f29c3886e19e0a2bdefed3a", + "manual" + ], + "wai-aria/combobox_controls_an_invalid_id-manual.html": [ + "a7428f00c7a7c1b7ec4571b053ed3f97b370d6a7", + "manual" + ], + "wai-aria/combobox_haspopup_dialog-manual.html": [ + "1763643ee1772e4e44f694be1161b7d9c4fb4ccd", + "manual" + ], + "wai-aria/combobox_haspopup_false-manual.html": [ + "cd628b6f7a53d048283395adf1ba5e1ca9aa3983", + "manual" + ], + "wai-aria/combobox_haspopup_grid-manual.html": [ + "a725532a4475cbba01a815fc0b70d7a9f18ca38f", + "manual" + ], + "wai-aria/combobox_haspopup_listbox-manual.html": [ + "66ad33bdc43763064bede6f49423c669fd6c8b54", + "manual" + ], + "wai-aria/combobox_haspopup_menu-manual.html": [ + "77eaf2adc1234c46b8d7f5016351f8f92734ce55", + "manual" + ], + "wai-aria/combobox_haspopup_tree-manual.html": [ + "023ba0b8badbeba32333d3283922054d5577ea57", + "manual" + ], + "wai-aria/combobox_haspopup_true-manual.html": [ + "11f474e4da6b76c9e9a74bf846f7209a9b040b08", + "manual" + ], + "wai-aria/combobox_haspopup_unspecified-manual.html": [ + "8285f5e4ca013a53f7fef22b3254ac34724d1e74", + "manual" + ], + "wai-aria/combobox_orientation_horizontal-manual.html": [ + "e8eb60d4d9a0850511cdee7a3e19ba5c2fb14c73", + "manual" + ], + "wai-aria/combobox_orientation_unspecified-manual.html": [ + "7c7b15f4586f4f84a0b6d40f2c8285de78d904be", + "manual" + ], + "wai-aria/combobox_orientation_vertical-manual.html": [ + "ed213ba95cac717ec3b4910f6a97ce713ecd00cc", + "manual" + ], + "wai-aria/combobox_readonly_false-manual.html": [ + "bbb7298bbf9f33e6ebe54bf392ef8a802d7d4cc5", + "manual" + ], + "wai-aria/combobox_readonly_true-manual.html": [ + "164858f5c1ce2f9daaf2a5d56485d8a5b6c1ed37", + "manual" + ], + "wai-aria/combobox_readonly_unspecified-manual.html": [ + "a4dda746a9b77935eee233e82ca70678e4dd5af4", + "manual" + ], + "wai-aria/dialog_modal_false-manual.html": [ + "3623f1024b0ab26ab2b6d48bc78e9fc4699ea584", + "manual" + ], + "wai-aria/dialog_modal_true-manual.html": [ + "c0ec6e36a67b7ba42b0076350e0876866be17d61", + "manual" + ], + "wai-aria/dialog_modal_unspecified-manual.html": [ + "41baed7d9e1e5d6512d3240bdbabb2db45b99436", + "manual" + ], + "wai-aria/div_element_without_role_roledescription_valid-manual.html": [ + "1f7fcd4985675b15c9a97f536c694ca8e2359856", + "manual" + ], + "wai-aria/errormessage_object_in_invalid_state-manual.html": [ + "0c7a38f437ccc80e81dbc8f11a70e695ff5c742a", + "manual" + ], + "wai-aria/errormessage_object_in_valid_state-manual.html": [ + "279aa052a362be0dc408d9926aecbd4a77622217", + "manual" + ], + "wai-aria/feed-manual.html": [ + "6768e3a7de2c91da15b218136156cfa58ff08266", + "manual" + ], + "wai-aria/figure-manual.html": [ + "ac697b43cc605ec65cb32b38c8d874aacbc71ce9", + "manual" + ], + "wai-aria/grid_aria-readonly_false_automatically_propagated-manual.html": [ + "6fbbec7c8a3d7d0910c6fcdd0eddcfa365b66278", + "manual" + ], + "wai-aria/grid_aria-readonly_true_automatically_propagated-manual.html": [ + "a82aa4fa5d961160f466139a1c55649aebafa8fb", + "manual" + ], + "wai-aria/grid_busy_false-manual.html": [ + "fd9ffb7a543c87860f1be98e25e25eef326e7751", + "manual" + ], + "wai-aria/grid_busy_true-manual.html": [ + "905f6765e8af6ad6f99004cba0580d360582b64b", + "manual" + ], + "wai-aria/grid_busy_value_changes-manual.html": [ + "164b4bb9fffae08a923fbbc3d929dab78c07f7da", + "manual" + ], + "wai-aria/grid_colcount_8-manual.html": [ + "dd37931f0fc32f2c00864626787e6d067e14592b", + "manual" + ], + "wai-aria/grid_columnheader_readonly_false-manual.html": [ + "ae9b21ab77f899329e20806ec8b4fd779532e591", + "manual" + ], + "wai-aria/grid_columnheader_readonly_true-manual.html": [ + "6acacc79477351796d7e31cb829254763985891b", + "manual" + ], + "wai-aria/grid_columnheader_readonly_unspecified-manual.html": [ + "74043387768367c5b31eca92f480d6eaf90957b1", + "manual" + ], + "wai-aria/grid_columnheader_required_false-manual.html": [ + "c3b02b385cfd99e689b005efc504ec761cb0a9b7", + "manual" + ], + "wai-aria/grid_columnheader_required_true-manual.html": [ + "b0dfaeb91b02fcb297693e96bfca333dda35716d", + "manual" + ], + "wai-aria/grid_columnheader_required_unspecified-manual.html": [ + "a6dc62bf3b5b589dc8721c3f5763183b4d015ac3", + "manual" + ], + "wai-aria/grid_rowcount_3-manual.html": [ + "bf3f9782a1a454a0c349616a61e280b1793230b0", + "manual" + ], + "wai-aria/grid_rowheader_readonly_false-manual.html": [ + "943cd5404948a66fed6a9c2cb0e8ced36c5102c0", + "manual" + ], + "wai-aria/grid_rowheader_readonly_true-manual.html": [ + "ff601c967bd5b0e738bdb14904a5497f34a16a19", + "manual" + ], + "wai-aria/grid_rowheader_readonly_unspecified-manual.html": [ + "4a76a804a411a15dcfbb1a6a8fb18bdfc2fb081f", + "manual" + ], + "wai-aria/grid_rowheader_required_false-manual.html": [ + "94fca0c3ef551d6d31d857e6d512963810e67992", + "manual" + ], + "wai-aria/grid_rowheader_required_true-manual.html": [ + "0649b9eb897fe2eb8967efb9d5332ef8e229c03d", + "manual" + ], + "wai-aria/grid_rowheader_required_unspecified-manual.html": [ + "dc4c36552e7c006db645ee0463a12675a3e0b466", + "manual" + ], + "wai-aria/gridcell_aria-colspan_2_on_div-manual.html": [ + "535e5db06891cf95856c2f3c18b40f5cdfda54cc", + "manual" + ], + "wai-aria/gridcell_aria-rowspan_2_on_div-manual.html": [ + "4b70f3c790eeafdf4519ca117d5636da75818329", + "manual" + ], + "wai-aria/gridcell_colindex_4-manual.html": [ + "e50950807c28c596da8498af6d5d6ad9813f8078", + "manual" + ], + "wai-aria/gridcell_rowindex_4-manual.html": [ + "a46ee5749847f5f7108f36bf94ab3cd68cc4b9da", + "manual" + ], + "wai-aria/group_hidden_undefined_element_not_rendered-manual.html": [ + "805ba51c4386fd6f55afefd2e6aae82914c4175d", + "manual" + ], + "wai-aria/group_hidden_undefined_element_rendered-manual.html": [ + "38b5fbf5a7dd587667a0b37183f8a7ae898f05cf", + "manual" + ], + "wai-aria/heading_level_unspecified-manual.html": [ + "7c2d392ee98849fe06f98274a2619c0a784f9b38", + "manual" + ], + "wai-aria/keyshortcuts_multiple_shortcuts-manual.html": [ + "af486cbc3db878e822c3fbb96bf036e6852cec5c", + "manual" + ], + "wai-aria/keyshortcuts_one_shortcut-manual.html": [ + "b3c04b5e58ee1526ef5f5e258ca90a582799dda4", + "manual" + ], + "wai-aria/listbox_busy_false-manual.html": [ + "1377c99b925c23caf6919f4374027b0e5ba257b2", + "manual" + ], + "wai-aria/listbox_busy_true-manual.html": [ + "2a5abfed2c9d72cc892cc49b797a46fde695e5f0", + "manual" + ], + "wai-aria/listbox_orientation_horizontal-manual.html": [ + "7f17844c821b26318f93b7cf76452f8acc2b3b0d", + "manual" + ], + "wai-aria/listbox_orientation_unspecified-manual.html": [ + "2d5b3c0dec5a14a3d9e0af254206ef87ee337771", + "manual" + ], + "wai-aria/listbox_orientation_vertical-manual.html": [ + "8a1c0a060d79ba685d3d0b9620defb605c6f62ff", + "manual" + ], + "wai-aria/listbox_readonly_false-manual.html": [ + "ec9dae486305791c724211354861638a247dc26c", + "manual" + ], + "wai-aria/listbox_readonly_true-manual.html": [ + "42e0b509269e688918e3a841f060aefd69df2169", + "manual" + ], + "wai-aria/listbox_readonly_unspecified-manual.html": [ + "1f541372495802bfa03caf45003005ae891948d7", + "manual" + ], + "wai-aria/listitem_setsize_-1-manual.html": [ + "b167105f60636d5ffcaaf500bae1edc88854465a", + "manual" + ], + "wai-aria/menu_orientation_horizontal-manual.html": [ + "020ef03f1ecbd6606e90c386ef4462c831c96732", + "manual" + ], + "wai-aria/menu_orientation_unspecified-manual.html": [ + "6850c3782b82c247edc598d7229f4f1a7724330f", + "manual" + ], + "wai-aria/menu_orientation_vertical-manual.html": [ + "0c8f0918aca79b7e517e26b893e1d1b6d69be5ca", + "manual" + ], + "wai-aria/menubar_busy_false-manual.html": [ + "c82d5db7dcd0c1312c3d57193254d01e7d72ce86", + "manual" + ], + "wai-aria/menubar_busy_true-manual.html": [ + "7bbc9132c65d46d9198005a85118ea3b720a1a13", + "manual" + ], + "wai-aria/menubar_orientation_horizontal-manual.html": [ + "80f7701f1dffe4a31cd107aef16737dc7f21a34d", + "manual" + ], + "wai-aria/menubar_orientation_unspecified-manual.html": [ + "588ca28c4c24def8245bd5b5769496103dfe9abc", + "manual" + ], + "wai-aria/menubar_orientation_vertical-manual.html": [ + "14bb2ca607953ee28c791e7fd0ecf19bc190758b", + "manual" + ], + "wai-aria/menuitem_posinset_and_setsize-manual.html": [ + "c55bb72e414f3ddbfd22ba5cf99bc109e5c980ac", + "manual" + ], + "wai-aria/menuitemcheckbox_posinset_and_setsize-manual.html": [ + "4553c3a159771357f5a622e982e95435c9eb93e4", + "manual" + ], + "wai-aria/menuitemcheckbox_readonly_false-manual.html": [ + "4042fbf1d8ebfdc4357f209bbd85e8af9c73830e", + "manual" + ], + "wai-aria/menuitemcheckbox_readonly_true-manual.html": [ + "30171ccd6e2c017e1c9595fe7cae11e2390facad", + "manual" + ], + "wai-aria/menuitemcheckbox_readonly_unspecified-manual.html": [ + "90858a2d3807fa9aaeb86a22d1f9347c0b7f18d1", + "manual" + ], + "wai-aria/menuitemradio_posinset_and_setsize-manual.html": [ + "d8b534c359b59241693f89624016aa284a044504", + "manual" + ], + "wai-aria/menuitemradio_readonly_false-manual.html": [ + "f1a615fcb66aaadbc8ebd2ccc51c71d405ef7a99", + "manual" + ], + "wai-aria/menuitemradio_readonly_true-manual.html": [ + "bcc2a14a9758cf50a09842f39e04dfe5eb88aca2", + "manual" + ], + "wai-aria/menuitemradio_readonly_unspecified-manual.html": [ + "240c09ed186cffe1a27b66c6fea18bbf834bac97", + "manual" + ], + "wai-aria/none-manual.html": [ + "ac3b80213f6e3f32731907e027aab65bed17bcca", + "manual" + ], + "wai-aria/option_selected_false-manual.html": [ + "5639b60eb2e929c4b9f5cc23a25576da6a8a0a08", + "manual" + ], + "wai-aria/option_selected_true-manual.html": [ + "3647d9da8c16d2905aa93fe18cbc1fb14942e431", + "manual" + ], + "wai-aria/option_selected_undefined-manual.html": [ + "e667c7bb74260d04128bcf89c43569a4dbc579d9", + "manual" + ], + "wai-aria/option_selected_value_changes-manual.html": [ + "f8f3b18dc5cc45f2a00d5c161569a109511543d8", + "manual" + ], + "wai-aria/radiogroup_orientation_horizontal-manual.html": [ + "d4b59488ea142fa84698919ba00d7e6c39680abb", + "manual" + ], + "wai-aria/radiogroup_orientation_unspecified-manual.html": [ + "fe639588f16cc6202a3d765c12d9ea5cbe4ea034", + "manual" + ], + "wai-aria/radiogroup_orientation_vertical-manual.html": [ + "575203e25857605f0f3076925b636e203c0a4985", + "manual" + ], + "wai-aria/radiogroup_readonly_false-manual.html": [ + "bd779e93fc3708db72848dd4d95938bf25f5eaf7", + "manual" + ], + "wai-aria/radiogroup_readonly_true-manual.html": [ + "72f4ddf0cfa0bf49d40d50911a564668a7c849d6", + "manual" + ], + "wai-aria/radiogroup_readonly_unspecified-manual.html": [ + "650e661bfdeb4428f9e92ab218e1596fd0cda64d", + "manual" + ], + "wai-aria/region_with_name-manual.html": [ + "d85fd90f06f86aeabe4c95996e3f913400dd21e4", + "manual" + ], + "wai-aria/region_without_name-manual.html": [ + "2178f5fa7d48ace5f56852304f392e34bd0fb00e", + "manual" + ], + "wai-aria/row_colindex_4-manual.html": [ + "09edc18410efb6f66b210dbb81818ca327969ad9", + "manual" + ], + "wai-aria/row_rowindex_4-manual.html": [ + "16a9f0d13d7e219d791a33313f484cea1d6a773a", + "manual" + ], + "wai-aria/rowheader_aria-colspan_2_on_div-manual.html": [ + "12a854c7835f358ffb82ac2337415b5a0a8a768c", + "manual" + ], + "wai-aria/rowheader_aria-rowspan_2_on_div-manual.html": [ + "b3653a6ac91d31a7fc73506afa8ae914b6dfb0f0", + "manual" + ], + "wai-aria/rowheader_colindex_4-manual.html": [ + "4b1095a3c7bbdbee01d208d909bceb1921d80fa5", + "manual" + ], + "wai-aria/rowheader_rowindex_4-manual.html": [ + "4a447def2f3f8c03ffa56352edb37b976a8ca340", + "manual" + ], + "wai-aria/rowheader_selected_false_not_automatically_propagated-manual.html": [ + "8abed2e46a404cce830afa5a3d0a2775a3c009a7", + "manual" + ], + "wai-aria/rowheader_selected_true_not_automatically_propagated-manual.html": [ + "d3def9e0ef906b28ea702bef37f529318c8133f5", + "manual" + ], + "wai-aria/scrollbar_all_values_unspecified-manual.html": [ + "c7bfcf35db82ec42822a129b40c0b26524931b95", + "manual" + ], + "wai-aria/scrollbar_only_valuenow_unspecified-manual.html": [ + "1436d040a20ec38e3493ab85df9110f81b468a1c", + "manual" + ], + "wai-aria/scrollbar_orientation_unspecified-manual.html": [ + "513a2cdd27dcd8ae2e3073ce2eff0e6b852e313c", + "manual" + ], + "wai-aria/searchbox-manual.html": [ + "69a89a2c6674f3994b24fa1a7cfebeaef2ff938e", + "manual" + ], + "wai-aria/searchbox_activedescendant-manual.html": [ + "0a28b434d5a38a23daeba52fe72040d152c6dd5d", + "manual" + ], + "wai-aria/searchbox_activedescendant_value_changes-manual.html": [ + "581ffae1f50715ea4af29b37631ce69fb163ed56", + "manual" + ], + "wai-aria/searchbox_autocomplete_both-manual.html": [ + "ceec0aec25373eea8a1255d7c508fa85534ff5b9", + "manual" + ], + "wai-aria/searchbox_autocomplete_inline-manual.html": [ + "17e69cb6a6e9aded2485c2c064ef4879a45f4164", + "manual" + ], + "wai-aria/searchbox_autocomplete_list-manual.html": [ + "9f881f8b334a36141363498d86a1d7327c97060a", + "manual" + ], + "wai-aria/searchbox_autocomplete_none-manual.html": [ + "f2ad6734ded2a347cb32411f2d26d9c74f2b9c61", + "manual" + ], + "wai-aria/searchbox_autocomplete_unspecified-manual.html": [ + "492f3c3d8f1a1c2bb5bb2a39af99333de8119cc8", + "manual" + ], + "wai-aria/searchbox_multiline_false-manual.html": [ + "2bc9db01cccb25a94add5c6a4b469ce38c32e713", + "manual" + ], + "wai-aria/searchbox_multiline_true-manual.html": [ + "35684d76a3c45e1355984bfe516d40d71b6424e6", + "manual" + ], + "wai-aria/searchbox_multiline_unspecified-manual.html": [ + "f1643f9c47f61f98ed28483bd9b3cb1ebcebacdf", + "manual" + ], + "wai-aria/searchbox_placeholder-manual.html": [ + "c7915eadb230631a11b326fe6a3045992ca11468", + "manual" + ], + "wai-aria/searchbox_readonly_false-manual.html": [ + "220bcf0b6de7e4ea38f14c63f5b035ad8c90b126", + "manual" + ], + "wai-aria/searchbox_readonly_true-manual.html": [ + "6333c8a2fe903d0dd528c17c255b474158d21230", + "manual" + ], + "wai-aria/searchbox_readonly_unspecified-manual.html": [ + "2706af2015509abaa4f8a96506a9b394dd24801c", + "manual" + ], + "wai-aria/searchbox_required_false-manual.html": [ + "96561ee3eeb254a17cf4e0665ccb78bf1362ea02", + "manual" + ], + "wai-aria/searchbox_required_true-manual.html": [ + "67dbe2e78c059e4ae018194f5ac3ea22cc5b274b", + "manual" + ], + "wai-aria/searchbox_required_unspecified-manual.html": [ + "216e258bd53649bf2703c586858471ed30f122e7", + "manual" + ], + "wai-aria/separator_focusable_all_values_unspecified-manual.html": [ + "36c88bd5c4316bdfde84c5ff5113863df302a286", + "manual" + ], + "wai-aria/separator_focusable_only_valuenow_unspecified-manual.html": [ + "06260be143c42b51ad13fda1cf050fd47c167fc0", + "manual" + ], + "wai-aria/separator_focusable_valuetext-manual.html": [ + "a3bd39904d064ea3822558ccd1c9ca473961219b", + "manual" + ], + "wai-aria/separator_orientation_unspecified-manual.html": [ + "d62a3821d9b02a735b397a599843b665cccebc90", + "manual" + ], + "wai-aria/separator_unfocusable_all_values_unspecified-manual.html": [ + "5e129d2319b57f7d86b0a04cb226d179a330f907", + "manual" + ], + "wai-aria/separator_unfocusable_valuetext-manual.html": [ + "93c6b47e0cc9689cce539a940eb1cdcba82ebfd5", + "manual" + ], + "wai-aria/slider_all_values_unspecified-manual.html": [ + "90ebac88d3f22a87378698cea51fa09452b76469", + "manual" + ], + "wai-aria/slider_only_valuenow_unspecified-manual.html": [ + "dcaa79500ad30ba8fba3f194b578f63bf8755acf", + "manual" + ], + "wai-aria/slider_orientation_unspecified-manual.html": [ + "48069859c3bd20aabcffedb1edbab2a370dd9b3f", + "manual" + ], + "wai-aria/slider_readonly_false-manual.html": [ + "861fcfcafdf59d381177a5bb5946c6f54a3da49e", + "manual" + ], + "wai-aria/slider_readonly_true-manual.html": [ + "b8b33452767ef838a17876d7e215abda33af1795", + "manual" + ], + "wai-aria/slider_readonly_unspecified-manual.html": [ + "ba1b3920b40f1acdf26a7ab6a31ab9ea26f5bbd0", + "manual" + ], + "wai-aria/spinbutton_all_values_unspecified-manual.html": [ + "d7e6862b38f714424aecc21dc838697fe09d7912", + "manual" + ], + "wai-aria/spinbutton_only_aria-valuenow_unspecified-manual.html": [ + "5c164b3834cf10846e920e83487039f1b9c26d8a", + "manual" + ], + "wai-aria/spinbutton_readonly_false-manual.html": [ + "2423f721a79e4a0078179b7f0d3f4f6ef0eb6334", + "manual" + ], + "wai-aria/spinbutton_readonly_true-manual.html": [ + "ce33688754649c0478a2bed417c3ebede3da6bd2", + "manual" + ], + "wai-aria/spinbutton_readonly_unspecified-manual.html": [ + "ae0499cdda8e51f1e514a37dd42a1f668a6f0fca", + "manual" + ], + "wai-aria/switch_checked_false-manual.html": [ + "34d619b1c380fd3b5e0a8196e1f8cf1ded2565da", + "manual" + ], + "wai-aria/switch_checked_mixed-manual.html": [ + "ac8deb477f3f0dbd9b15d066aa5fedf7303155d6", + "manual" + ], + "wai-aria/switch_checked_true-manual.html": [ + "89762ad8710d61af6f02dc47d2d0cb85278e5a0f", + "manual" + ], + "wai-aria/switch_checked_undefined-manual.html": [ + "43dfbc3fed1773110b780bc9d8a8b001ab0bf522", + "manual" + ], + "wai-aria/switch_checked_value_changes-manual.html": [ + "7eabfd644e607e92298e449a02376aee38623f71", + "manual" + ], + "wai-aria/switch_readonly_false-manual.html": [ + "b80fb7d4726566e0bd111e4ad5a2e17c72c19a22", + "manual" + ], + "wai-aria/switch_readonly_true-manual.html": [ + "432d55a0b9943f9d44641e73bbf94c4d346882be", + "manual" + ], + "wai-aria/switch_readonly_unspecified-manual.html": [ + "7b491505435f6ce21bea99acf817d5f8452793ce", + "manual" + ], + "wai-aria/tab_posinset_and_setsize-manual.html": [ + "0a81f2ec8a073a4aa4c9b2262bf3b894500a7d85", + "manual" + ], + "wai-aria/table_colcount_-1-manual.html": [ + "767517c0b13aa5738caca739fac835255495b552", + "manual" + ], + "wai-aria/table_colcount_8-manual.html": [ + "10ef7ce22ebdbff6b82408bff4ea269b22a84cfe", + "manual" + ], + "wai-aria/table_rowcount_-1-manual.html": [ + "c1b42be4c24652dbab05bb6e1b21705b679f80f2", + "manual" + ], + "wai-aria/table_rowcount_3-manual.html": [ + "59ff2493b3107e6e3832bc116087fc25a1f4cdfc", + "manual" + ], + "wai-aria/tablist_orientation_horizontal-manual.html": [ + "65b14b357bfadb29334f7e0b4d327387f00b16a3", + "manual" + ], + "wai-aria/tablist_orientation_unspecified-manual.html": [ + "9fe1319decbd2959c7edee1729781b7c7714cfa3", + "manual" + ], + "wai-aria/tablist_orientation_vertical-manual.html": [ + "b42ccf2e219954234e715c67702e6161738c74c0", + "manual" + ], + "wai-aria/term_role-manual.html": [ + "9b94e2327fdcb8f0812931fb4beef1a820ac73bc", + "manual" + ], + "wai-aria/textbox_placeholder-manual.html": [ + "0d62d1d8d51380f76df1cb292560946af5acc117", + "manual" + ], + "wai-aria/toolbar_orientation_horizontal-manual.html": [ + "c0d179f4aa923ceb79a3d6b6f2c709c08bff6d1b", + "manual" + ], + "wai-aria/toolbar_orientation_unspecified-manual.html": [ + "5291a72ec14d159b5ac2a9ee98faf8f49fff25db", + "manual" + ], + "wai-aria/toolbar_orientation_vertical-manual.html": [ + "9a997719c1f7056de7effc8bf6715a5542ba328e", + "manual" + ], + "wai-aria/tree_orientation_horizontal-manual.html": [ + "ced3f1f1877a379e2838e768faf301156eb0d21b", + "manual" + ], + "wai-aria/tree_orientation_unspecified-manual.html": [ + "314a725577dcb0f1353976149bcfa4320348771d", + "manual" + ], + "wai-aria/tree_orientation_vertical-manual.html": [ + "1b6c426e4c296d51fd37e882360a99b9177c9dec", + "manual" + ], + "wai-aria/treegrid_colcount_8-manual.html": [ + "93141db40bf34a33833917c3679a21facaef3b54", + "manual" + ], + "wai-aria/treegrid_orientation_horizontal-manual.html": [ + "d47fc7b4534e78d6740caf2f184a9682cbea9551", + "manual" + ], + "wai-aria/treegrid_orientation_unspecified-manual.html": [ + "314b5fba7dbf05874c87ed583707a256a0c48e95", + "manual" + ], + "wai-aria/treegrid_orientation_vertical-manual.html": [ + "a010eac09cba60995983bce684eef3dffdd2b173", + "manual" + ], + "wai-aria/treegrid_rowcount_3-manual.html": [ + "05e99e92cb0a8661fcc6ca9e4073814995e1e335", + "manual" + ], + "wai-aria/treeitem_selected_false-manual.html": [ + "306b11914f05b8aba7373e4b8d098940436f0628", + "manual" + ], + "wai-aria/treeitem_selected_true-manual.html": [ + "840111cebbbae4c1f7145151f6286c77f43e59c4", + "manual" + ], + "wai-aria/treeitem_selected_undefined-manual.html": [ + "3e12ca040cd5b1fc5230e8c98ac84b4e98794de2", + "manual" + ], + "wai-aria/treeitem_selected_value_changes-manual.html": [ + "ff1dff851d96bc1bbee1821b958c9220868dc1d1", + "manual" + ], "web-animations/OWNERS": [ "c4f52fc673833f80178284b30d6fc4bad1f581d2", "support" @@ -211789,6 +218819,10 @@ "395dad4a877ef4af20649d6bcfece102a22b3059", "testharness" ], + "web-animations/interfaces/Animation/idlharness.html": [ + "bf61e9cb3d009b4d5ccbd70ec7397842e2d521d2", + "testharness" + ], "web-animations/interfaces/Animation/oncancel.html": [ "0477d2fef7fc64bbc969b29d4ba542574c4c3706", "testharness" @@ -211814,7 +218848,7 @@ "testharness" ], "web-animations/interfaces/Animation/ready.html": [ - "f79ea4e2bfc3bc83a7ac96634cbb2d5f21f6c1f5", + "b23b76881f4d38c07710d0e59c1f6c8569de9060", "testharness" ], "web-animations/interfaces/Animation/startTime.html": [ @@ -211862,7 +218896,7 @@ "testharness" ], "web-animations/interfaces/AnimationTimeline/document-timeline.html": [ - "033c4137ea1fcffc7c32a4cc353009b07b800c4a", + "2df691f77422d0e64833addf0c099e44f9afe051", "testharness" ], "web-animations/interfaces/AnimationTimeline/idlharness.html": [ @@ -211953,12 +218987,24 @@ "53a4a6c6c6d07e00fecc50e5de831862e7bf4b2e", "testharness" ], + "web-animations/timing-model/animations/canceling-an-animation.html": [ + "079bc0e0f7ea60b94999ed1b4f92c1aa2fc2c7bb", + "testharness" + ], "web-animations/timing-model/animations/current-time.html": [ "b1ea8e490cbfb69fd71b91a90e7e2d9ce99f42d3", "testharness" ], + "web-animations/timing-model/animations/finishing-an-animation.html": [ + "570ec579c6118866b888b1384e21977c9cfb0ec0", + "testharness" + ], + "web-animations/timing-model/animations/pausing-an-animation.html": [ + "a000d8f86fa62b90ec7a60c289066aaaa1758377", + "testharness" + ], "web-animations/timing-model/animations/playing-an-animation.html": [ - "88ab1d42390d50bcdf513bb12159c0c15d6278ff", + "2b4f51977d43f9bf90c066bfcc57728ae096b6e9", "testharness" ], "web-animations/timing-model/animations/reversing-an-animation.html": [ @@ -211985,16 +219031,24 @@ "66e2277c77e4bd7b2d8981a725fb5083a8f5e0f6", "testharness" ], + "web-nfc/OWNERS": [ + "214e3edd526f674d2bd69f4292c0681e54685a0d", + "support" + ], + "web-nfc/idlharness.https.html": [ + "b44413f6709ec74f6fc809726d0e988c127ef02d", + "testharness" + ], "webaudio/.gitignore": [ "11bc81247643b0a9fc665f1e4b1f592cc1f4c670", "support" ], "webaudio/OWNERS": [ - "d98264a830bdab63db07061e8b25080188e1aeab", + "72bd1a8929367ef9a8f8353d7fc5bda3354477a6", "support" ], "webaudio/README.md": [ - "4c364a7fe763f5d1fa603cfe5ab62234e7a1f9ee", + "230684ec60fd2e408f9b6014417f3eddfe2dc95a", "support" ], "webaudio/js/buffer-loader.js": [ @@ -212238,7 +219292,7 @@ "testharness" ], "webdriver/OWNERS": [ - "ed6ae435828699abe5d1399c6e9bacc7bae7474f", + "cbfd094d14a2be6678df83a7bcd8b022922396dd", "support" ], "webdriver/README.md": [ @@ -212286,7 +219340,7 @@ "support" ], "webdriver/conftest.py": [ - "5abb72cd5cce31dde7772f4a88a9c618aeacc42e", + "d58492066c9eba232867b4c2928e9e74839d3f8a", "wdspec" ], "webdriver/contexts.py": [ @@ -212301,12 +219355,16 @@ "dd2f52a3a77497ce8785e698f9ab462390ed0d57", "wdspec" ], + "webdriver/support/__init__.py": [ + "5a31a3917a5157516c10951a3b3d5ffb43b992d9", + "support" + ], "webdriver/support/asserts.py": [ "68bde3a7b3e3fe3ecd45e43c9fbc3c1317828e08", "support" ], "webdriver/support/fixtures.py": [ - "281f7e8b5baa0f4e51900db120ef688a75108ae0", + "1742e49d5661ce9e5a806fd17c293f6bd502227f", "support" ], "webdriver/support/http_request.py": [ @@ -212317,6 +219375,10 @@ "bc85126e5637145e81f27d037f3a9090747130c8", "support" ], + "webdriver/support/merge_dictionaries.py": [ + "84a6d3c6f8f4afded0f21264bbaeebec38a7f827", + "support" + ], "webgl/OWNERS": [ "f8e0703fe2cc88edd21ef2c94fcb2e1a8889f5ae", "support" @@ -221650,7 +228712,7 @@ "support" ], "webgl/conformance-1.0.3/resources/js-test-pre.js": [ - "0ea0d3b945ac49d9a98c39788b2bc18c82de762a", + "23bc989f25ee5371a45762bac36c260d230001ca", "support" ], "webgl/conformance-1.0.3/resources/js-test-style.css": [ @@ -221686,7 +228748,7 @@ "support" ], "webgl/tools/js-test-pre.patch": [ - "b903fa3810ba7538a735d4126d20364d285b88cc", + "9d692bf9bf2b37385f1193855e2605573af8249e", "support" ], "webgl/tools/unit.patch": [ @@ -221750,7 +228812,7 @@ "support" ], "webmessaging/README.md": [ - "4c7f9f149edb1036692128007742f8ae358e167a", + "d126c708f1d34de380f2e063bb8e404f30b6a487", "support" ], "webmessaging/Transferred_objects_unusable.sub.htm": [ @@ -221833,6 +228895,10 @@ "19fc5d2f7e0f30e9d35a8606c3fb05b537ea3a82", "testharness" ], + "webmessaging/messageerror.html": [ + "92c5359ad64394cb2d30402204968d49227c5daf", + "testharness" + ], "webmessaging/postMessage_ArrayBuffer.sub.htm": [ "ce4d489c97753d15ea9370093fdc3b2fe1592cf1", "testharness" @@ -221994,7 +229060,7 @@ "testharness" ], "webmessaging/with-ports/027.html": [ - "c392333f994dd5196c5456176e775528abc2a9a7", + "2d1ca62b5be602139a4a86599fc86f3ff14d1377", "testharness" ], "webmessaging/without-ports/001.html": [ @@ -222122,13 +229188,41 @@ "testharness" ], "webrtc/OWNERS": [ - "07bfd311abbe127d95ac7e49c8615f7948a4949e", + "e7b3745ccd77b56023dedda83488a9b77327dffe", "support" ], + "webrtc/RTCConfiguration-iceCandidatePoolSize.html": [ + "9551402aed448bf6abde4aa815d174ba321cc655", + "testharness" + ], "webrtc/RTCDataChannelEvent-constructor.html": [ "8a8b30a23abddb5d11a802fead534fd56aacbb62", "testharness" ], + "webrtc/RTCPeerConnection-canTrickleIceCandidates.html": [ + "0f585a89bd8f25aa8f83b6ec39b704cbb8e970b2", + "testharness" + ], + "webrtc/RTCPeerConnection-constructor.html": [ + "54fff02eab02b0be84c945ec7e77afe722d9f988", + "testharness" + ], + "webrtc/RTCPeerConnection-createDataChannel.html": [ + "4e46c66c535a49573a3400355dde79b63f7b95d6", + "testharness" + ], + "webrtc/RTCPeerConnection-iceGatheringState.html": [ + "4f752838326116e65543a10e023a0cbe9c07e9e8", + "testharness" + ], + "webrtc/RTCPeerConnection-idl.html": [ + "e322b3ab7f8e0bc7ff802f00234a9a6e80b8285a", + "testharness" + ], + "webrtc/RTCPeerConnection-setRemoteDescription.html": [ + "ee89fd092059a4cc489536898d4a47a7bbbf36f2", + "testharness" + ], "webrtc/RTCPeerConnectionIceEvent-constructor.html": [ "46bb1ba3a908f99b46a656d34094aae8998ed484", "testharness" @@ -222137,36 +229231,28 @@ "56a37968e489d6ee39a1234ca888dd628f17648e", "testharness" ], + "webrtc/datachannel-idlharness.html": [ + "a1753a9a537a626775194ccc5dfdbf6829c5df35", + "testharness" + ], + "webrtc/getstats.html": [ + "6656998d4adfab0e6ca51c98cd141cf162d3879c", + "testharness" + ], + "webrtc/interfaces.html": [ + "bd71316e6efddce47bb4cf3218b3133f8c69c3db", + "testharness" + ], "webrtc/no-media-call.html": [ - "d82774b3116ba278303b9407176ee528d0754700", + "e9f056be5a865f1bb73d60ec72c38f8d5f16d747", "testharness" ], "webrtc/promises-call.html": [ - "392d4975b232b9003a75d3771ba5c6f2e992849e", - "testharness" - ], - "webrtc/rtcpeerconnection/iceGatheringState.html": [ - "4f752838326116e65543a10e023a0cbe9c07e9e8", - "testharness" - ], - "webrtc/rtcpeerconnection/rtcconfiguration-icecandidatepoolsize.html": [ - "9551402aed448bf6abde4aa815d174ba321cc655", - "testharness" - ], - "webrtc/rtcpeerconnection/rtcpeerconnection-constructor.html": [ - "54fff02eab02b0be84c945ec7e77afe722d9f988", - "testharness" - ], - "webrtc/rtcpeerconnection/rtcpeerconnection-idl.html": [ - "e322b3ab7f8e0bc7ff802f00234a9a6e80b8285a", - "testharness" - ], - "webrtc/rtcpeerconnection/setRemoteDescription.html": [ - "b11f7f3cc9a11b6aac9d70324a15e878c0345945", + "f0292ca52ee86920d0fdb8bccae2bc40a8ef99af", "testharness" ], "webrtc/simplecall.html": [ - "0ccdc365173e0c805f708edc49dbb8c8a88d786a", + "ce76df05d5866807a4b58c9509ce66efcddaf3d7", "testharness" ], "websockets/Close-1000-reason.htm": [ @@ -222282,7 +229368,7 @@ "support" ], "websockets/README.md": [ - "cb6f6f64079ef7f8843b7553ab732bf84c8794bf", + "1b8473c8d482b7628fc7337e263c78aca7ca5088", "support" ], "websockets/Secure-Close-1000-reason.htm": [ @@ -223102,7 +230188,7 @@ "support" ], "webstorage/README.md": [ - "48097218468237985b9c3275f8e72979e44fe214", + "2f211af6d9f953cebb65e8bbfcbf417e50788a45", "support" ], "webstorage/document-domain.html": [ @@ -223366,7 +230452,7 @@ "support" ], "webvr/idlharness.html": [ - "53ac12278e26e70cc0f6d6f31171fc4d2b6e6667", + "236974fe82ab29908e849d25c5ce748f5c0509c3", "testharness" ], "webvtt/OWNERS": [ @@ -226130,7 +233216,7 @@ "support" ], "workers/README.md": [ - "2660d9dbe4f7a2947ec78b14e6418554c8204d6b", + "b32446a62602baf1a316520ee8e2e5d9e60cada3", "support" ], "workers/SharedWorker_blobUrl.html": [ diff --git a/testing/web-platform/meta/mozilla-sync b/testing/web-platform/meta/mozilla-sync index ab1d5f37f233..84f82abeb257 100644 --- a/testing/web-platform/meta/mozilla-sync +++ b/testing/web-platform/meta/mozilla-sync @@ -1,2 +1,2 @@ -local: 0000000000000000000000000000000000000000 -upstream: 8181d7f09ee35cb521452bb727a48a1667901afd +local: 0b255199db9d6a6f189b89b7906f99155bde3726 +upstream: 72d174747fe176cbefcba315b445fac99d3dbfb2 diff --git a/testing/web-platform/tests/.codecov.yml b/testing/web-platform/tests/.codecov.yml new file mode 100644 index 000000000000..904cf85a4fd7 --- /dev/null +++ b/testing/web-platform/tests/.codecov.yml @@ -0,0 +1,6 @@ +comment: + require_changes: yes + +ignore: + - "**" + - "!tools/.*" diff --git a/testing/web-platform/tests/.gitmodules b/testing/web-platform/tests/.gitmodules index 5eb46bc69154..41d2a66089be 100644 --- a/testing/web-platform/tests/.gitmodules +++ b/testing/web-platform/tests/.gitmodules @@ -1,14 +1,12 @@ -[submodule "resources"] - path = resources - url = https://github.com/w3c/testharness.js.git - ignore = dirty -[submodule "tools"] - path = tools - url = https://github.com/w3c/wpt-tools.git - ignore = dirty [submodule "css/tools/apiclient"] path = css/tools/apiclient url = https://github.com/w3c/csswg-apiclient.git [submodule "css/tools/w3ctestlib"] path = css/tools/w3ctestlib url = https://github.com/w3c/csswg-w3ctestlib.git +[submodule "tools/html5lib/html5lib/tests/testdata"] + path = tools/html5lib/html5lib/tests/testdata + url = https://github.com/html5lib/html5lib-tests.git +[submodule "resources/webidl2/test/widlproc"] + path = resources/webidl2/test/widlproc + url = https://github.com/dontcallmedom/widlproc.git \ No newline at end of file diff --git a/testing/web-platform/tests/.travis.yml b/testing/web-platform/tests/.travis.yml index a558820fd4ea..f413d82fe00b 100644 --- a/testing/web-platform/tests/.travis.yml +++ b/testing/web-platform/tests/.travis.yml @@ -1,6 +1,9 @@ dist: trusty sudo: required language: python +branches: + only: + - master addons: hosts: - web-platform.test @@ -18,6 +21,7 @@ install: - pip install -U requests env: # required at the top-level for allow_failures to work below matrix: + fast_finish: true include: - os: linux python: "2.7" @@ -48,10 +52,21 @@ matrix: env: - secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM=" - SCRIPT=ci_stability.sh PRODUCT=chrome:unstable + - python: 2.7 + env: TOXENV=py27 HYPOTHESIS_PROFILE=ci SCRIPT=ci_unittest.sh + - python: 3.5 + env: TOXENV=py35 HYPOTHESIS_PROFILE=ci SCRIPT=ci_unittest.sh + - python: 3.6 + env: TOXENV=py36 HYPOTHESIS_PROFILE=ci SCRIPT=ci_unittest.sh + - python: pypy + env: TOXENV=pypy HYPOTHESIS_PROFILE=ci_pypy SCRIPT=ci_unittest.sh exclude: - env: # exclude empty env from the top-level above allow_failures: - env: SCRIPT=css/build-css-testsuites.sh + - env: + - secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM=" + - SCRIPT=ci_stability.sh PRODUCT=chrome:unstable script: - bash $SCRIPT cache: diff --git a/testing/web-platform/tests/2dcontext/2x4.png b/testing/web-platform/tests/2dcontext/2x4.png new file mode 100644 index 000000000000..f5589a731840 Binary files /dev/null and b/testing/web-platform/tests/2dcontext/2x4.png differ diff --git a/testing/web-platform/tests/2dcontext/4x2.png b/testing/web-platform/tests/2dcontext/4x2.png new file mode 100644 index 000000000000..4a8d81e7c22f Binary files /dev/null and b/testing/web-platform/tests/2dcontext/4x2.png differ diff --git a/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14.html b/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14.html new file mode 100644 index 000000000000..0a28aa462831 --- /dev/null +++ b/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14.html @@ -0,0 +1,33 @@ + + + +Canvas test: 2d.drawImage.crop.2x4 + + + + diff --git a/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14_ref.html b/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14_ref.html new file mode 100644 index 000000000000..f682f87cc6f4 --- /dev/null +++ b/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_14_ref.html @@ -0,0 +1,25 @@ + + + + + + + +
+ + diff --git a/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15.html b/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15.html new file mode 100644 index 000000000000..507ff31eb9d8 --- /dev/null +++ b/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15.html @@ -0,0 +1,33 @@ + + + +Canvas test: 2d.drawImage.crop.4x2 + + + + diff --git a/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15_ref.html b/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15_ref.html new file mode 100644 index 000000000000..a7abc3cb28ac --- /dev/null +++ b/testing/web-platform/tests/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_15_ref.html @@ -0,0 +1,25 @@ + + + + + + + +
+ + diff --git a/testing/web-platform/tests/2dcontext/tools/gentestutils.py b/testing/web-platform/tests/2dcontext/tools/gentestutils.py index 469c33a30fea..fb7bf18d2343 100644 --- a/testing/web-platform/tests/2dcontext/tools/gentestutils.py +++ b/testing/web-platform/tests/2dcontext/tools/gentestutils.py @@ -235,10 +235,6 @@ def genTestUtils(TESTOUTPUTDIR, IMAGEOUTPUTDIR, TEMPLATEFILE, NAME2DIRFILE, ISOF r'assert_throws(new \1(), function() { \2; });', code) - code = re.sub(r'@assert throws (.*);', - r'assert_throws(null, function() { \1; });', - code) - code = re.sub(r'@assert (.*) === (.*);', lambda m: '_assertSame(%s, %s, "%s", "%s");' % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2))) diff --git a/testing/web-platform/tests/IndexedDB/idb_webworkers.htm b/testing/web-platform/tests/IndexedDB/idb_webworkers.htm index dba3a93f120a..9c29d00b30e1 100644 --- a/testing/web-platform/tests/IndexedDB/idb_webworkers.htm +++ b/testing/web-platform/tests/IndexedDB/idb_webworkers.htm @@ -8,6 +8,7 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-advance-continue-async.htm b/testing/web-platform/tests/IndexedDB/idbcursor-advance-continue-async.htm index d1b6af3e189e..ccadb7fa95a6 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-advance-continue-async.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-advance-continue-async.htm @@ -7,180 +7,175 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-advance-invalid.htm b/testing/web-platform/tests/IndexedDB/idbcursor-advance-invalid.htm index dda216b75316..ee911cc9e4bc 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-advance-invalid.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-advance-invalid.htm @@ -13,176 +13,180 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-advance.htm b/testing/web-platform/tests/IndexedDB/idbcursor-advance.htm index f4ecbc0e5aac..f08a2594f3dd 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-advance.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-advance.htm @@ -7,237 +7,241 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-continue.htm b/testing/web-platform/tests/IndexedDB/idbcursor-continue.htm index 968cd9cbd09d..372d452f7813 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-continue.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-continue.htm @@ -9,232 +9,240 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm b/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm index 0d35218b9e0a..56a23a1123ff 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm @@ -45,12 +45,12 @@ indexeddb_test( store.deleteIndex("idx"); }); - txn.oncomplete = function() { + txn.oncomplete = t.step_func(function() { assert_throws("TransactionInactiveError", function() { cursor.continuePrimaryKey("A", 4); }, "transaction-state check should precede deletion check"); t.done(); - }; + }); }, null, "TransactionInactiveError v.s. InvalidStateError(deleted index)" @@ -378,5 +378,3 @@ indexeddb_test( "DataError(keys are larger then current one) in 'prev' direction" ); - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exceptions.htm b/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exceptions.htm index d6785137bb1d..9393e2fbf24f 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exceptions.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exceptions.htm @@ -16,6 +16,10 @@ async_test(function(t) { open.onupgradeneeded = t.step_func(function() { var db = open.result; + t.add_cleanup(function() { + db.close(); + indexedDB.deleteDatabase(db.name); + }); var store = db.createObjectStore('store'); store.put('a', 1).onerror = t.unreached_func('put should not fail'); var request = store.openCursor(); @@ -60,6 +64,10 @@ async_test(function(t) { open.onupgradeneeded = t.step_func(function() { var db = open.result; + t.add_cleanup(function() { + db.close(); + indexedDB.deleteDatabase(db.name); + }); var store = db.createObjectStore('store', {keyPath: 'pk'}); var index = store.createIndex('index', 'ik', {multiEntry: true}); store.put({pk: 'a', ik: [1,2,3]}).onerror = diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction-index-keyrange.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction-index-keyrange.htm index e0f0c6d0ad0e..2de3854dc9bf 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-direction-index-keyrange.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction-index-keyrange.htm @@ -15,69 +15,46 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction-index.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction-index.htm index 39afcb24d86d..0eb926d9ec0f 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-direction-index.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction-index.htm @@ -13,69 +13,45 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm index 7bcb971bbb68..96f92a0445a4 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm @@ -11,68 +11,44 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore.htm index c02355395a29..85088ee72444 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore.htm @@ -13,68 +13,44 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction.htm index b50eded79085..246cd79aac8b 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-direction.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction.htm @@ -17,6 +17,11 @@ open_rq.onupgradeneeded = function(e) { db = e.target.result; + t.add_cleanup(function() { + db.close(); + indexedDB.deleteDatabase(db.name); + }); + var objStore = db.createObjectStore("test"); objStore.add("data", "key"); @@ -69,5 +74,3 @@ cursor_direction("prevunique", "prevunique"); - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-source.htm b/testing/web-platform/tests/IndexedDB/idbcursor-source.htm index 7e3746ae7e6b..b23551c8d49c 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor-source.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor-source.htm @@ -6,63 +6,61 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_iterating.htm b/testing/web-platform/tests/IndexedDB/idbcursor_iterating.htm index fd3cd0a690d5..d9be6b6ad6a4 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor_iterating.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor_iterating.htm @@ -13,6 +13,7 @@ var open_rq = createdb(t); open_rq.onupgradeneeded = function(e) { db = e.target.result; + t.add_cleanup(function() { db.close(); indexedDB.deleteDatabase(db.name); }); var objStore = db.createObjectStore("test", { keyPath: "key" }); for (var i = 0; i < 500; i++) @@ -106,5 +107,3 @@ }); }; - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore.htm b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore.htm index db66c4db33be..c4c8d57148de 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore.htm @@ -18,6 +18,7 @@ var open_rq = createdb(t); open_rq.onupgradeneeded = function(e) { db = e.target.result; + t.add_cleanup(function() { db.close(); indexedDB.deleteDatabase(db.name); }); var objStore = db.createObjectStore("test", {keyPath:"pKey"}); for (var i = 0; i < records.length; i++) @@ -47,5 +48,3 @@ }); }; - -
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore2.htm index 2374a854e446..899b2ac0e6da 100644 --- a/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore2.htm +++ b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore2.htm @@ -18,6 +18,7 @@ var open_rq = createdb(t); open_rq.onupgradeneeded = function(e) { db = e.target.result; + t.add_cleanup(function() { db.close(); indexedDB.deleteDatabase(db.name); }); var objStore = db.createObjectStore("test", {keyPath:"pKey"}); for (var i = 0; i < records.length; i++) @@ -47,5 +48,3 @@ }); }; - -
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase-transaction-exception-order.html b/testing/web-platform/tests/IndexedDB/idbdatabase-transaction-exception-order.html index 686f44ef5cb6..c0021d926a83 100644 --- a/testing/web-platform/tests/IndexedDB/idbdatabase-transaction-exception-order.html +++ b/testing/web-platform/tests/IndexedDB/idbdatabase-transaction-exception-order.html @@ -45,10 +45,10 @@ indexeddb_test( assert_throws('NotFoundError', () => { db.transaction('no-such-store', 'versionchange'); }, '"No such store" check (NotFoundError) should precede ' + - '"invalid mode" check (InvalidAccessError)'); + '"invalid mode" check (TypeError)'); t.done(); }, - 'IDBDatabase.transaction exception order: NotFoundError vs. InvalidAccessError' + 'IDBDatabase.transaction exception order: NotFoundError vs. TypeError' ); diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_close.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_close.htm index dc3f585a8cd1..781f8cba9d18 100644 --- a/testing/web-platform/tests/IndexedDB/idbdatabase_close.htm +++ b/testing/web-platform/tests/IndexedDB/idbdatabase_close.htm @@ -33,6 +33,7 @@ open_rq.onsuccess = function(e) { assert_equals(blocked_fired, 1, 'block event fired #') assert_equals(upgradeneeded_fired, 2, 'second upgradeneeded event fired #') + rq.result.close(); t.done(); }); rq.onerror = fail(t, 'Unexpected database deletion error'); diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm index 0a6dc03a67ab..4a28d4033c08 100644 --- a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm +++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm @@ -7,11 +7,11 @@ diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open10.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open10.htm index 598046ff98f9..c0ac71ae8576 100644 --- a/testing/web-platform/tests/IndexedDB/idbfactory_open10.htm +++ b/testing/web-platform/tests/IndexedDB/idbfactory_open10.htm @@ -81,6 +81,8 @@ }); idx.getKey("Sicking").onsuccess = this.step_func(function(e) { assert_equals(e.target.result, undefined, "getKey(Sicking)"); + + db3.close(); this.done(); }); }); diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open11.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open11.htm index 66ea9d52559b..88c59bd9f65c 100644 --- a/testing/web-platform/tests/IndexedDB/idbfactory_open11.htm +++ b/testing/web-platform/tests/IndexedDB/idbfactory_open11.htm @@ -51,6 +51,8 @@ count_done++; assert_equals(count_done, 3, "count_done"); + + db2.close(); this.done(); }); }); diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open3.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open3.htm index 9ec6db5ab861..ac8ca5e1b655 100644 --- a/testing/web-platform/tests/IndexedDB/idbfactory_open3.htm +++ b/testing/web-platform/tests/IndexedDB/idbfactory_open3.htm @@ -17,6 +17,7 @@ var open_rq2 = window.indexedDB.open(db.name); open_rq2.onsuccess = this.step_func(function(e) { assert_equals(e.target.result.version, 13, "db.version") + e.target.result.close(); this.done(); }); open_rq2.onupgradeneeded = fail(this, 'Unexpected upgradeneeded') diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open6.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open6.htm index bbb8ac02d37f..c2e2c080d0c3 100644 --- a/testing/web-platform/tests/IndexedDB/idbfactory_open6.htm +++ b/testing/web-platform/tests/IndexedDB/idbfactory_open6.htm @@ -8,13 +8,14 @@ + diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getAllKeys.html b/testing/web-platform/tests/IndexedDB/idbindex_getAllKeys.html index 7653a5152605..a882312db48f 100644 --- a/testing/web-platform/tests/IndexedDB/idbindex_getAllKeys.html +++ b/testing/web-platform/tests/IndexedDB/idbindex_getAllKeys.html @@ -2,25 +2,14 @@ IndexedDB: Test IDBIndex.getAllKeys. + diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore-index-finished.html b/testing/web-platform/tests/IndexedDB/idbobjectstore-index-finished.html new file mode 100644 index 000000000000..75677cf39dc3 --- /dev/null +++ b/testing/web-platform/tests/IndexedDB/idbobjectstore-index-finished.html @@ -0,0 +1,26 @@ + + +IndexedDB: IDBObjectStore index() when transaction is finished + + + + + diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_deleteIndex.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_deleteIndex.htm index 1e0fb2976c88..ebebbb7db486 100644 --- a/testing/web-platform/tests/IndexedDB/idbobjectstore_deleteIndex.htm +++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_deleteIndex.htm @@ -35,6 +35,7 @@ assert_throws('NotFoundError', function() { index = objStore.index("index") }); assert_equals(index, undefined); + db.close(); t.done(); } } diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_deleted.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_deleted.htm index 1d9421ce03af..74934636a1b6 100644 --- a/testing/web-platform/tests/IndexedDB/idbobjectstore_deleted.htm +++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_deleted.htm @@ -28,16 +28,17 @@ db.deleteObjectStore("store"); assert_equals(db.objectStoreNames.length, 0, "objectStoreNames.length after delete"); - assert_throws(null, function() { objStore.add(2); }); - assert_throws(null, function() { objStore.put(3); }); - assert_throws(null, function() { objStore.get(1); }); - assert_throws(null, function() { objStore.clear(); }); - assert_throws(null, function() { objStore.count(); }); - assert_throws(null, function() { objStore.delete(1); }); - assert_throws(null, function() { objStore.openCursor(); }); - assert_throws(null, function() { objStore.index("idx"); }); - assert_throws(null, function() { objStore.deleteIndex("idx"); }); - assert_throws(null, function() { objStore.createIndex("idx2", "a"); }); + const exc = "InvalidStateError" + assert_throws(exc, function() { objStore.add(2); }); + assert_throws(exc, function() { objStore.put(3); }); + assert_throws(exc, function() { objStore.get(1); }); + assert_throws(exc, function() { objStore.clear(); }); + assert_throws(exc, function() { objStore.count(); }); + assert_throws(exc, function() { objStore.delete(1); }); + assert_throws(exc, function() { objStore.openCursor(); }); + assert_throws(exc, function() { objStore.index("idx"); }); + assert_throws(exc, function() { objStore.deleteIndex("idx"); }); + assert_throws(exc, function() { objStore.createIndex("idx2", "a"); }); } open_rq.onsuccess = function() { diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_getAll.html b/testing/web-platform/tests/IndexedDB/idbobjectstore_getAll.html index f81e4caf3d25..c9d29d3c3a42 100644 --- a/testing/web-platform/tests/IndexedDB/idbobjectstore_getAll.html +++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_getAll.html @@ -2,25 +2,14 @@ IndexedDB: Test IDBObjectStore.getAll. + diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_getAllKeys.html b/testing/web-platform/tests/IndexedDB/idbobjectstore_getAllKeys.html index f4d317d4328d..896d4df32e6a 100644 --- a/testing/web-platform/tests/IndexedDB/idbobjectstore_getAllKeys.html +++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_getAllKeys.html @@ -2,25 +2,14 @@ IndexedDB: Test IDBObjectStore.getAllKeys. + diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_getKey.html b/testing/web-platform/tests/IndexedDB/idbobjectstore_getKey.html index 19229456728b..ddb78b112132 100644 --- a/testing/web-platform/tests/IndexedDB/idbobjectstore_getKey.html +++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_getKey.html @@ -4,17 +4,12 @@ + - - -
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_openKeyCursor.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_openKeyCursor.htm index 9dc547c3ff96..345845965fe0 100644 --- a/testing/web-platform/tests/IndexedDB/idbobjectstore_openKeyCursor.htm +++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_openKeyCursor.htm @@ -2,26 +2,20 @@ IDBObjectStore.openKeyCursor() + + + + diff --git a/testing/web-platform/tests/IndexedDB/idbtransaction.htm b/testing/web-platform/tests/IndexedDB/idbtransaction.htm index 8a3484511e5d..5baa3db557d0 100644 --- a/testing/web-platform/tests/IndexedDB/idbtransaction.htm +++ b/testing/web-platform/tests/IndexedDB/idbtransaction.htm @@ -6,41 +6,54 @@ - -
diff --git a/testing/web-platform/tests/IndexedDB/idbtransaction_objectStoreNames.html b/testing/web-platform/tests/IndexedDB/idbtransaction_objectStoreNames.html index 7f6aa3518f02..da0b9aba36e0 100644 --- a/testing/web-platform/tests/IndexedDB/idbtransaction_objectStoreNames.html +++ b/testing/web-platform/tests/IndexedDB/idbtransaction_objectStoreNames.html @@ -73,7 +73,8 @@ indexeddb_test(function(t, db, tx) { assert_array_equals(saved_tx.objectStoreNames, ['s2', 's3'], 'previous transaction objectStoreNames should be unchanged'); assert_array_equals(db.objectStoreNames, saved_tx.objectStoreNames, - 'connection and transaction objectStoreNames should match'); + 'connection and transaction objectStoreNames should match'); + db2.close(); t.done(); }); }, 'IDBTransaction.objectStoreNames - value after close'); diff --git a/testing/web-platform/tests/IndexedDB/support.js b/testing/web-platform/tests/IndexedDB/support.js index cf3aa4d0ee23..7cab067fe20b 100644 --- a/testing/web-platform/tests/IndexedDB/support.js +++ b/testing/web-platform/tests/IndexedDB/support.js @@ -106,30 +106,34 @@ function assert_key_equals(actual, expected, description) { function indexeddb_test(upgrade_func, open_func, description, options) { async_test(function(t) { - var options = Object.assign({upgrade_will_abort: false}, options); + options = Object.assign({upgrade_will_abort: false}, options); var dbname = document.location + '-' + t.name; var del = indexedDB.deleteDatabase(dbname); del.onerror = t.unreached_func('deleteDatabase should succeed'); var open = indexedDB.open(dbname, 1); - if (!options.upgrade_will_abort) { - open.onsuccess = t.unreached_func('open should not succeed'); - } else { - open.onerror = t.unreached_func('open should succeed'); - } open.onupgradeneeded = t.step_func(function() { - var db = open.result; - var tx = open.transaction; - upgrade_func(t, db, tx); - }); - open.onsuccess = t.step_func(function() { var db = open.result; t.add_cleanup(function() { + // If open didn't succeed already, ignore the error. + open.onerror = function(e) { + e.preventDefault(); + }; db.close(); indexedDB.deleteDatabase(db.name); }); - if (open_func) - open_func(t, db); + var tx = open.transaction; + upgrade_func(t, db, tx); }); + if (options.upgrade_will_abort) { + open.onsuccess = t.unreached_func('open should not succeed'); + } else { + open.onerror = t.unreached_func('open should succeed'); + open.onsuccess = t.step_func(function() { + var db = open.result; + if (open_func) + open_func(t, db); + }); + } }, description); } diff --git a/testing/web-platform/tests/README.md b/testing/web-platform/tests/README.md index 94e26a2ab2f7..266d4ecc5967 100644 --- a/testing/web-platform/tests/README.md +++ b/testing/web-platform/tests/README.md @@ -40,13 +40,6 @@ following entries are required: If you are behind a proxy, you also need to make sure the domains above are excluded from your proxy lookups. -Because web-platform-tests uses git submodules, you must ensure that -these are up to date. In the root of your checkout, run: - -``` -git submodule update --init --recursive -``` - The test environment can then be started using ./serve @@ -77,6 +70,55 @@ like: "ssl": {"openssl": {"binary": "/path/to/openssl"}} ``` +Submodules +======================================= + +Some optional components of web-platform-tests (test components from +third party software and pieces of the CSS build system) are included +as submodules. To obtain these components run the following in the +root of your checkout: + +``` +git submodule update --init --recursive +``` + +Prior to commit `39d07eb01fab607ab1ffd092051cded1bdd64d78` submodules +were requried for basic functionality. If you are working with an +older checkout, the above command is required in all cases. + +When moving between a commit prior to `39d07eb` and one after it git +may complain + +``` +$ git checkout master +error: The following untracked working tree files would be overwritten by checkout: +[…] +``` + +followed by a long list of files. To avoid this error remove +the `resources` and `tools` directories before switching branches: + +``` +$ rm -r resources/ tools/ +$ git checkout master +Switched to branch 'master' +Your branch is up-to-date with 'origin/master' +``` + +When moving in the opposite direction, i.e. to a commit that does have +submodules, you will need to `git submodule update`, as above. If git +throws an error like: + +``` +fatal: No url found for submodule path 'resources/webidl2/test/widlproc' in .gitmodules +Failed to recurse into submodule path 'resources/webidl2' +fatal: No url found for submodule path 'tools/html5lib' in .gitmodules +Failed to recurse into submodule path 'resources' +Failed to recurse into submodule path 'tools' +``` + +then remove the `tools` and `resources` directories, as above. + Windows Notes ============================================= @@ -257,8 +299,8 @@ is [archived][ircarchive]. [contributing]: https://github.com/w3c/web-platform-tests/blob/master/CONTRIBUTING.md [ircw3org]: https://www.w3.org/wiki/IRC -[ircarchive]: http://krijnhoetmer.nl/irc-logs/testing/ -[mailarchive]: http://lists.w3.org/Archives/Public/public-test-infra/ +[ircarchive]: http://logs.glob.uno/?c=w3%23testing +[mailarchive]: https://lists.w3.org/Archives/Public/public-test-infra/ Documentation ============= diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/pbkdf2.js b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/pbkdf2.js index ced14d932430..74f8a6cbdb60 100644 --- a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/pbkdf2.js +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/pbkdf2.js @@ -1,5 +1,4 @@ - -function run_test() { +function run_test(testPasswordSize, testSaltSize) { // May want to test prefixed implementations. var subtle = self.crypto.subtle; @@ -28,7 +27,9 @@ function run_test() { // and number of iterations. The derivations object is structured in // that way, so navigate it to run tests and compare with correct results. Object.keys(derivations).forEach(function(passwordSize) { + if (typeof testPasswordSize != 'undefined' && testPasswordSize != passwordSize) return; Object.keys(derivations[passwordSize]).forEach(function(saltSize) { + if (typeof testSaltSize != 'undefined' && testSaltSize != saltSize) return; Object.keys(derivations[passwordSize][saltSize]).forEach(function(hashName) { Object.keys(derivations[passwordSize][saltSize][hashName]).forEach(function(iterations) { var testName = passwordSize + " password, " + saltSize + " salt, " + hashName + ", with " + iterations + " iterations"; diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_ecdh_bits.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_ecdh_bits.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_ecdh_bits.html rename to testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_ecdh_bits.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_ecdh_keys.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_ecdh_keys.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_ecdh_keys.html rename to testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_ecdh_keys.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_hkdf.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_hkdf.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_hkdf.html rename to testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_hkdf.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_empty.https.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_empty.https.html new file mode 100644 index 000000000000..15af4f38f6da --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_empty.https.html @@ -0,0 +1,22 @@ + + + +WebCryptoAPI: deriveBits() and deriveKey() Using PBKDF2 + + + + + + + + + +

deriveBits and deriveKey Tests for PBKDF2

+ +
+ diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_long.https.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_long.https.html new file mode 100644 index 000000000000..c8a251dd3f27 --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_long.https.html @@ -0,0 +1,22 @@ + + + +WebCryptoAPI: deriveBits() and deriveKey() Using PBKDF2 + + + + + + + + + +

deriveBits and deriveKey Tests for PBKDF2

+ +
+ diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_short.https.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_short.https.html new file mode 100644 index 000000000000..62da41aab5b7 --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_empty_short.https.html @@ -0,0 +1,22 @@ + + + +WebCryptoAPI: deriveBits() and deriveKey() Using PBKDF2 + + + + + + + + + +

deriveBits and deriveKey Tests for PBKDF2

+ +
+ diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_empty.https.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_empty.https.html new file mode 100644 index 000000000000..3b5845fcdfba --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_empty.https.html @@ -0,0 +1,22 @@ + + + +WebCryptoAPI: deriveBits() and deriveKey() Using PBKDF2 + + + + + + + + + +

deriveBits and deriveKey Tests for PBKDF2

+ +
+ diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_long.https.html similarity index 91% rename from testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2.html rename to testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_long.https.html index 0658b1a2fd8e..d9d04433de16 100644 --- a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2.html +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_long.https.html @@ -15,5 +15,8 @@
diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_short.https.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_short.https.html new file mode 100644 index 000000000000..fa81c7f3c1e4 --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_long_short.https.html @@ -0,0 +1,22 @@ + + + +WebCryptoAPI: deriveBits() and deriveKey() Using PBKDF2 + + + + + + + + + +

deriveBits and deriveKey Tests for PBKDF2

+ +
+ diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_empty.https.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_empty.https.html new file mode 100644 index 000000000000..2497b522c98a --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_empty.https.html @@ -0,0 +1,22 @@ + + + +WebCryptoAPI: deriveBits() and deriveKey() Using PBKDF2 + + + + + + + + + +

deriveBits and deriveKey Tests for PBKDF2

+ +
+ diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_long.https.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_long.https.html new file mode 100644 index 000000000000..f56cd2c6ad05 --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_long.https.html @@ -0,0 +1,22 @@ + + + +WebCryptoAPI: deriveBits() and deriveKey() Using PBKDF2 + + + + + + + + + +

deriveBits and deriveKey Tests for PBKDF2

+ +
+ diff --git a/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_short.https.html b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_short.https.html new file mode 100644 index 000000000000..c5fa4273b9d1 --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/derive_bits_keys/test_pbkdf2_short_short.https.html @@ -0,0 +1,22 @@ + + + +WebCryptoAPI: deriveBits() and deriveKey() Using PBKDF2 + + + + + + + + + +

deriveBits and deriveKey Tests for PBKDF2

+ +
+ diff --git a/testing/web-platform/tests/WebCryptoAPI/digest/test_digest.html b/testing/web-platform/tests/WebCryptoAPI/digest/test_digest.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/digest/test_digest.html rename to testing/web-platform/tests/WebCryptoAPI/digest/test_digest.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_cbc.html b/testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_cbc.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_cbc.html rename to testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_cbc.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_ctr.html b/testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_ctr.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_ctr.html rename to testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_ctr.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_gcm.html b/testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_gcm.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_gcm.html rename to testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_aes_gcm.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.html b/testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.html rename to testing/web-platform/tests/WebCryptoAPI/encrypt_decrypt/test_rsa_oaep.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes.js index db4aae085dea..6a74c01ddde4 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes.js @@ -1,5 +1,5 @@ -function run_test(algorithmNames) { +function run_test(algorithmNames, slowTest) { var subtle = crypto.subtle; // Change to test prefixed implementations setup({explicit_timeout: true}); @@ -74,7 +74,7 @@ function run_test(algorithmNames) { // Test all valid sets of parameters for successful // key generation. testVectors.forEach(function(vector) { - allNameVariants(vector.name).forEach(function(name) { + allNameVariants(vector.name, slowTest).forEach(function(name) { allAlgorithmSpecifiersFor(name).forEach(function(algorithm) { allValidUsages(vector.usages, false, vector.mandatoryUsages).forEach(function(usages) { [false, true].forEach(function(extractable) { diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_aes-cbc.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_aes-cbc.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_aes-cbc.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_aes-cbc.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_aes-ctr.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_aes-ctr.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_aes-ctr.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_aes-ctr.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-CBC.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-CBC.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-CBC.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-CBC.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-CTR.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-CTR.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-CTR.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-CTR.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-GCM.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-GCM.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-GCM.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-GCM.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-KW.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-KW.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-KW.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_AES-KW.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_ECDH.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_ECDH.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_ECDH.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_ECDH.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_ECDSA.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_ECDSA.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_ECDSA.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_ECDSA.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_HMAC.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_HMAC.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_HMAC.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_HMAC.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSA-OAEP.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSA-OAEP.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSA-OAEP.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSA-OAEP.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSA-PSS.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSA-PSS.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSA-PSS.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSA-PSS.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-CBC.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-CBC.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-CBC.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-CBC.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-CTR.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-CTR.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-CTR.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-CTR.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-GCM.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-GCM.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-GCM.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-GCM.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-KW.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-KW.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-KW.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_AES-KW.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_ECDH.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_ECDH.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_ECDH.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_ECDH.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_ECDSA.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_ECDSA.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_ECDSA.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_ECDSA.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_HMAC.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_HMAC.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_HMAC.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_HMAC.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.html deleted file mode 100644 index db58fd6690ab..000000000000 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.html +++ /dev/null @@ -1,23 +0,0 @@ - - - -WebCryptoAPI: generateKey() Successful Calls - - - - - - - - -

generateKey Tests for Good Parameters

-

- Warning! RSA key generation is intrinsically - very slow, so the related tests can take up to - several minutes to complete, depending on browser! -

- -
- \ No newline at end of file diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html similarity index 96% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html index 384db1cd1987..48136260390a 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes.html +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html @@ -19,5 +19,5 @@
diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-PSS.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-PSS.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-PSS.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSA-PSS.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.html b/testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.html rename to testing/web-platform/tests/WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/idlharness.https.html b/testing/web-platform/tests/WebCryptoAPI/idlharness.https.html new file mode 100644 index 000000000000..81e1e04f9c1e --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/idlharness.https.html @@ -0,0 +1,45 @@ + + + + +IDL check of WebCrypto + + + + + + + + + +

Description

+ +

This test verifies that the implementations of the WebCrypto API match with its WebIDL definition.

+ +
+ + diff --git a/testing/web-platform/tests/WebCryptoAPI/import_export/test_ec_importKey.html b/testing/web-platform/tests/WebCryptoAPI/import_export/test_ec_importKey.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/import_export/test_ec_importKey.html rename to testing/web-platform/tests/WebCryptoAPI/import_export/test_ec_importKey.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/import_export/test_rsa_importKey.html b/testing/web-platform/tests/WebCryptoAPI/import_export/test_rsa_importKey.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/import_export/test_rsa_importKey.html rename to testing/web-platform/tests/WebCryptoAPI/import_export/test_rsa_importKey.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/import_export/test_symmetric_importKey.html b/testing/web-platform/tests/WebCryptoAPI/import_export/test_symmetric_importKey.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/import_export/test_symmetric_importKey.html rename to testing/web-platform/tests/WebCryptoAPI/import_export/test_symmetric_importKey.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html b/testing/web-platform/tests/WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html new file mode 100644 index 000000000000..79bcec7a4dae --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html b/testing/web-platform/tests/WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html new file mode 100644 index 000000000000..67f7ff0b2b80 --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/WebCryptoAPI/sign_verify/test_ecdsa.html b/testing/web-platform/tests/WebCryptoAPI/sign_verify/test_ecdsa.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/sign_verify/test_ecdsa.html rename to testing/web-platform/tests/WebCryptoAPI/sign_verify/test_ecdsa.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/sign_verify/test_hmac.html b/testing/web-platform/tests/WebCryptoAPI/sign_verify/test_hmac.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/sign_verify/test_hmac.html rename to testing/web-platform/tests/WebCryptoAPI/sign_verify/test_hmac.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/sign_verify/test_rsa_pkcs.html b/testing/web-platform/tests/WebCryptoAPI/sign_verify/test_rsa_pkcs.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/sign_verify/test_rsa_pkcs.html rename to testing/web-platform/tests/WebCryptoAPI/sign_verify/test_rsa_pkcs.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/sign_verify/test_rsa_pss.html b/testing/web-platform/tests/WebCryptoAPI/sign_verify/test_rsa_pss.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/sign_verify/test_rsa_pss.html rename to testing/web-platform/tests/WebCryptoAPI/sign_verify/test_rsa_pss.https.html diff --git a/testing/web-platform/tests/WebCryptoAPI/util/helpers.js b/testing/web-platform/tests/WebCryptoAPI/util/helpers.js index fb723c3f7906..c13ce9146e2b 100644 --- a/testing/web-platform/tests/WebCryptoAPI/util/helpers.js +++ b/testing/web-platform/tests/WebCryptoAPI/util/helpers.js @@ -219,12 +219,13 @@ function allValidUsages(validUsages, emptyIsValid, mandatoryUsages) { // Algorithm name specifiers are case-insensitive. Generate several // case variations of a given name. -function allNameVariants(name) { +function allNameVariants(name, slowTest) { var upCaseName = name.toUpperCase(); var lowCaseName = name.toLowerCase(); var mixedCaseName = upCaseName.substring(0, 1) + lowCaseName.substring(1); + // for slow tests effectively cut the amount of work in third by only + // returning one variation + if (slowTest) return [mixedCaseName]; return [upCaseName, lowCaseName, mixedCaseName]; } - - diff --git a/testing/web-platform/tests/WebCryptoAPI/util/worker-report-crypto-subtle-presence.js b/testing/web-platform/tests/WebCryptoAPI/util/worker-report-crypto-subtle-presence.js new file mode 100644 index 000000000000..22cca7b6236f --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/util/worker-report-crypto-subtle-presence.js @@ -0,0 +1,3 @@ +subtle_crypto_found = true; +if (typeof crypto.subtle === 'undefined') subtle_crypto_found = false; +postMessage({ msg_type: 'subtle_crypto_found', msg_value: subtle_crypto_found }); diff --git a/testing/web-platform/tests/WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.html b/testing/web-platform/tests/WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.https.html similarity index 100% rename from testing/web-platform/tests/WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.html rename to testing/web-platform/tests/WebCryptoAPI/wrapKey_unwrapKey/test_wrapKey_unwrapKey.https.html diff --git a/testing/web-platform/tests/WebIDL/ecmascript-binding/has-instance.html b/testing/web-platform/tests/WebIDL/ecmascript-binding/has-instance.html index 986d27c9b83a..caf0be472906 100644 --- a/testing/web-platform/tests/WebIDL/ecmascript-binding/has-instance.html +++ b/testing/web-platform/tests/WebIDL/ecmascript-binding/has-instance.html @@ -1,8 +1,11 @@ - +instanceof behavior + + + diff --git a/testing/web-platform/tests/WebIDL/ecmascript-binding/interface-prototype-object.html b/testing/web-platform/tests/WebIDL/ecmascript-binding/interface-prototype-object.html new file mode 100644 index 000000000000..590710dc8e70 --- /dev/null +++ b/testing/web-platform/tests/WebIDL/ecmascript-binding/interface-prototype-object.html @@ -0,0 +1,19 @@ + + +Interface prototype objects + + + + diff --git a/testing/web-platform/tests/WebIDL/ecmascript-binding/legacy-callback-interface-object.html b/testing/web-platform/tests/WebIDL/ecmascript-binding/legacy-callback-interface-object.html new file mode 100644 index 000000000000..01a008d108cd --- /dev/null +++ b/testing/web-platform/tests/WebIDL/ecmascript-binding/legacy-callback-interface-object.html @@ -0,0 +1,69 @@ + + +Legacy callback interface objects + + + + + + diff --git a/testing/web-platform/tests/XMLHttpRequest/formdata-foreach.html b/testing/web-platform/tests/XMLHttpRequest/formdata-foreach.html index 9b10367aece1..3ad184c4d557 100644 --- a/testing/web-platform/tests/XMLHttpRequest/formdata-foreach.html +++ b/testing/web-platform/tests/XMLHttpRequest/formdata-foreach.html @@ -14,8 +14,12 @@ fd.append('n2', 'v5'); fd.append('n3', 'v6'); fd.delete('n2'); - var expected_keys = ['n1', 'n3', 'n1', 'n3']; - var expected_values = ['v1', 'v3', 'v4', 'v6']; + + var file = new File(['hello'], "hello.txt"); + fd.append('f1', file); + + var expected_keys = ['n1', 'n3', 'n1', 'n3', 'f1']; + var expected_values = ['v1', 'v3', 'v4', 'v6', file]; test(function() { var mykeys = [], myvalues = []; for(var entry of fd) { diff --git a/testing/web-platform/tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm b/testing/web-platform/tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm index 3cbdb9c068cb..0659a3a05e25 100644 --- a/testing/web-platform/tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm +++ b/testing/web-platform/tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm @@ -18,7 +18,7 @@ assert_equals(client.getResponseHeader('Trailer'), 'X-Test-Me') assert_equals(client.getResponseHeader('X-Test-Me'), null) assert_equals(client.getAllResponseHeaders().indexOf('Trailer header value'), -1) - assert_regexp_match(client.getAllResponseHeaders(), /Trailer:\sX-Test-Me/) + assert_regexp_match(client.getAllResponseHeaders(), /trailer:\sX-Test-Me/) assert_equals(client.responseText, "First chunk\r\nSecond chunk\r\nYet another (third) chunk\r\nYet another (fourth) chunk\r\n") test.done() } diff --git a/testing/web-platform/tests/XMLHttpRequest/interfaces.html b/testing/web-platform/tests/XMLHttpRequest/interfaces.html index 96de3c00f949..56ba5523e318 100644 --- a/testing/web-platform/tests/XMLHttpRequest/interfaces.html +++ b/testing/web-platform/tests/XMLHttpRequest/interfaces.html @@ -9,46 +9,6 @@

XMLHttpRequest IDL tests

- diff --git a/testing/web-platform/tests/accelerometer/Accelerometer.https.html b/testing/web-platform/tests/accelerometer/Accelerometer.https.html new file mode 100644 index 000000000000..6421ab568d98 --- /dev/null +++ b/testing/web-platform/tests/accelerometer/Accelerometer.https.html @@ -0,0 +1,16 @@ + + +Accelerometer Test + + + + + +
+ + diff --git a/testing/web-platform/tests/accelerometer/Accelerometer_insecure_context.html b/testing/web-platform/tests/accelerometer/Accelerometer_insecure_context.html new file mode 100644 index 000000000000..4ff4789c37e8 --- /dev/null +++ b/testing/web-platform/tests/accelerometer/Accelerometer_insecure_context.html @@ -0,0 +1,20 @@ + + +Accelerometer Test: insecure context + + + + + +
+

Precondition

+
    +
  1. + Run test in an insecure context, e.g. http://example.com/. +
  2. +
+ diff --git a/testing/web-platform/tests/accelerometer/Accelerometer_onerror-manual.https.html b/testing/web-platform/tests/accelerometer/Accelerometer_onerror-manual.https.html new file mode 100644 index 000000000000..a3e815001222 --- /dev/null +++ b/testing/web-platform/tests/accelerometer/Accelerometer_onerror-manual.https.html @@ -0,0 +1,20 @@ + + +Accelerometer Test: onerror + + + + + +
+

Precondition

+
    +
  1. + Disable the Accelerometer Sensor or run test on a device without Accelerometer Sensor. +
  2. +
+ diff --git a/testing/web-platform/tests/accelerometer/idlharness.https.html b/testing/web-platform/tests/accelerometer/idlharness.https.html index 79cd5c925d74..66e228cda155 100644 --- a/testing/web-platform/tests/accelerometer/idlharness.https.html +++ b/testing/web-platform/tests/accelerometer/idlharness.https.html @@ -2,7 +2,8 @@ Accelerometer Sensor IDL tests - + + @@ -18,24 +19,24 @@ interface Event { }; -interface EventTarget { -}; - -interface EventHandler { -}; - interface Error { }; dictionary EventInit { }; + +interface EventTarget { +}; + +interface EventHandler { +};
 [SecureContext]
 interface Sensor : EventTarget {
-  readonly attribute SensorState state;
-  readonly attribute SensorReading? reading;
+  readonly attribute boolean activated;
+  readonly attribute DOMHighResTimeStamp? timestamp;
   void start();
   void stop();
   attribute EventHandler onchange;
@@ -47,18 +48,6 @@ dictionary SensorOptions {
   double? frequency;
 };
 
-enum SensorState {
-  "idle",
-  "activating",
-  "activated",
-  "errored"
-};
-
-[SecureContext]
-interface SensorReading {
-  readonly attribute DOMHighResTimeStamp timeStamp;
-};
-
 [SecureContext, Constructor(DOMString type, SensorErrorEventInit errorEventInitDict)]
 interface SensorErrorEvent : Event {
   readonly attribute Error error;
@@ -67,47 +56,41 @@ interface SensorErrorEvent : Event {
 dictionary SensorErrorEventInit : EventInit {
   required Error error;
 };
-
 
-[Constructor(optional AccelerometerOptions accelerometerOptions)]
+[Constructor(optional SensorOptions options)]
 interface Accelerometer : Sensor {
-  readonly attribute AccelerometerReading? reading;
-  readonly attribute boolean includesGravity;
+  readonly attribute unrestricted double? x;
+  readonly attribute unrestricted double? y;
+  readonly attribute unrestricted double? z;
 };
 
-dictionary AccelerometerOptions :  SensorOptions  {
-  boolean includeGravity = true;
+[Constructor(optional SensorOptions options)]
+interface LinearAccelerationSensor : Accelerometer {
 };
 
-[Constructor(AccelerometerReadingInit AccelerometerReadingInit)]
-interface AccelerometerReading : SensorReading {
-    readonly attribute double x;
-    readonly attribute double y;
-    readonly attribute double z;
-};
-
-dictionary AccelerometerReadingInit {
-    double x = 0;
-    double y = 0;
-    double z = 0;
+[Constructor(optional SensorOptions options)]
+interface GravitySensor : Accelerometer {
 };
 
diff --git a/testing/web-platform/tests/accelerometer/support-iframe.html b/testing/web-platform/tests/accelerometer/support-iframe.html new file mode 100644 index 000000000000..a123f486bea3 --- /dev/null +++ b/testing/web-platform/tests/accelerometer/support-iframe.html @@ -0,0 +1,10 @@ + + + diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor.https.html b/testing/web-platform/tests/ambient-light/AmbientLightSensor.https.html new file mode 100644 index 000000000000..5e2310d0d853 --- /dev/null +++ b/testing/web-platform/tests/ambient-light/AmbientLightSensor.https.html @@ -0,0 +1,16 @@ + + +AmbientLightSensor Test + + + + + +
+ + diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor.js b/testing/web-platform/tests/ambient-light/AmbientLightSensor.js deleted file mode 100644 index 5a1f8ea2ff59..000000000000 --- a/testing/web-platform/tests/ambient-light/AmbientLightSensor.js +++ /dev/null @@ -1,5 +0,0 @@ -(function() { - test(function() { - assert_true(false); - }, 'Test suite not implemented yet.'); -})(); diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor_browsing_context.https.html b/testing/web-platform/tests/ambient-light/AmbientLightSensor_browsing_context.https.html deleted file mode 100644 index 1b045bd9eeaf..000000000000 --- a/testing/web-platform/tests/ambient-light/AmbientLightSensor_browsing_context.https.html +++ /dev/null @@ -1,33 +0,0 @@ - - -AmbientLightSensor Test: Sensor readings must only be available in the top-level browsing context - - - - -
- - diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor_insecure_context.html b/testing/web-platform/tests/ambient-light/AmbientLightSensor_insecure_context.html index 76662e07eb7c..de900e048943 100644 --- a/testing/web-platform/tests/ambient-light/AmbientLightSensor_insecure_context.html +++ b/testing/web-platform/tests/ambient-light/AmbientLightSensor_insecure_context.html @@ -5,19 +5,16 @@ + +

Precondition

  1. Run test in an insecure context, e.g. http://example.com/.
-
diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor_onchange.https.html b/testing/web-platform/tests/ambient-light/AmbientLightSensor_onchange.https.html deleted file mode 100644 index 737bb755234b..000000000000 --- a/testing/web-platform/tests/ambient-light/AmbientLightSensor_onchange.https.html +++ /dev/null @@ -1,26 +0,0 @@ - - -AmbientLightSensor Test: onchange - - - - -
- diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor_onerror-manual.https.html b/testing/web-platform/tests/ambient-light/AmbientLightSensor_onerror-manual.https.html index d7811cfa6676..8bcb9082cc9d 100644 --- a/testing/web-platform/tests/ambient-light/AmbientLightSensor_onerror-manual.https.html +++ b/testing/web-platform/tests/ambient-light/AmbientLightSensor_onerror-manual.https.html @@ -5,28 +5,16 @@ + +

Precondition

  1. Disable the Ambient Light Sensor or run test on a device without Amibent Light Sensor.
-
diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor_reading.https.html b/testing/web-platform/tests/ambient-light/AmbientLightSensor_reading.https.html deleted file mode 100644 index 34eab24f9b1b..000000000000 --- a/testing/web-platform/tests/ambient-light/AmbientLightSensor_reading.https.html +++ /dev/null @@ -1,64 +0,0 @@ - - -AmbientLightSensor Test: reading - - - - -
- diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor_start.https.html b/testing/web-platform/tests/ambient-light/AmbientLightSensor_start.https.html deleted file mode 100644 index e08a2490ff0b..000000000000 --- a/testing/web-platform/tests/ambient-light/AmbientLightSensor_start.https.html +++ /dev/null @@ -1,43 +0,0 @@ - - -AmbientLightSensor Test: start() - - - - -
- diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor_stop.https.html b/testing/web-platform/tests/ambient-light/AmbientLightSensor_stop.https.html deleted file mode 100644 index 8f504c5fe817..000000000000 --- a/testing/web-platform/tests/ambient-light/AmbientLightSensor_stop.https.html +++ /dev/null @@ -1,35 +0,0 @@ - - -AmbientLightSensor Test: stop() - - - - -
- diff --git a/testing/web-platform/tests/ambient-light/AmbientLightSensor_tests.html b/testing/web-platform/tests/ambient-light/AmbientLightSensor_tests.html deleted file mode 100644 index 2008597152b5..000000000000 --- a/testing/web-platform/tests/ambient-light/AmbientLightSensor_tests.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - -Ambient Light Sensor Test Suite - - - - -
- diff --git a/testing/web-platform/tests/ambient-light/idlharness.https.html b/testing/web-platform/tests/ambient-light/idlharness.https.html index 307d53c82d3a..2ccc23f598d4 100644 --- a/testing/web-platform/tests/ambient-light/idlharness.https.html +++ b/testing/web-platform/tests/ambient-light/idlharness.https.html @@ -2,7 +2,8 @@ Ambient Light Sensor IDL tests - + + @@ -18,24 +19,24 @@ interface Event { }; -interface EventTarget { -}; - -interface EventHandler { -}; - interface Error { }; dictionary EventInit { }; + +interface EventTarget { +}; + +interface EventHandler { +};
 [SecureContext]
 interface Sensor : EventTarget {
-  readonly attribute SensorState state;
-  readonly attribute SensorReading? reading;
+  readonly attribute boolean activated;
+  readonly attribute DOMHighResTimeStamp? timestamp;
   void start();
   void stop();
   attribute EventHandler onchange;
@@ -47,18 +48,6 @@ dictionary SensorOptions {
   double? frequency;
 };
 
-enum SensorState {
-  "idle",
-  "activating",
-  "activated",
-  "errored"
-};
-
-[SecureContext]
-interface SensorReading {
-  readonly attribute DOMHighResTimeStamp timeStamp;
-};
-
 [SecureContext, Constructor(DOMString type, SensorErrorEventInit errorEventInitDict)]
 interface SensorErrorEvent : Event {
   readonly attribute Error error;
@@ -67,38 +56,29 @@ interface SensorErrorEvent : Event {
 dictionary SensorErrorEventInit : EventInit {
   required Error error;
 };
-
 
 [Constructor(optional SensorOptions sensorOptions)]
 interface AmbientLightSensor : Sensor {
-};
-
-[Constructor(AmbientLightSensorReadingInit ambientLightSensorReadingInit)]
-interface AmbientLightSensorReading : SensorReading {
-    readonly attribute unrestricted double illuminance;
-};
-
-dictionary AmbientLightSensorReadingInit {
-  required unrestricted double illuminance;
+  readonly attribute unrestricted double? illuminance;
 };
 
+ diff --git a/testing/web-platform/tests/ambient-light/support-iframe.html b/testing/web-platform/tests/ambient-light/support-iframe.html index 5041a6861a4e..17ff8e7aca2a 100644 --- a/testing/web-platform/tests/ambient-light/support-iframe.html +++ b/testing/web-platform/tests/ambient-light/support-iframe.html @@ -3,8 +3,8 @@ diff --git a/testing/web-platform/tests/apng/animated-png-timeout-ref.html b/testing/web-platform/tests/apng/animated-png-timeout-ref.html new file mode 100644 index 000000000000..c46bb9016499 --- /dev/null +++ b/testing/web-platform/tests/apng/animated-png-timeout-ref.html @@ -0,0 +1 @@ + diff --git a/testing/web-platform/tests/apng/animated-png-timeout.html b/testing/web-platform/tests/apng/animated-png-timeout.html new file mode 100644 index 000000000000..6975bd9c4e73 --- /dev/null +++ b/testing/web-platform/tests/apng/animated-png-timeout.html @@ -0,0 +1,11 @@ + +APNG: Second frame displays quickly, replacing red with green. + + + diff --git a/testing/web-platform/tests/bluetooth/OWNERS b/testing/web-platform/tests/bluetooth/OWNERS new file mode 100644 index 000000000000..9a9c462090d9 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/OWNERS @@ -0,0 +1,3 @@ +@jyasskin +@g-ortuno +@scheib diff --git a/testing/web-platform/tests/bluetooth/idl-Bluetooth.html b/testing/web-platform/tests/bluetooth/idl-Bluetooth.html index 129a10cd70be..b0263f980a8e 100644 --- a/testing/web-platform/tests/bluetooth/idl-Bluetooth.html +++ b/testing/web-platform/tests/bluetooth/idl-Bluetooth.html @@ -6,9 +6,9 @@ 'use strict'; test(() => { - assert_throws(null, () => new Bluetooth(), + assert_throws(new TypeError(), () => new Bluetooth(), 'the constructor should not be callable with "new"'); - assert_throws(null, () => Bluetooth(), + assert_throws(new TypeError(), () => Bluetooth(), 'the constructor should not be callable'); // Bluetooth implements BluetoothDiscovery; diff --git a/testing/web-platform/tests/check_stability.ini b/testing/web-platform/tests/check_stability.ini new file mode 100644 index 000000000000..cf18896a0b66 --- /dev/null +++ b/testing/web-platform/tests/check_stability.ini @@ -0,0 +1,9 @@ +[file detection] +skip_tests: conformance-checkers docs tools +# The vast majority of tests rely on files located within the `resources` +# directory. Because of this, modifications to that directory's contents have +# the potential to introduce instability in a large number of tests. +# Exhaustively validating such changes is highly resource intensive +# (particularly in terms of execution time), making it impractical in most +# cases. +ignore_changes: resources diff --git a/testing/web-platform/tests/check_stability.py b/testing/web-platform/tests/check_stability.py index 6dcee782a803..08d75e7b9bc5 100644 --- a/testing/web-platform/tests/check_stability.py +++ b/testing/web-platform/tests/check_stability.py @@ -9,10 +9,11 @@ import subprocess import sys import tarfile import zipfile +from ConfigParser import RawConfigParser, SafeConfigParser from abc import ABCMeta, abstractmethod from cStringIO import StringIO as CStringIO from collections import defaultdict, OrderedDict -from ConfigParser import RawConfigParser +from distutils.spawn import find_executable from io import BytesIO, StringIO import requests @@ -171,6 +172,12 @@ class Browser(object): def wptrunner_args(self): return NotImplemented + def prepare_environment(self): + """Do any additional setup of the environment required to start the + browser successfully + """ + pass + class Firefox(Browser): """Firefox-specific interface. @@ -282,6 +289,26 @@ class Chrome(Browser): "test_types": ["testharness", "reftest"] } + def prepare_environment(self): + # https://bugs.chromium.org/p/chromium/issues/detail?id=713947 + logger.debug("DBUS_SESSION_BUS_ADDRESS %s" % os.environ.get("DBUS_SESSION_BUS_ADDRESS")) + if "DBUS_SESSION_BUS_ADDRESS" not in os.environ: + if find_executable("dbus-launch"): + logger.debug("Attempting to start dbus") + dbus_conf = subprocess.check_output(["dbus-launch"]) + logger.debug(dbus_conf) + + # From dbus-launch(1): + # + # > When dbus-launch prints bus information to standard output, + # > by default it is in a simple key-value pairs format. + for line in dbus_conf.strip().split("\n"): + key, _, value = line.partition("=") + os.environ[key] = value + else: + logger.critical("dbus not running and can't be started") + sys.exit(1) + def get(url): """Issue GET request to a given URL and return the response.""" @@ -383,10 +410,7 @@ def build_manifest(): def install_wptrunner(): - """Clone and install wptrunner.""" - call("git", "clone", "--depth=1", "https://github.com/w3c/wptrunner.git", wptrunner_root) - git = get_git_cmd(wptrunner_root) - git("submodule", "update", "--init", "--recursive") + """Install wptrunner.""" call("pip", "install", wptrunner_root) @@ -394,27 +418,42 @@ def get_branch_point(user): git = get_git_cmd(wpt_root) if os.environ.get("TRAVIS_PULL_REQUEST", "false") != "false": # This is a PR, so the base branch is in TRAVIS_BRANCH - branch_point = os.environ.get("TRAVIS_COMMIT_RANGE").split(".", 1)[0] - branch_point = git("rev-parse", branch_point) + travis_branch = os.environ.get("TRAVIS_BRANCH") + assert travis_branch, "TRAVIS_BRANCH environment variable is defined" + branch_point = git("rev-parse", travis_branch) else: # Otherwise we aren't on a PR, so we try to find commits that are only in the # current branch c.f. # http://stackoverflow.com/questions/13460152/find-first-ancestor-commit-in-another-branch head = git("rev-parse", "HEAD") # To do this we need all the commits in the local copy - fetch_wpt(user, "--unshallow", "+refs/heads/*:refs/remotes/origin/*") + fetch_args = [user, "+refs/heads/*:refs/remotes/origin/*"] + if os.path.exists(os.path.join(wpt_root, ".git", "shallow")): + fetch_args.insert(1, "--unshallow") + fetch_wpt(*fetch_args) not_heads = [item for item in git("rev-parse", "--not", "--all").split("\n") - if not head in item] + if item.strip() and not head in item] commits = git("rev-list", "HEAD", *not_heads).split("\n") - first_commit = commits[-1] - branch_point = git("rev-parse", first_commit + "^") - # The above can produce a too-early commit if we are e.g. on master and there are - # preceding changes that were rebased and so aren't on any other branch. To avoid - # this issue we check for the later of the above branch point and the merge-base - # with master + branch_point = None + if len(commits): + first_commit = commits[-1] + if first_commit: + branch_point = git("rev-parse", first_commit + "^") + + # The above heuristic will fail in the following cases: + # + # - The current branch has fallen behind the version retrieved via the above + # `fetch` invocation + # - Changes on the current branch were rebased and therefore do not exist on any + # other branch. This will result in the selection of a commit that is earlier + # in the history than desired (as determined by calculating the later of the + # branch point and the merge base) + # + # In either case, fall back to using the merge base as the branch point. merge_base = git("merge-base", "HEAD", "origin/master") - if (branch_point != merge_base and - not git("log", "--oneline", "%s..%s" % (merge_base, branch_point)).strip()): + if (branch_point is None or + (branch_point != merge_base and + not git("log", "--oneline", "%s..%s" % (merge_base, branch_point)).strip())): logger.debug("Using merge-base as the branch point") branch_point = merge_base else: @@ -424,24 +463,34 @@ def get_branch_point(user): return branch_point -def get_files_changed(branch_point): - """Get and return files changed since current branch diverged from master.""" +def get_files_changed(branch_point, ignore_changes): + """Get and return files changed since current branch diverged from master, + excluding those that are located within any directory specifed by + `ignore_changes`.""" root = os.path.abspath(os.curdir) git = get_git_cmd(wpt_root) - files = git("diff", "--name-only", "-z", "%s.." % branch_point) + files = git("diff", "--name-only", "-z", "%s..." % branch_point) if not files: - return [] + return [], [] assert files[-1] == "\0" - return [os.path.join(wpt_root, item) - for item in files[:-1].split("\0")] + changed = [] + ignored = [] + for item in files[:-1].split("\0"): + fullpath = os.path.join(wpt_root, item) + topmost_dir = item.split(os.sep, 1)[0] + if topmost_dir in ignore_changes: + ignored.append(fullpath) + else: + changed.append(fullpath) -def get_affected_testfiles(files_changed): + return changed, ignored + +def get_affected_testfiles(files_changed, skip_tests): """Determine and return list of test files that reference changed files.""" affected_testfiles = set() nontests_changed = set(files_changed) manifest_file = os.path.join(wpt_root, "MANIFEST.json") - skip_dirs = ["conformance-checkers", "docs", "tools"] test_types = ["testharness", "reftest", "wdspec"] wpt_manifest = manifest.load(wpt_root, manifest_file) @@ -462,7 +511,7 @@ def get_affected_testfiles(files_changed): # (because it's not part of any test). continue top_level_subdir = path_components[0] - if top_level_subdir in skip_dirs: + if top_level_subdir in skip_tests: continue repo_path = "/" + os.path.relpath(full_path, wpt_root).replace(os.path.sep, "/") nontest_changed_paths.add((full_path, repo_path)) @@ -471,7 +520,7 @@ def get_affected_testfiles(files_changed): # Walk top_level_subdir looking for test files containing either the # relative filepath or absolute filepatch to the changed files. if root == wpt_root: - for dir_name in skip_dirs: + for dir_name in skip_tests: dirs.remove(dir_name) for fname in fnames: test_full_path = os.path.join(root, fname) @@ -617,6 +666,7 @@ def markdown_adjust(s): s = s.replace('\n', u'\\n') s = s.replace('\r', u'\\r') s = s.replace('`', u'') + s = s.replace('|', u'\\|') return s @@ -691,7 +741,9 @@ def write_results(results, iterations, comment_pr): def get_parser(): """Create and return script-specific argument parser.""" - parser = argparse.ArgumentParser() + description = """Detect instabilities in new tests by executing tests + repeatedly and comparing results between executions.""" + parser = argparse.ArgumentParser(description=description) parser.add_argument("--root", action="store", default=os.path.join(os.path.expanduser("~"), "build"), @@ -709,12 +761,17 @@ def get_parser(): action="store", # Travis docs say do not depend on USER env variable. # This is a workaround to get what should be the same value - default=os.environ.get("TRAVIS_REPO_SLUG").split('/')[0], + default=os.environ.get("TRAVIS_REPO_SLUG", "w3c").split('/')[0], help="Travis user name") parser.add_argument("--output-bytes", action="store", type=int, help="Maximum number of bytes to write to standard output/error") + parser.add_argument("--config-file", + action="store", + type=str, + help="Location of ini-formatted configuration file", + default="check_stability.ini") parser.add_argument("product", action="store", help="Product to run against (`browser-name` or 'browser-name:channel')") @@ -731,6 +788,12 @@ def main(): parser = get_parser() args = parser.parse_args() + with open(args.config_file, 'r') as config_fp: + config = SafeConfigParser() + config.readfp(config_fp) + skip_tests = config.get("file detection", "skip_tests").split() + ignore_changes = set(config.get("file detection", "ignore_changes").split()) + if args.output_bytes is not None: replace_streams(args.output_bytes, "Log reached capacity (%s bytes); output disabled." % args.output_bytes) @@ -739,7 +802,7 @@ def main(): setup_logging() wpt_root = os.path.abspath(os.curdir) - wptrunner_root = os.path.normpath(os.path.join(wpt_root, "..", "wptrunner")) + wptrunner_root = os.path.normpath(os.path.join(wpt_root, "tools", "wptrunner")) if not os.path.exists(args.root): logger.critical("Root directory %s does not exist" % args.root) @@ -767,7 +830,11 @@ def main(): # For now just pass the whole list of changed files to wptrunner and # assume that it will run everything that's actually a test - files_changed = get_files_changed(branch_point) + files_changed, files_ignored = get_files_changed(branch_point, ignore_changes) + + if files_ignored: + logger.info("Ignoring %s changed files:\n%s" % (len(files_ignored), + "".join(" * %s\n" % item for item in files_ignored))) if not files_changed: logger.info("No files changed") @@ -789,7 +856,7 @@ def main(): logger.debug("Files changed:\n%s" % "".join(" * %s\n" % item for item in files_changed)) - affected_testfiles = get_affected_testfiles(files_changed) + affected_testfiles = get_affected_testfiles(files_changed, skip_tests) logger.debug("Affected tests:\n%s" % "".join(" * %s\n" % item for item in affected_testfiles)) @@ -800,6 +867,8 @@ def main(): args.iterations, browser) + browser.prepare_environment() + with TravisFold("running_tests"): logger.info("Starting %i test iterations" % args.iterations) with open("raw.log", "wb") as log: @@ -840,6 +909,8 @@ if __name__ == "__main__": try: retcode = main() except: - raise + import traceback + traceback.print_exc() + sys.exit(1) else: sys.exit(retcode) diff --git a/testing/web-platform/tests/ci_unittest.sh b/testing/web-platform/tests/ci_unittest.sh new file mode 100755 index 000000000000..410b883def72 --- /dev/null +++ b/testing/web-platform/tests/ci_unittest.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +ROOT=$PWD +pip install -U tox codecov +cd tools +tox + +if [ $TOXENV == "py27" ] || [ $TOXENV == "pypy" ]; then + cd wptrunner + tox +fi + +cd $ROOT + +coverage combine tools tools/wptrunner +codecov diff --git a/testing/web-platform/tests/clipboard/OWNERS b/testing/web-platform/tests/clipboard/OWNERS index 01c0055fd913..6332787efaff 100644 --- a/testing/web-platform/tests/clipboard/OWNERS +++ b/testing/web-platform/tests/clipboard/OWNERS @@ -1 +1,2 @@ +@garykac @hallvors diff --git a/testing/web-platform/tests/common/PrefixedPostMessage.js b/testing/web-platform/tests/common/PrefixedPostMessage.js new file mode 100644 index 000000000000..674b52877c0d --- /dev/null +++ b/testing/web-platform/tests/common/PrefixedPostMessage.js @@ -0,0 +1,100 @@ +/** + * Supports pseudo-"namespacing" for window-posted messages for a given test + * by generating and using a unique prefix that gets wrapped into message + * objects. This makes it more feasible to have multiple tests that use + * `window.postMessage` in a single test file. Basically, make it possible + * for the each test to listen for only the messages that are pertinent to it. + * + * 'Prefix' not an elegant term to use here but this models itself after + * PrefixedLocalStorage. + * + * PrefixedMessageTest: Instantiate in testharness.js tests to generate + * a new unique-ish prefix that can be used by other test support files + * PrefixedMessageResource: Instantiate in supporting test resource + * files to use/share a prefix generated by a test. + */ +var PrefixedMessage = function () { + this.prefix = ''; + this.param = 'prefixedMessage'; // Param to use in querystrings +}; + +/** + * Generate a URL that adds/replaces param with this object's prefix + * Use to link to test support files that make use of + * PrefixedMessageResource. + */ +PrefixedMessage.prototype.url = function (uri) { + function updateUrlParameter (uri, key, value) { + var i = uri.indexOf('#'); + var hash = (i === -1) ? '' : uri.substr(i); + uri = (i === -1) ? uri : uri.substr(0, i); + var re = new RegExp(`([?&])${key}=.*?(&|$)`, 'i'); + var separator = uri.indexOf('?') !== -1 ? '&' : '?'; + uri = (uri.match(re)) ? uri.replace(re, `$1${key}=${value}$2`) : + `${uri}${separator}${key}=${value}`; + return uri + hash; + } + return updateUrlParameter(uri, this.param, this.prefix); +}; + +/** + * Add an eventListener on `message` but only invoke the given callback + * for messages whose object contains this object's prefix. Remove the + * event listener once the anticipated message has been received. + */ +PrefixedMessage.prototype.onMessage = function (fn) { + window.addEventListener('message', e => { + if (typeof e.data === 'object' && e.data.hasOwnProperty('prefix')) { + if (e.data.prefix === this.prefix) { + // Only invoke callback when `data` is an object containing + // a `prefix` key with this object's prefix value + // Note fn is invoked with "unwrapped" data first, then the event `e` + // (which contains the full, wrapped e.data should it be needed) + fn.call(this, e.data.data, e); + window.removeEventListener('message', fn); + } + } + }); +}; + +/** + * Instantiate in a test file (e.g. during `setup`) to create a unique-ish + * prefix that can be shared by support files + */ +var PrefixedMessageTest = function () { + PrefixedMessage.call(this); + this.prefix = `${document.location.pathname}-${Math.random()}-${Date.now()}-`; +}; +PrefixedMessageTest.prototype = Object.create(PrefixedMessage.prototype); +PrefixedMessageTest.prototype.constructor = PrefixedMessageTest; + +/** + * Instantiate in a test support script to use a "prefix" generated by a + * PrefixedMessageTest in a controlling test file. It will look for + * the prefix in a URL param (see also PrefixedMessage#url) + */ +var PrefixedMessageResource = function () { + PrefixedMessage.call(this); + // Check URL querystring for prefix to use + var regex = new RegExp(`[?&]${this.param}(=([^&#]*)|&|#|$)`), + results = regex.exec(document.location.href); + if (results && results[2]) { + this.prefix = results[2]; + } +}; +PrefixedMessageResource.prototype = Object.create(PrefixedMessage.prototype); +PrefixedMessageResource.prototype.constructor = PrefixedMessageResource; + +/** + * This is how a test resource document can "send info" to its + * opener context. It will whatever message is being sent (`data`) in + * an object that injects the prefix. + */ +PrefixedMessageResource.prototype.postToOpener = function (data) { + if (window.opener) { + window.opener.postMessage({ + prefix: this.prefix, + data: data + }, '*'); + } +}; diff --git a/testing/web-platform/tests/common/object-association.js b/testing/web-platform/tests/common/object-association.js new file mode 100644 index 000000000000..cd1453e4739f --- /dev/null +++ b/testing/web-platform/tests/common/object-association.js @@ -0,0 +1,64 @@ +"use strict"; + +// For now this only has per-Window tests, but we could expand it to also test per-Document + +window.testIsPerWindow = propertyName => { + test(t => { + const iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + const frame = iframe.contentWindow; + + const before = frame[propertyName]; + assert_true(before !== undefined && before !== null, `window.${propertyName} must be implemented`); + + iframe.remove(); + + const after = frame[propertyName]; + assert_equals(after, before); + }, `Discarding the browsing context must not change window.${propertyName}`); + + async_test(t => { + const iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + const frame = iframe.contentWindow; + + const before = frame[propertyName]; + assert_true(before !== undefined && before !== null, `window.${propertyName} must be implemented`); + + // Note: cannot use step_func_done for this because it might be called twice, per the below comment. + iframe.onload = t.step_func(() => { + if (frame.location.href === "about:blank") { + // Browsers are not reliable on whether about:blank fires the load event; see + // https://github.com/whatwg/html/issues/490 + return; + } + + const after = frame[propertyName]; + assert_equals(after, before); + t.done(); + }); + + iframe.src = "/common/blank.html"; + }, `Navigating from the initial about:blank must not replace window.${propertyName}`); + + // Note: document.open()'s spec doesn't match most browsers; see https://github.com/whatwg/html/issues/1698. + // However, as explained in https://github.com/whatwg/html/issues/1698#issuecomment-298748641, even an updated spec + // will probably still reset Window-associated properties. + async_test(t => { + const iframe = document.createElement("iframe"); + + iframe.onload = t.step_func_done(() => { + const frame = iframe.contentWindow; + const before = frame[propertyName]; + assert_true(before !== undefined && before !== null, `window.${propertyName} must be implemented`); + + frame.document.open(); + + const after = frame[propertyName]; + assert_not_equals(after, before); + }); + + iframe.src = "/common/blank.html"; + document.body.appendChild(iframe); + }, `document.open() must replace window.${propertyName}`); +}; diff --git a/testing/web-platform/tests/common/performance-timeline-utils.js b/testing/web-platform/tests/common/performance-timeline-utils.js new file mode 100644 index 000000000000..268bb114722b --- /dev/null +++ b/testing/web-platform/tests/common/performance-timeline-utils.js @@ -0,0 +1,40 @@ +var performanceNamespace = window.performance; +var namespace_check = false; +function wp_test(func, msg, properties) +{ + // only run the namespace check once + if (!namespace_check) + { + namespace_check = true; + + if (performanceNamespace === undefined || performanceNamespace == null) + { + // show a single error that window.performance is undefined + test(function() { assert_true(performanceNamespace !== undefined && performanceNamespace != null, "window.performance is defined and not null"); }, "window.performance is defined and not null.", {author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "}); + } + } + + test(func, msg, properties); +} + +function test_true(value, msg, properties) +{ + wp_test(function () { assert_true(value, msg); }, msg, properties); +} + +function test_equals(value, equals, msg, properties) +{ + wp_test(function () { assert_equals(value, equals, msg); }, msg, properties); +} + +// assert for every entry in `expectedEntries`, there is a matching entry _somewhere_ in `actualEntries` +function test_entries(actualEntries, expectedEntries) { + test_equals(actualEntries.length, expectedEntries.length) + expectedEntries.forEach(function (expectedEntry) { + test_true(!!actualEntries.find(function (actualEntry) { + return typeof Object.keys(expectedEntry).find(function (key) { + return actualEntry[key] !== expectedEntry[key] + }) === 'undefined' + })) + }) +} diff --git a/testing/web-platform/tests/content-security-policy/child-src/child-src-allowed.sub.html b/testing/web-platform/tests/content-security-policy/child-src/child-src-allowed.sub.html index 12a075adb653..6fee98883da0 100644 --- a/testing/web-platform/tests/content-security-policy/child-src/child-src-allowed.sub.html +++ b/testing/web-platform/tests/content-security-policy/child-src/child-src-allowed.sub.html @@ -55,7 +55,7 @@ Content-Security-Policy: child-src 'self'; script-src 'self' 'unsafe-inline'; co - +
diff --git a/testing/web-platform/tests/content-security-policy/child-src/child-src-blocked.sub.html b/testing/web-platform/tests/content-security-policy/child-src/child-src-blocked.sub.html index e32cc0af05eb..3d14da43e00d 100644 --- a/testing/web-platform/tests/content-security-policy/child-src/child-src-blocked.sub.html +++ b/testing/web-platform/tests/content-security-policy/child-src/child-src-blocked.sub.html @@ -53,9 +53,9 @@ child-src 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self'; - +
- + diff --git a/testing/web-platform/tests/content-security-policy/child-src/child-src-conflicting-frame-src.sub.html b/testing/web-platform/tests/content-security-policy/child-src/child-src-conflicting-frame-src.sub.html index b681253ae016..d11b7a3af6b1 100644 --- a/testing/web-platform/tests/content-security-policy/child-src/child-src-conflicting-frame-src.sub.html +++ b/testing/web-platform/tests/content-security-policy/child-src/child-src-conflicting-frame-src.sub.html @@ -53,7 +53,7 @@ frame-src 'none'; child-src 'self'; script-src 'self' 'unsafe-inline'; connect-s - +
diff --git a/testing/web-platform/tests/content-security-policy/child-src/child-src-cross-origin-load.sub.html b/testing/web-platform/tests/content-security-policy/child-src/child-src-cross-origin-load.sub.html index b6f3e5164e27..81bb003d652e 100644 --- a/testing/web-platform/tests/content-security-policy/child-src/child-src-cross-origin-load.sub.html +++ b/testing/web-platform/tests/content-security-policy/child-src/child-src-cross-origin-load.sub.html @@ -58,11 +58,11 @@ child-src 'self' http://www1.{{host}}:{{ports[http][0]}}; script-src 'self' 'uns - - - + + +
- + diff --git a/testing/web-platform/tests/content-security-policy/child-src/child-src-redirect-blocked.sub.html b/testing/web-platform/tests/content-security-policy/child-src/child-src-redirect-blocked.sub.html new file mode 100644 index 000000000000..74b77c95d564 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/child-src/child-src-redirect-blocked.sub.html @@ -0,0 +1,61 @@ + + + + + + child-src-blocked + + + + + +

+ IFrames blocked by CSP should generate a 'load', not 'error' event, regardless of blocked state. This means they appear to be normal cross-origin loads, thereby not leaking URL information directly to JS. +

+ + + + + +
+ + + + diff --git a/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-allowed.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/child-src/child-src-redirect-blocked.sub.html.sub.headers similarity index 77% rename from testing/web-platform/tests/content-security-policy/child-src/child-src-worker-allowed.sub.html.sub.headers rename to testing/web-platform/tests/content-security-policy/child-src/child-src-redirect-blocked.sub.html.sub.headers index 4ddb39e84b24..60dac9bc498d 100644 --- a/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-allowed.sub.html.sub.headers +++ b/testing/web-platform/tests/content-security-policy/child-src/child-src-redirect-blocked.sub.html.sub.headers @@ -2,5 +2,5 @@ Expires: Mon, 26 Jul 1997 05:00:00 GMT Cache-Control: no-store, no-cache, must-revalidate Cache-Control: post-check=0, pre-check=0, false Pragma: no-cache -Set-Cookie: child-src-worker-allowed={{$id:uuid()}}; Path=/content-security-policy/child-src +Set-Cookie: child-src-redirect-blocked={{$id:uuid()}}; Path=/content-security-policy/child-src Content-Security-Policy: child-src 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self'; report-uri /content-security-policy/support/report.py?op=put&reportID={{$id}} diff --git a/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-allowed.sub.html b/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-allowed.sub.html index 361d0974287f..d02abaef1934 100644 --- a/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-allowed.sub.html +++ b/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-allowed.sub.html @@ -5,28 +5,34 @@ child-src-worker-allowed - - - - + +

This test used to check the child-src csp controlling worker creation. This behaviour has been deprecated but it's still supported + until the transition is done. This still tests that behaviour but we need to go through extra hoops to make sure 'script-src' + does not affect the result in any way (for instance by allowing 'self'). +

- diff --git a/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-blocked.sub.html b/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-blocked.sub.html index 8ed6b157a814..675cd95ea4f9 100644 --- a/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-blocked.sub.html +++ b/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-blocked.sub.html @@ -5,31 +5,40 @@ child-src-worker-blocked - - - - + +

This test used to check the child-src csp controlling worker creation. This behaviour has been deprecated but it's still supported + until the transition is done. This still tests that behaviour but we need to go through extra hoops to make sure 'script-src' + does not affect the result in any way (for instance by allowing 'self'). +

- diff --git a/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-blocked.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-blocked.sub.html.sub.headers deleted file mode 100644 index 685d6dcf5ea3..000000000000 --- a/testing/web-platform/tests/content-security-policy/child-src/child-src-worker-blocked.sub.html.sub.headers +++ /dev/null @@ -1,6 +0,0 @@ -Expires: Mon, 26 Jul 1997 05:00:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Cache-Control: post-check=0, pre-check=0, false -Pragma: no-cache -Set-Cookie: child-src-worker-blocked={{$id:uuid()}}; Path=/content-security-policy/child-src -Content-Security-Policy: child-src 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self'; report-uri /content-security-policy/support/report.py?op=put&reportID={{$id}} diff --git a/testing/web-platform/tests/content-security-policy/embedded-enforcement/embedding_csp-header-invalid-format.html b/testing/web-platform/tests/content-security-policy/embedded-enforcement/embedding_csp-header-invalid-format.html new file mode 100644 index 000000000000..98bdbd29a6e2 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/embedded-enforcement/embedding_csp-header-invalid-format.html @@ -0,0 +1,70 @@ + + + +Embedded Enforcement: Embedding-CSP header. + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/embedded-enforcement/embedding_csp-header.html b/testing/web-platform/tests/content-security-policy/embedded-enforcement/embedding_csp-header.html index 424233a3ad82..2d526e329793 100644 --- a/testing/web-platform/tests/content-security-policy/embedded-enforcement/embedding_csp-header.html +++ b/testing/web-platform/tests/content-security-policy/embedded-enforcement/embedding_csp-header.html @@ -18,9 +18,6 @@ { "name": "Send Embedding-CSP Header on change of `src` attribute on iframe.", "csp": "script-src 'unsafe-inline'", "expected": "script-src 'unsafe-inline'" }, - { "name": "Wrong value of `csp` should not trigger sending Embedding-CSP Header.", - "csp": "completely wrong csp", - "expected": null}, ]; tests.forEach(test => { diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/deep-allows-none.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/deep-allows-none.sub.html deleted file mode 100644 index 1926007d34ca..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/deep-allows-none.sub.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - single-frame-self-allowed - - - - - - - - - -
- - diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-none-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-none-block.html new file mode 100644 index 000000000000..674deb655a75 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-none-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block.html new file mode 100644 index 000000000000..85b7f0efdc82 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-star-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-star-allow.html new file mode 100644 index 000000000000..7f5a867de94b --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-star-allow.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-allow.html new file mode 100644 index 000000000000..99ab0718e8db --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-allow.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-block.html new file mode 100644 index 000000000000..9bcf63735e75 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-none-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-none-block.html new file mode 100644 index 000000000000..1cdd540149f4 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-none-block.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-self-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-self-block.html new file mode 100644 index 000000000000..da9733971141 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-self-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-star-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-star-allow.html new file mode 100644 index 000000000000..c523b9ef10a7 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-star-allow.html @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow.html new file mode 100644 index 000000000000..1f1ffb9f894b --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow.html @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-block.html new file mode 100644 index 000000000000..62dd1c1ef665 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-sandboxed-cross-url-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-sandboxed-cross-url-block.html new file mode 100644 index 000000000000..654e90e0b82d --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-sandboxed-cross-url-block.html @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-none-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-none-block.html new file mode 100644 index 000000000000..f01c6d766fc1 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-none-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-self-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-self-block.html new file mode 100644 index 000000000000..bae5992e8609 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-self-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-star-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-star-allow.html new file mode 100644 index 000000000000..85d66f660ab8 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-star-allow.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-allow.html new file mode 100644 index 000000000000..dff041be9a39 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-allow.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block.html new file mode 100644 index 000000000000..5d2fc57ac14e --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-none-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-none-block.html new file mode 100644 index 000000000000..234cca82c8ce --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-none-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-self-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-self-allow.html new file mode 100644 index 000000000000..747c5636967e --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-self-allow.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-star-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-star-allow.html new file mode 100644 index 000000000000..d7eaf73fd6cc --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-star-allow.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-allow.html new file mode 100644 index 000000000000..432c25f0d2a6 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-allow.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-block.html new file mode 100644 index 000000000000..c02091bf4ff7 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-none-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-none-block.html new file mode 100644 index 000000000000..596d3e7bc300 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-none-block.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-overrides-xfo.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-overrides-xfo.html new file mode 100644 index 000000000000..83654660331f --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-overrides-xfo.html @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-self-allow.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-self-allow.html new file mode 100644 index 000000000000..a8a295dfc40c --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-self-allow.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-self-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-self-block.html new file mode 100644 index 000000000000..438f2b8eb218 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-self-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-star-allow-crossorigin.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-star-allow-crossorigin.html new file mode 100644 index 000000000000..09ee28bbeaf4 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-star-allow-crossorigin.html @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-star-allow-sameorigin.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-star-allow-sameorigin.html new file mode 100644 index 000000000000..62bbe45b2580 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-star-allow-sameorigin.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-url-allow.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-url-allow.sub.html new file mode 100644 index 000000000000..f4f42e475f88 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-url-allow.sub.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-url-block.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-url-block.html new file mode 100644 index 000000000000..c320370be515 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/frame-ancestors-url-block.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html deleted file mode 100644 index 6b9c91c9356d..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html +++ /dev/null @@ -1,21 +0,0 @@ - - - -

Reporting Frame...

- - - - \ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html.headers b/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html.headers deleted file mode 100644 index f0eb936b362d..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-self.sub.html.headers +++ /dev/null @@ -1,5 +0,0 @@ -Expires: Mon, 26 Jul 1997 05:00:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Cache-Control: post-check=0, pre-check=0, false -Pragma: no-cache -Content-Security-Policy: frame-ancestors 'self' diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html deleted file mode 100644 index d51e0d5329db..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html +++ /dev/null @@ -1,20 +0,0 @@ - - - -

Reporting Frame...

- - - - \ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html.headers b/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html.headers deleted file mode 100644 index 734aa227ffea..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/intermediate-reporting-frame-allows-star.sub.html.headers +++ /dev/null @@ -1,5 +0,0 @@ -Expires: Mon, 26 Jul 1997 05:00:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Cache-Control: post-check=0, pre-check=0, false -Pragma: no-cache -Content-Security-Policy: frame-ancestors * diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/multiple-frames-meta-ignored.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/multiple-frames-meta-ignored.sub.html deleted file mode 100644 index 47bb0244b4b9..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/multiple-frames-meta-ignored.sub.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - multiple-frames-self-allowed - - - - - - - - - - -
- - diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/multiple-frames-one-blocked.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/multiple-frames-one-blocked.sub.html deleted file mode 100644 index 3857a173cc2e..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/multiple-frames-one-blocked.sub.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - multiple-frames-self-allowed - - - - - - - - - - -
- - diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/multiple-frames-self-allowed.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/multiple-frames-self-allowed.sub.html deleted file mode 100644 index 485b6eb0f172..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/multiple-frames-self-allowed.sub.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - multiple-frames-self-allowed - - - - - - - - - - -
- - diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/nested-traversing-allowed.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/nested-traversing-allowed.sub.html deleted file mode 100644 index a49049d13675..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/nested-traversing-allowed.sub.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - single-frame-self-allowed - - - - - - - - - -
- - diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/nested-traversing-banned-top-is-self.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/nested-traversing-banned-top-is-self.sub.html deleted file mode 100644 index ced262fd7024..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/nested-traversing-banned-top-is-self.sub.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - single-frame-self-allowed - - - - - - - - - -
- - diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/nested-traversing-banned.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/nested-traversing-banned.sub.html deleted file mode 100644 index e58f0ba8d2b7..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/nested-traversing-banned.sub.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - single-frame-self-allowed - - - - - - - - - -
- - diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-none-meta.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-none-meta.html deleted file mode 100644 index c0d079f01c4b..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-none-meta.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - -

Reporting Frame...

- - - \ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-none.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-none.html deleted file mode 100644 index e38d99a6c19c..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-none.html +++ /dev/null @@ -1,22 +0,0 @@ - - - -

Reporting Frame...

- - - \ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-none.html.headers b/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-none.html.headers deleted file mode 100644 index 18bfb8156f32..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-none.html.headers +++ /dev/null @@ -1,5 +0,0 @@ -Expires: Mon, 26 Jul 1997 05:00:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Cache-Control: post-check=0, pre-check=0, false -Pragma: no-cache -Content-Security-Policy: frame-ancestors 'none' diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-self.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-self.html deleted file mode 100644 index 7c1186e77a42..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-self.html +++ /dev/null @@ -1,22 +0,0 @@ - - - -

Reporting Frame...

- - - \ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-self.html.headers b/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-self.html.headers deleted file mode 100644 index f0eb936b362d..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/reporting-frame-allows-self.html.headers +++ /dev/null @@ -1,5 +0,0 @@ -Expires: Mon, 26 Jul 1997 05:00:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Cache-Control: post-check=0, pre-check=0, false -Pragma: no-cache -Content-Security-Policy: frame-ancestors 'self' diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/single-frame-self-allowed.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/single-frame-self-allowed.sub.html deleted file mode 100644 index 3a9b4552e080..000000000000 --- a/testing/web-platform/tests/content-security-policy/frame-ancestors/single-frame-self-allowed.sub.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - single-frame-self-allowed - - - - - - - - - -
- - diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html new file mode 100644 index 000000000000..e22fea3ccd36 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html @@ -0,0 +1,9 @@ + + + +

This is an IFrame sending a Content Security Policy header containing "frame-ancestors {{GET[policy]}}" and "X-Frame-Options: {{GET[xfo]}}".

+ + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html.sub.headers new file mode 100644 index 000000000000..636e0facde59 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors-and-x-frame-options.sub.html.sub.headers @@ -0,0 +1,3 @@ +Content-Type: text/html; charset=UTF-8 +Content-Security-Policy: frame-ancestors {{GET[policy]}} +X-Frame-Options: {{GET[xfo]}} diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors-test.sub.js b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors-test.sub.js new file mode 100644 index 000000000000..dde04f0627e1 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors-test.sub.js @@ -0,0 +1,134 @@ +var SAME_ORIGIN = true; +var CROSS_ORIGIN = false; + +var EXPECT_BLOCK = true; +var EXPECT_LOAD = false; + +var SAMEORIGIN_ORIGIN = "{{location[scheme]}}://{{location[host]}}"; +var CROSSORIGIN_ORIGIN = "http://{{domains[www1]}}:{{ports[http][1]}}"; + +var test; + +function endTest(failed, message) { + if (typeof test === 'undefined') return; + + if (failed) { + test.step(function() { + assert_unreached(message); + test.done(); + }); + } + else test.done({message: message}); +} + +window.addEventListener("message", function (e) { + if (window.parent != window) + window.parent.postMessage(e.data, "*"); + else + if (e.data.type === 'test_result') + endTest(e.data.failed, "Inner IFrame msg: " + e.data.msg); +}); + +function injectNestedIframe(policy, parent, child, expectation, isSandboxed) { + var iframe = document.createElement("iframe"); + + var url = "/content-security-policy/frame-ancestors/support/frame-in-frame.sub.html" + + "?policy=" + policy + + "&parent=" + parent + + "&child=" + child + + "&expectation=" + expectation; + url = (parent == "same" ? SAMEORIGIN_ORIGIN : CROSSORIGIN_ORIGIN) + url; + + iframe.src = url; + + if (isSandboxed) + iframe.sandbox = 'allow-scripts'; + + document.body.appendChild(iframe); +} + +function injectIFrame(policy, sameOrigin, expectBlock) { + var iframe = document.createElement("iframe"); + iframe.addEventListener("load", iframeLoaded(expectBlock)); + iframe.addEventListener("error", iframeLoaded(expectBlock)); + + var url = "/content-security-policy/frame-ancestors/support/frame-ancestors.sub.html?policy=" + policy; + if (sameOrigin) + url = SAMEORIGIN_ORIGIN + url; + else + url = CROSSORIGIN_ORIGIN + url; + + iframe.src = url; + document.body.appendChild(iframe); +} + +function iframeLoaded(expectBlock) { + return function(ev) { + var failed = true; + var message = ""; + try { + if (expectBlock) { + message = "The IFrame should have been blocked (or cross-origin). It wasn't."; + failed = true; + } else { + message = "The IFrame should not have been blocked. It wasn't."; + failed = false; + } + } catch (ex) { + if (expectBlock) { + message = "The IFrame should have been blocked (or cross-origin). It was."; + failed = false; + } else { + message = "The IFrame should not have been blocked. It was."; + failed = true; + } + } + if (window.parent != window) + window.parent.postMessage({type: 'test_result', failed: failed, message: message}, '*'); + else + endTest(failed, message); + }; +} + +function originFrameShouldBe(child, expectation, policy) { + if (child == "cross" && expectation == "blocked") crossOriginFrameShouldBeBlocked(policy); + if (child == "same" && expectation == "blocked") sameOriginFrameShouldBeBlocked(policy); + if (child == "cross" && expectation == "allowed") crossOriginFrameShouldBeAllowed(policy); + if (child == "same" && expectation == "allowed") sameOriginFrameShouldBeAllowed(policy); +} + +function crossOriginFrameShouldBeBlocked(policy) { + window.onload = function () { + injectIFrame(policy, CROSS_ORIGIN, EXPECT_BLOCK); + }; +} + +function crossOriginFrameShouldBeAllowed(policy) { + window.onload = function () { + injectIFrame(policy, CROSS_ORIGIN, EXPECT_LOAD); + }; +} + +function sameOriginFrameShouldBeBlocked(policy) { + window.onload = function () { + injectIFrame(policy, SAME_ORIGIN, EXPECT_BLOCK); + }; +} + +function sameOriginFrameShouldBeAllowed(policy) { + window.onload = function () { + injectIFrame(policy, SAME_ORIGIN, EXPECT_LOAD); + }; +} + +function testNestedIFrame(policy, parent, child, expectation) { + window.onload = function () { + injectNestedIframe(policy, parent == SAME_ORIGIN ? "same" : "cross", child == SAME_ORIGIN ? "same" : "cross", expectation == EXPECT_LOAD ? "allowed" : "blocked", false /* isSandboxed */); + }; +} + +function testNestedSandboxedIFrame(policy, parent, child, expectation) { + window.onload = function () { + injectNestedIframe(policy, parent == SAME_ORIGIN ? "same" : "cross", child == SAME_ORIGIN ? "same" : "cross", expectation == EXPECT_LOAD ? "allowed" : "blocked", true /* isSandboxed */); + }; +} diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors.sub.html new file mode 100644 index 000000000000..de652773437f --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors.sub.html @@ -0,0 +1,9 @@ + + + +

This is an IFrame sending a Content Security Policy header containing "frame-ancestors {{GET[policy]}}".

+ + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors.sub.html.sub.headers new file mode 100644 index 000000000000..9369a4101fa1 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-ancestors.sub.html.sub.headers @@ -0,0 +1,2 @@ +Content-Type: text/html; charset=UTF-8 +Content-Security-Policy: frame-ancestors {{GET[policy]}} diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-in-frame.sub.html b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-in-frame.sub.html new file mode 100644 index 000000000000..5a60eb7f347c --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-in-frame.sub.html @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-in-frame.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-in-frame.sub.html.sub.headers new file mode 100644 index 000000000000..e853d6cee5e0 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-ancestors/support/frame-in-frame.sub.html.sub.headers @@ -0,0 +1 @@ +Content-Type: text/html; charset=UTF-8 diff --git a/testing/web-platform/tests/content-security-policy/frame-src/frame-src-redirect.html b/testing/web-platform/tests/content-security-policy/frame-src/frame-src-redirect.html new file mode 100644 index 000000000000..f5ac88b05242 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-src/frame-src-redirect.html @@ -0,0 +1,35 @@ + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/frame-src/frame-src-redirect.html.headers b/testing/web-platform/tests/content-security-policy/frame-src/frame-src-redirect.html.headers new file mode 100644 index 000000000000..338bea13b84a --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-src/frame-src-redirect.html.headers @@ -0,0 +1,2 @@ +Content-Security-Policy: frame-src 'self' +Content-Security-Policy-Report-Only: frame-src http://foo.test diff --git a/testing/web-platform/tests/content-security-policy/frame-src/support/frame.html b/testing/web-platform/tests/content-security-policy/frame-src/support/frame.html new file mode 100644 index 000000000000..50be42958744 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-src/support/frame.html @@ -0,0 +1,2 @@ + + diff --git a/testing/web-platform/tests/content-security-policy/frame-src/support/testharness-helper.sub.js b/testing/web-platform/tests/content-security-policy/frame-src/support/testharness-helper.sub.js new file mode 100644 index 000000000000..b9e9a6c856bf --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/frame-src/support/testharness-helper.sub.js @@ -0,0 +1,5 @@ +function generateCrossOriginRedirectFrame() { + var target = "http://{{domains[天気の良い日]}}:" + document.location.port + "/content-security-policy/frame-src/support/frame.html"; + var url = "/common/redirect.py?location=" + encodeURIComponent(target); + return { url: url, target: target }; +} diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_1-img-src.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_1-img-src.html index c3778f81604d..0c1021589856 100644 --- a/testing/web-platform/tests/content-security-policy/generic/generic-0_1-img-src.html +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_1-img-src.html @@ -29,7 +29,7 @@ } - + diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_1-script-src.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_1-script-src.html index 740b2a553477..e4f0d1d5054f 100644 --- a/testing/web-platform/tests/content-security-policy/generic/generic-0_1-script-src.html +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_1-script-src.html @@ -29,7 +29,7 @@ } - + diff --git a/testing/web-platform/tests/content-security-policy/script-src/crossoriginScript.js b/testing/web-platform/tests/content-security-policy/script-src/crossoriginScript.js new file mode 100644 index 000000000000..08535fa552ea --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/script-src/crossoriginScript.js @@ -0,0 +1,3 @@ +// Identical to simpleSourcedScript.js but with a different hash, thanks to +// this comment! +window.postMessage(document.currentScript.id, "*"); diff --git a/testing/web-platform/tests/content-security-policy/script-src/crossoriginScript.js.headers b/testing/web-platform/tests/content-security-policy/script-src/crossoriginScript.js.headers new file mode 100644 index 000000000000..cb762eff8068 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/script-src/crossoriginScript.js.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/testing/web-platform/tests/content-security-policy/script-src/externalScript.js b/testing/web-platform/tests/content-security-policy/script-src/externalScript.js new file mode 100644 index 000000000000..2920b03c9bc9 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/script-src/externalScript.js @@ -0,0 +1 @@ +externalRan = true; \ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html b/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html new file mode 100644 index 000000000000..2c888f46d991 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html @@ -0,0 +1,104 @@ + + + + + External scripts with matching SRI hash should be allowed. + + + + + + + +

External scripts with matching SRI hash should be allowed.

+
+ + + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html.sub.headers new file mode 100644 index 000000000000..25cd6541acac --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html.sub.headers @@ -0,0 +1,5 @@ +Expires: Mon, 26 Jul 1997 05:00:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Cache-Control: post-check=0, pre-check=0, false +Pragma: no-cache +Content-Security-Policy: script-src {{domains[www]}}:* 'nonce-dummy' 'sha256-wIc3KtqOuTFEu6t17sIBuOswgkV406VJvhSk79Gw6U0=' 'sha256-L7/UQ9VWpyG7C9RDEC4ctS5hI3Zcw+ta+haPGlByG9c=' 'sha512-rYCVMxWV5nq8IsMo+UZNObWtEiWGok/vDN8BMoEQi41s0znSes6E1Q2aag3Lw3u2J1w2rqH7uF2ws6FpQhfSOA=' diff --git a/testing/web-platform/tests/content-security-policy/script-src/script-src-strict_dynamic_worker.https.html b/testing/web-platform/tests/content-security-policy/script-src/script-src-strict_dynamic_worker.https.html new file mode 100644 index 000000000000..213eb6276d85 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/script-src/script-src-strict_dynamic_worker.https.html @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html new file mode 100644 index 000000000000..27611273babc --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html @@ -0,0 +1,31 @@ + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html.headers b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html.headers new file mode 100644 index 000000000000..57207bbd23cf --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html.headers @@ -0,0 +1,2 @@ +Content-Security-Policy-Report-Only: img-src https: +Content-Security-Policy: upgrade-insecure-requests diff --git a/testing/web-platform/tests/content-security-policy/securitypolicyviolation/support/testharness-helper.sub.js b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/support/testharness-helper.sub.js new file mode 100644 index 000000000000..816b88fc6e47 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/support/testharness-helper.sub.js @@ -0,0 +1,5 @@ +function generateCrossOriginRedirectImage() { + var target = "http://{{host}}:{{ports[https][0]}}/content-security-policy/support/pass.png"; + var url = "/common/redirect.py?location=" + encodeURIComponent(target); + return { url: url, target: target } +} \ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html new file mode 100644 index 000000000000..5a0bc7c8e7aa --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html @@ -0,0 +1,60 @@ + + + + + + + diff --git a/testing/web-platform/tests/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html.headers b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html.headers new file mode 100644 index 000000000000..b8bec0b95e39 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html.headers @@ -0,0 +1,2 @@ +Content-Security-Policy-Report-Only: frame-src https:; img-src https: +Content-Security-Policy: upgrade-insecure-requests diff --git a/testing/web-platform/tests/content-security-policy/support/post-message.js b/testing/web-platform/tests/content-security-policy/support/post-message.js new file mode 100644 index 000000000000..69daa31d2f1b --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/support/post-message.js @@ -0,0 +1 @@ +postMessage("importScripts allowed"); diff --git a/testing/web-platform/tests/content-security-policy/support/postmessage-fail.html b/testing/web-platform/tests/content-security-policy/support/postmessage-fail.html new file mode 100644 index 000000000000..a0308ad98b4c --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/support/postmessage-fail.html @@ -0,0 +1,4 @@ + diff --git a/testing/web-platform/tests/content-security-policy/support/postmessage-pass.html b/testing/web-platform/tests/content-security-policy/support/postmessage-pass.html new file mode 100644 index 000000000000..700167b5db84 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/support/postmessage-pass.html @@ -0,0 +1,4 @@ + diff --git a/testing/web-platform/tests/content-security-policy/svg/object-in-svg-foreignobject.sub.html b/testing/web-platform/tests/content-security-policy/svg/object-in-svg-foreignobject.sub.html new file mode 100644 index 000000000000..aa4f15695307 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/svg/object-in-svg-foreignobject.sub.html @@ -0,0 +1,27 @@ + + + + Object inside SVG foreignobject respect csp + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/cors/allow-headers.htm b/testing/web-platform/tests/cors/allow-headers.htm index 08e00a5270f7..8f25f3e4351b 100644 --- a/testing/web-platform/tests/cors/allow-headers.htm +++ b/testing/web-platform/tests/cors/allow-headers.htm @@ -44,7 +44,7 @@ function shouldFail(origin) { + '/resources/cors-makeheader.py?origin=' + encodeURIComponent(origin), false) - assert_throws(null, function() { client.send() }, 'send') + assert_throws("NetworkError", function() { client.send() }, 'send') }, 'Disallow origin: ' + origin.replace('\0', '\\0')); } diff --git a/testing/web-platform/tests/cors/origin.htm b/testing/web-platform/tests/cors/origin.htm index a3bb6c56542b..a04a29eb497f 100644 --- a/testing/web-platform/tests/cors/origin.htm +++ b/testing/web-platform/tests/cors/origin.htm @@ -47,7 +47,7 @@ function shouldFail(origin) { + '/resources/cors-makeheader.py?origin=' + encodeURIComponent(origin), false) - assert_throws(null, function() { client.send() }, 'send') + assert_throws("NetworkError", function() { client.send() }, 'send') }, 'Disallow origin: ' + origin.replace(/\0/g, "\\0")); } @@ -105,7 +105,7 @@ function doubleOrigin(origin, origin2) { + encodeURIComponent(origin) + '&origin2=' + encodeURIComponent(origin2), false) - assert_throws(null, function() { client.send() }, 'send') + assert_throws("NetworkError", function() { client.send() }, 'send') }, 'Disallow multiple headers (' + origin + ', ' + origin2 + ')'); } diff --git a/testing/web-platform/tests/cors/request-headers.htm b/testing/web-platform/tests/cors/request-headers.htm index 8adaeb4f8bd9..289f402191eb 100644 --- a/testing/web-platform/tests/cors/request-headers.htm +++ b/testing/web-platform/tests/cors/request-headers.htm @@ -48,7 +48,7 @@ test(function() { client.open('GET', CROSSDOMAIN + 'resources/cors-makeheader.py?headers=x-print', false) client.setRequestHeader('x-print', 'unicorn') client.setRequestHeader('y-print', 'unicorn') - assert_throws(null, function() { client.send(null) }) + assert_throws("NetworkError", function() { client.send(null) }) }, 'Unspecified request headers are disallowed') test(function() { diff --git a/testing/web-platform/tests/credential-management/idl.https.html b/testing/web-platform/tests/credential-management/idl.https.html new file mode 100644 index 000000000000..bc779d069e90 --- /dev/null +++ b/testing/web-platform/tests/credential-management/idl.https.html @@ -0,0 +1,93 @@ + + + + + + + + + diff --git a/testing/web-platform/tests/css-font-loading/fontfacesetloadevent-constructor.html b/testing/web-platform/tests/css-font-loading/fontfacesetloadevent-constructor.html new file mode 100644 index 000000000000..d5038ce690c6 --- /dev/null +++ b/testing/web-platform/tests/css-font-loading/fontfacesetloadevent-constructor.html @@ -0,0 +1,20 @@ + +FontFaceSetLoadEvent constructor + + + + diff --git a/testing/web-platform/tests/css-paint-api/OWNERS b/testing/web-platform/tests/css-paint-api/OWNERS new file mode 100644 index 000000000000..bd72a2a78f75 --- /dev/null +++ b/testing/web-platform/tests/css-paint-api/OWNERS @@ -0,0 +1,3 @@ +@bfgeek +@grorg +@shans diff --git a/testing/web-platform/tests/cssom-view/CaretPosition-001.html b/testing/web-platform/tests/cssom-view/CaretPosition-001.html new file mode 100644 index 000000000000..d8e97a92342c --- /dev/null +++ b/testing/web-platform/tests/cssom-view/CaretPosition-001.html @@ -0,0 +1,44 @@ + + + +CSSOM View Module test:CaretPosition + + + + + + + +
+
+
+
+
+
+
+
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/MediaQueryList-001.html b/testing/web-platform/tests/cssom-view/MediaQueryList-001.html new file mode 100644 index 000000000000..06c81d5de4c6 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/MediaQueryList-001.html @@ -0,0 +1,21 @@ + + + + CSSOM View Module test:MediaQueryList + + + + + + + +

This case tests the MediaQueryList

+
+ + + diff --git a/testing/web-platform/tests/cssom-view/OWNERS b/testing/web-platform/tests/cssom-view/OWNERS index cd9ff2eee4bb..678152d6503c 100644 --- a/testing/web-platform/tests/cssom-view/OWNERS +++ b/testing/web-platform/tests/cssom-view/OWNERS @@ -1 +1,3 @@ @AutomatedTester +@plinss +@zcorpan diff --git a/testing/web-platform/tests/cssom-view/Screen-pixelDepth-Screen-colorDepth001.html b/testing/web-platform/tests/cssom-view/Screen-pixelDepth-Screen-colorDepth001.html new file mode 100644 index 000000000000..2a8d5b5b4928 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/Screen-pixelDepth-Screen-colorDepth001.html @@ -0,0 +1,33 @@ + + + + CSSOM View Module test:Screen-pixelDepth,Screen-colorDepth + + + + + + + +

This case tests the Screen pixelDepth and colorDepth

+

The test passes if the value is 24

+
+ + + diff --git a/testing/web-platform/tests/cssom-view/cssom-getBoundingClientRect-001.html b/testing/web-platform/tests/cssom-view/cssom-getBoundingClientRect-001.html new file mode 100644 index 000000000000..7d96540adfe9 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/cssom-getBoundingClientRect-001.html @@ -0,0 +1,41 @@ + + + + CSSOM View - 6.1 - getBoundingClientRect tests + + + + + + + + + +
test item
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/cssom-getBoundingClientRect-002.html b/testing/web-platform/tests/cssom-view/cssom-getBoundingClientRect-002.html new file mode 100644 index 000000000000..a7c3568969a7 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/cssom-getBoundingClientRect-002.html @@ -0,0 +1,27 @@ + + + + + CSS Test (CSSOM View): getBoundingClientRect of element outside DOM + + + + + + + + + + + diff --git a/testing/web-platform/tests/cssom-view/cssom-getClientRects.html b/testing/web-platform/tests/cssom-view/cssom-getClientRects.html new file mode 100644 index 000000000000..36559eb116a6 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/cssom-getClientRects.html @@ -0,0 +1,23 @@ + + + + + CSS Test (CSSOM View): getClientRects of element outside DOM + + + + + + + + + + diff --git a/testing/web-platform/tests/cssom-view/cssom-view-img-attributes-001.html b/testing/web-platform/tests/cssom-view/cssom-view-img-attributes-001.html new file mode 100644 index 000000000000..2f4228810415 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/cssom-view-img-attributes-001.html @@ -0,0 +1,46 @@ + + + + CSS Test: HTMLImageElement x and y attributes + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom-view/cssom-view-window-screen-interface.html b/testing/web-platform/tests/cssom-view/cssom-view-window-screen-interface.html new file mode 100644 index 000000000000..0d5e9bcaa549 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/cssom-view-window-screen-interface.html @@ -0,0 +1,40 @@ + + + + CSS Test: cssom view window screen attribute + + + + + + + + +
+
+ + + + diff --git a/testing/web-platform/tests/cssom-view/cssom-view/media-query-list-interface.xht b/testing/web-platform/tests/cssom-view/cssom-view/media-query-list-interface.xht new file mode 100644 index 000000000000..98bdaae6ec40 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/cssom-view/media-query-list-interface.xht @@ -0,0 +1,70 @@ + + + + + CSSOM MediaQueryList Test: Properties and Functions + + + + + + + + diff --git a/testing/web-platform/tests/cssom-view/cssom-view/window-interface.xht b/testing/web-platform/tests/cssom-view/cssom-view/window-interface.xht new file mode 100644 index 000000000000..2ed64cba6e6c --- /dev/null +++ b/testing/web-platform/tests/cssom-view/cssom-view/window-interface.xht @@ -0,0 +1,98 @@ + + + + + CSSOM Window Test: Properties and Functions + + + + + + + + diff --git a/testing/web-platform/tests/cssom-view/elementFromPoint-001.html b/testing/web-platform/tests/cssom-view/elementFromPoint-001.html new file mode 100644 index 000000000000..c2fcc42c530c --- /dev/null +++ b/testing/web-platform/tests/cssom-view/elementFromPoint-001.html @@ -0,0 +1,34 @@ + + + + CSSOM View - 5 - extensions to the Document interface + + + + + + + + + +
+
+
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/elementFromPosition.html b/testing/web-platform/tests/cssom-view/elementFromPosition.html new file mode 100644 index 000000000000..b781bb3713ed --- /dev/null +++ b/testing/web-platform/tests/cssom-view/elementFromPosition.html @@ -0,0 +1,143 @@ + + + + CSS Test: CSSOM View elementFromPoint + + + + + + + + + + +
+ + + + + diff --git a/testing/web-platform/tests/cssom-view/elementScroll.html b/testing/web-platform/tests/cssom-view/elementScroll.html index 6227d6654575..a5df48109eb5 100644 --- a/testing/web-platform/tests/cssom-view/elementScroll.html +++ b/testing/web-platform/tests/cssom-view/elementScroll.html @@ -4,35 +4,27 @@
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ultricies tortor eu augue eleifend malesuada. Duis id condimentum urna. Duis vulputate urna a dignissim sodales. Aenean et magna id dui rutrum suscipit. Etiam metus mauris, congue ac suscipit dapibus, mattis non neque. Donec porttitor eros sed mauris tristique, non condimentum augue feugiat. Suspendisse iaculis faucibus nunc at porttitor. Integer convallis enim in feugiat molestie. Ut eget tincidunt mi, vel malesuada lectus. Quisque fermentum neque a sapien interdum consectetur. Nam tincidunt leo sit amet tortor ornare, sit amet ultrices ante semper. Fusce malesuada mi vitae venenatis sagittis. Duis eget urna quam. - - Sed lacinia aliquam tortor quis elementum. Cras vitae mauris erat. Vestibulum posuere justo et dolor condimentum feugiat. Sed at magna nunc. Suspendisse est nunc, ultrices sed enim lobortis, vulputate rutrum mauris. Fusce ultrices eget erat blandit porta. Sed eros nulla, tristique eget porta a, viverra vel velit. Praesent sit amet odio eleifend, tempor arcu ut, elementum tellus. Suspendisse lorem tortor, sodales eget nulla a, rhoncus lobortis magna. Phasellus purus ante, rhoncus a ipsum nec, condimentum lacinia purus. Cras lobortis posuere nisi, vitae dapibus ante feugiat et. Quisque ornare nisi quis erat congue viverra. Vestibulum a nunc odio. - - Sed id venenatis tortor. Curabitur sit amet mauris eget mi semper rutrum vel et odio. Phasellus eu sapien in sem ultricies pretium eu sit amet magna. Nulla finibus nec lorem ac semper. Nulla eleifend eros id fringilla pellentesque. Proin eleifend, sem vel lobortis viverra, massa augue viverra felis, quis ultricies sapien ipsum at magna. Duis rutrum tempus lobortis. Aliquam quis nulla eget velit viverra pretium. Maecenas venenatis nec nisl at pulvinar. Duis in sodales lectus, ac porta augue. - - Sed sed ante aliquam, rutrum nisl quis, fermentum tellus. Proin ac leo molestie, euismod mauris sed, consequat nunc. Vivamus ut leo a nunc pharetra accumsan a non lorem. Aliquam iaculis mattis augue, in eleifend est accumsan vel. Pellentesque efficitur pulvinar leo vel ornare. Pellentesque non fermentum enim, ut efficitur elit. Duis risus quam, congue vel nulla a, blandit egestas erat. Suspendisse at sodales dolor. Vivamus auctor, lorem et ultrices venenatis, erat ex mollis nisi, quis maximus libero quam a libero. - - Curabitur elit lacus, bibendum non tempus a, bibendum sit amet ante. Mauris eget nibh quis leo rhoncus consequat. Integer iaculis sed sapien eu pellentesque. In aliquet elementum lorem, ut consequat elit ultrices id. Phasellus vestibulum ex ex, ac sagittis tortor convallis et. Curabitur placerat id lectus at aliquam. Morbi sed nisl sem. Nam sit amet arcu maximus, volutpat nisl ac, dignissim neque. Etiam nec efficitur libero. Quisque tristique pulvinar est, eget dictum ex vehicula non. Nam dignissim non felis a iaculis. Nullam vel dolor vitae libero aliquet congue. Donec mi eros, semper non lectus at, commodo ullamcorper ligula. Donec commodo, sem vel lacinia porttitor, elit orci maximus felis, eget eleifend est velit id lorem. -
+
+ + + +
...
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/matchMedia.xht b/testing/web-platform/tests/cssom-view/matchMedia.xht new file mode 100644 index 000000000000..7ac875c6aa96 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/matchMedia.xht @@ -0,0 +1,187 @@ + + + + + CSS Test: CSSOM View matchMedia and MediaQueryList + + + + + + + + diff --git a/testing/web-platform/tests/cssom-view/matchMediaAddListener.html b/testing/web-platform/tests/cssom-view/matchMediaAddListener.html new file mode 100644 index 000000000000..7236be7febc9 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/matchMediaAddListener.html @@ -0,0 +1,65 @@ + + + + CSS Test: CSSOM View matchMedia addListener + + + + + + + + +
+ + + + diff --git a/testing/web-platform/tests/cssom-view/offsetParent_element_test.html b/testing/web-platform/tests/cssom-view/offsetParent_element_test.html new file mode 100644 index 000000000000..473120f4b9be --- /dev/null +++ b/testing/web-platform/tests/cssom-view/offsetParent_element_test.html @@ -0,0 +1,138 @@ + + + + +CSSOM View —— offsetParent element test + + + + + + + + + + + +
+ +
+
+
+ +
+
+
+ + + + + + + + + +
+
+
+ +
+ +
+ +

+ + + + +
+ +
+
+ +
+ + + + diff --git a/testing/web-platform/tests/cssom-view/scrollWidthHeight.xht b/testing/web-platform/tests/cssom-view/scrollWidthHeight.xht new file mode 100644 index 000000000000..b4696e136305 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/scrollWidthHeight.xht @@ -0,0 +1,147 @@ + + + + + CSS Test: CSSOM View scrollWidth and scrollHeight + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/scrollWidthHeightWhenNotScrollable.xht b/testing/web-platform/tests/cssom-view/scrollWidthHeightWhenNotScrollable.xht new file mode 100644 index 000000000000..e8c7f1298bc4 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/scrollWidthHeightWhenNotScrollable.xht @@ -0,0 +1,137 @@ + + + + + CSS Test: CSSOM View scrollWidth/scrollHeight (for nonscrollable elements) + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/scrolling-quirks-vs-nonquirks.html b/testing/web-platform/tests/cssom-view/scrolling-quirks-vs-nonquirks.html new file mode 100644 index 000000000000..568f572ac22c --- /dev/null +++ b/testing/web-platform/tests/cssom-view/scrolling-quirks-vs-nonquirks.html @@ -0,0 +1,220 @@ + + +cssom-view - scrolling quirks VS nonquirks mode + + + + + +
+ diff --git a/testing/web-platform/tests/cssom-view/support/1x1-green.png b/testing/web-platform/tests/cssom-view/support/1x1-green.png new file mode 100644 index 000000000000..b98ca0ba0a03 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/1x1-green.png differ diff --git a/testing/web-platform/tests/cssom-view/support/1x1-lime.png b/testing/web-platform/tests/cssom-view/support/1x1-lime.png new file mode 100644 index 000000000000..cb397fb090e1 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/1x1-lime.png differ diff --git a/testing/web-platform/tests/cssom-view/support/1x1-maroon.png b/testing/web-platform/tests/cssom-view/support/1x1-maroon.png new file mode 100644 index 000000000000..3f86b0721955 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/1x1-maroon.png differ diff --git a/testing/web-platform/tests/cssom-view/support/1x1-navy.png b/testing/web-platform/tests/cssom-view/support/1x1-navy.png new file mode 100644 index 000000000000..9b9a03955bae Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/1x1-navy.png differ diff --git a/testing/web-platform/tests/cssom-view/support/1x1-red.png b/testing/web-platform/tests/cssom-view/support/1x1-red.png new file mode 100644 index 000000000000..6bd73ac10187 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/1x1-red.png differ diff --git a/testing/web-platform/tests/cssom-view/support/1x1-white.png b/testing/web-platform/tests/cssom-view/support/1x1-white.png new file mode 100644 index 000000000000..dd43faec54ae Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/1x1-white.png differ diff --git a/testing/web-platform/tests/cssom-view/support/60x60-gg-rr.png b/testing/web-platform/tests/cssom-view/support/60x60-gg-rr.png new file mode 100644 index 000000000000..84f5b2a4f1d1 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/60x60-gg-rr.png differ diff --git a/testing/web-platform/tests/cssom-view/support/60x60-green.png b/testing/web-platform/tests/cssom-view/support/60x60-green.png new file mode 100644 index 000000000000..b3c8cf3eb4c8 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/60x60-green.png differ diff --git a/testing/web-platform/tests/cssom-view/support/60x60-red.png b/testing/web-platform/tests/cssom-view/support/60x60-red.png new file mode 100644 index 000000000000..823f125b8e4a Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/60x60-red.png differ diff --git a/testing/web-platform/tests/cssom-view/support/README b/testing/web-platform/tests/cssom-view/support/README new file mode 100644 index 000000000000..2e5f2ad0738c --- /dev/null +++ b/testing/web-platform/tests/cssom-view/support/README @@ -0,0 +1,28 @@ +CSS Global Support Directory +============================ + +This directory contains common support files (such as images and external +style sheets). These are sync'ed into the support directories of all our +test suites. If you have test-suite-specific support files, please add +them to the appropriate test-suite-specific support/ directory. + +If you add to a support/ directory, please run the tools/supportprop.py +script from the top of the repository to cascade support files into the +lower-level support directories. + +Description of the Common Support File Collection +------------------------------------------------- + +The 1x1-* images are all exactly one pixel. + +The swatch-* images all use 15x15 cells. + +The square-* images all use 15x15 cells with one pixel borders. + +The pattern-* images use cells of various sizes: + + pattern-grg-rgr-grg.png 20x20 + pattern-rgr-grg-rgr.png 20x20 + pattern-tr.png 15x15 + pattern-grg-rrg-rgg.png 15x15 + diff --git a/testing/web-platform/tests/cssom-view/support/a-green.css b/testing/web-platform/tests/cssom-view/support/a-green.css new file mode 100644 index 000000000000..b0dbb071d5b0 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/support/a-green.css @@ -0,0 +1 @@ +.a { color: green; } diff --git a/testing/web-platform/tests/cssom-view/support/b-green.css b/testing/web-platform/tests/cssom-view/support/b-green.css new file mode 100644 index 000000000000..a0473f5ca266 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/support/b-green.css @@ -0,0 +1 @@ +.b { color: green; } \ No newline at end of file diff --git a/testing/web-platform/tests/cssom-view/support/c-red.css b/testing/web-platform/tests/cssom-view/support/c-red.css new file mode 100644 index 000000000000..d4ba5c64e954 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/support/c-red.css @@ -0,0 +1 @@ +.c { color: red; } \ No newline at end of file diff --git a/testing/web-platform/tests/cssom-view/support/cat.png b/testing/web-platform/tests/cssom-view/support/cat.png new file mode 100644 index 000000000000..85dd7324815b Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/cat.png differ diff --git a/testing/web-platform/tests/cssom-view/support/import-green.css b/testing/web-platform/tests/cssom-view/support/import-green.css new file mode 100644 index 000000000000..537104e66336 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/support/import-green.css @@ -0,0 +1 @@ +.import { color: green; } diff --git a/testing/web-platform/tests/cssom-view/support/import-red.css b/testing/web-platform/tests/cssom-view/support/import-red.css new file mode 100644 index 000000000000..9945ef47114c --- /dev/null +++ b/testing/web-platform/tests/cssom-view/support/import-red.css @@ -0,0 +1 @@ +.import { color: red; } diff --git a/testing/web-platform/tests/cssom-view/support/pattern-grg-rgr-grg.png b/testing/web-platform/tests/cssom-view/support/pattern-grg-rgr-grg.png new file mode 100644 index 000000000000..9b88fbd81149 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/pattern-grg-rgr-grg.png differ diff --git a/testing/web-platform/tests/cssom-view/support/pattern-grg-rrg-rgg.png b/testing/web-platform/tests/cssom-view/support/pattern-grg-rrg-rgg.png new file mode 100644 index 000000000000..fcf4f3fd7d95 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/pattern-grg-rrg-rgg.png differ diff --git a/testing/web-platform/tests/cssom-view/support/pattern-rgr-grg-rgr.png b/testing/web-platform/tests/cssom-view/support/pattern-rgr-grg-rgr.png new file mode 100644 index 000000000000..d454e3a630cd Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/pattern-rgr-grg-rgr.png differ diff --git a/testing/web-platform/tests/cssom-view/support/pattern-tr.png b/testing/web-platform/tests/cssom-view/support/pattern-tr.png new file mode 100644 index 000000000000..8b4b25364e0f Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/pattern-tr.png differ diff --git a/testing/web-platform/tests/cssom-view/support/ruler-h-50%.png b/testing/web-platform/tests/cssom-view/support/ruler-h-50%.png new file mode 100644 index 000000000000..cf2eea6b438a Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/ruler-h-50%.png differ diff --git a/testing/web-platform/tests/cssom-view/support/ruler-h-50px.png b/testing/web-platform/tests/cssom-view/support/ruler-h-50px.png new file mode 100644 index 000000000000..9f46583665ca Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/ruler-h-50px.png differ diff --git a/testing/web-platform/tests/cssom-view/support/ruler-v-100px.png b/testing/web-platform/tests/cssom-view/support/ruler-v-100px.png new file mode 100644 index 000000000000..a837eca22250 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/ruler-v-100px.png differ diff --git a/testing/web-platform/tests/cssom-view/support/ruler-v-50px.png b/testing/web-platform/tests/cssom-view/support/ruler-v-50px.png new file mode 100644 index 000000000000..84141028020b Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/ruler-v-50px.png differ diff --git a/testing/web-platform/tests/cssom-view/support/square-purple.png b/testing/web-platform/tests/cssom-view/support/square-purple.png new file mode 100644 index 000000000000..0f522d787284 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/square-purple.png differ diff --git a/testing/web-platform/tests/cssom-view/support/square-teal.png b/testing/web-platform/tests/cssom-view/support/square-teal.png new file mode 100644 index 000000000000..e567f51b91bb Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/square-teal.png differ diff --git a/testing/web-platform/tests/cssom-view/support/square-white.png b/testing/web-platform/tests/cssom-view/support/square-white.png new file mode 100644 index 000000000000..5853cbb238cb Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/square-white.png differ diff --git a/testing/web-platform/tests/cssom-view/support/support/README b/testing/web-platform/tests/cssom-view/support/support/README new file mode 100644 index 000000000000..ea8cb9ef357d --- /dev/null +++ b/testing/web-platform/tests/cssom-view/support/support/README @@ -0,0 +1,4 @@ +The swatch-green.png file in this directory is really a RED swatch, +and the swatch-red.png file is really a green swatch. + +This directory is used to test relative URIs. \ No newline at end of file diff --git a/testing/web-platform/tests/cssom-view/support/support/swatch-green.png b/testing/web-platform/tests/cssom-view/support/support/swatch-green.png new file mode 100644 index 000000000000..1caf25c992aa Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/support/swatch-green.png differ diff --git a/testing/web-platform/tests/cssom-view/support/support/swatch-red.png b/testing/web-platform/tests/cssom-view/support/support/swatch-red.png new file mode 100644 index 000000000000..0aa79b0c86bd Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/support/swatch-red.png differ diff --git a/testing/web-platform/tests/cssom-view/support/swatch-blue.png b/testing/web-platform/tests/cssom-view/support/swatch-blue.png new file mode 100644 index 000000000000..bf2759634d45 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/swatch-blue.png differ diff --git a/testing/web-platform/tests/cssom-view/support/swatch-green.png b/testing/web-platform/tests/cssom-view/support/swatch-green.png new file mode 100644 index 000000000000..0aa79b0c86bd Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/swatch-green.png differ diff --git a/testing/web-platform/tests/cssom-view/support/swatch-lime.png b/testing/web-platform/tests/cssom-view/support/swatch-lime.png new file mode 100644 index 000000000000..55fd7fdaedfc Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/swatch-lime.png differ diff --git a/testing/web-platform/tests/cssom-view/support/swatch-orange.png b/testing/web-platform/tests/cssom-view/support/swatch-orange.png new file mode 100644 index 000000000000..d3cd498b52bd Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/swatch-orange.png differ diff --git a/testing/web-platform/tests/cssom-view/support/swatch-red.png b/testing/web-platform/tests/cssom-view/support/swatch-red.png new file mode 100644 index 000000000000..1caf25c992aa Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/swatch-red.png differ diff --git a/testing/web-platform/tests/cssom-view/support/swatch-teal.png b/testing/web-platform/tests/cssom-view/support/swatch-teal.png new file mode 100644 index 000000000000..0293ce89dea5 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/swatch-teal.png differ diff --git a/testing/web-platform/tests/cssom-view/support/swatch-white.png b/testing/web-platform/tests/cssom-view/support/swatch-white.png new file mode 100644 index 000000000000..1a7d4323d772 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/swatch-white.png differ diff --git a/testing/web-platform/tests/cssom-view/support/swatch-yellow.png b/testing/web-platform/tests/cssom-view/support/swatch-yellow.png new file mode 100644 index 000000000000..1591aa0e2e27 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/swatch-yellow.png differ diff --git a/testing/web-platform/tests/cssom-view/support/test-bl.png b/testing/web-platform/tests/cssom-view/support/test-bl.png new file mode 100644 index 000000000000..904e24e996a3 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/test-bl.png differ diff --git a/testing/web-platform/tests/cssom-view/support/test-br.png b/testing/web-platform/tests/cssom-view/support/test-br.png new file mode 100644 index 000000000000..f413ff5c1a0f Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/test-br.png differ diff --git a/testing/web-platform/tests/cssom-view/support/test-inner-half-size.png b/testing/web-platform/tests/cssom-view/support/test-inner-half-size.png new file mode 100644 index 000000000000..e473bf80efc6 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/test-inner-half-size.png differ diff --git a/testing/web-platform/tests/cssom-view/support/test-outer.png b/testing/web-platform/tests/cssom-view/support/test-outer.png new file mode 100644 index 000000000000..82eeace7fc0c Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/test-outer.png differ diff --git a/testing/web-platform/tests/cssom-view/support/test-tl.png b/testing/web-platform/tests/cssom-view/support/test-tl.png new file mode 100644 index 000000000000..f6ac0ef7e8f6 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/test-tl.png differ diff --git a/testing/web-platform/tests/cssom-view/support/test-tr.png b/testing/web-platform/tests/cssom-view/support/test-tr.png new file mode 100644 index 000000000000..59843ae54b64 Binary files /dev/null and b/testing/web-platform/tests/cssom-view/support/test-tr.png differ diff --git a/testing/web-platform/tests/cssom-view/ttwf-js-cssomview-getclientrects-length.html b/testing/web-platform/tests/cssom-view/ttwf-js-cssomview-getclientrects-length.html new file mode 100644 index 000000000000..bc873174568c --- /dev/null +++ b/testing/web-platform/tests/cssom-view/ttwf-js-cssomview-getclientrects-length.html @@ -0,0 +1,28 @@ + + + + CSSOM View API Test: the length of getClientRects + + + + + + + + + +
+ + Test Link +
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/ttwf-scrollintoview.html b/testing/web-platform/tests/cssom-view/ttwf-scrollintoview.html new file mode 100644 index 000000000000..1ccb9c580de6 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/ttwf-scrollintoview.html @@ -0,0 +1,32 @@ + + + + CSSOM View - 6 - scrollIntoView tests + + + + + + + + + +
+
+
+
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/window-screen-height-immutable.html b/testing/web-platform/tests/cssom-view/window-screen-height-immutable.html new file mode 100644 index 000000000000..88dd0684816d --- /dev/null +++ b/testing/web-platform/tests/cssom-view/window-screen-height-immutable.html @@ -0,0 +1,27 @@ + + + + CSSOM View - 4.2 - screen.height immutability + + + + + + + + +
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/window-screen-height.html b/testing/web-platform/tests/cssom-view/window-screen-height.html new file mode 100644 index 000000000000..9bb7e528b89f --- /dev/null +++ b/testing/web-platform/tests/cssom-view/window-screen-height.html @@ -0,0 +1,37 @@ + + + + CSSOM View - 4.2 - screen.height range tests + + + + + + + + +
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/window-screen-width-immutable.html b/testing/web-platform/tests/cssom-view/window-screen-width-immutable.html new file mode 100644 index 000000000000..1415bfaca440 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/window-screen-width-immutable.html @@ -0,0 +1,27 @@ + + + + CSSOM View - 4.2 - screen.width immutability + + + + + + + + +
+
+ + + diff --git a/testing/web-platform/tests/cssom-view/window-screen-width.html b/testing/web-platform/tests/cssom-view/window-screen-width.html new file mode 100644 index 000000000000..fdae2bc74250 --- /dev/null +++ b/testing/web-platform/tests/cssom-view/window-screen-width.html @@ -0,0 +1,37 @@ + + + + CSSOM View - 4.2 - screen.width range tests + + + + + + + + +
+
+ + + diff --git a/testing/web-platform/tests/cssom/CSSKeyframesRule.html b/testing/web-platform/tests/cssom/CSSKeyframesRule.html index 9cf387def866..68453498767c 100644 --- a/testing/web-platform/tests/cssom/CSSKeyframesRule.html +++ b/testing/web-platform/tests/cssom/CSSKeyframesRule.html @@ -10,6 +10,7 @@ 0% { top: 0px; } 100% { top: 200px; } } + @keyframes empty {} diff --git a/testing/web-platform/tests/cssom/CSSStyleRule.html b/testing/web-platform/tests/cssom/CSSStyleRule.html index e6b68d7503dd..65d6d5340466 100644 --- a/testing/web-platform/tests/cssom/CSSStyleRule.html +++ b/testing/web-platform/tests/cssom/CSSStyleRule.html @@ -1,24 +1,90 @@ - - - - - - - + - test(function() { - assert_equals(typeof rule.style, "object"); - assert_equals(rule.style.margin, "10px"); - assert_equals(rule.style.padding, "0px"); + + + +
- rule.style.padding = "5px"; - rule.style.border = "1px solid"; + + test(function() { + assert_true(rule instanceof CSSRule); + assert_true(rule instanceof CSSStyleRule); + }, "CSSRule and CSSStyleRule types"); + + test(function() { + assert_equals(rule.STYLE_RULE, 1); + assert_equals(rule.IMPORT_RULE, 3); + assert_equals(rule.MEDIA_RULE, 4); + assert_equals(rule.FONT_FACE_RULE, 5); + assert_equals(rule.PAGE_RULE, 6); + assert_equals(rule.NAMESPACE_RULE, 10); + assert_idl_attribute(rule, "type"); + assert_equals(typeof rule.type, "number"); + }, "Type of CSSRule#type and constant values"); + + test(function() { + assert_true(rule instanceof CSSRule); + assert_idl_attribute(rule, "cssText"); + assert_idl_attribute(rule, "parentRule"); + assert_idl_attribute(rule, "parentStyleSheet"); + }, "Existence of CSSRule attributes"); + + test(function() { + assert_readonly(rule, "type"); + assert_readonly(rule, "parentRule"); + assert_readonly(rule, "parentStyleSheet"); + }, "Writability of CSSRule attributes"); + + test(function() { + assert_equals(rule.type, rule.STYLE_RULE); + assert_equals(typeof rule.cssText, "string"); + assert_equals(rule.cssText, "div { margin: 10px; padding: 0px; }"); + assert_equals(rule.parentRule, null); + assert_true(rule.parentStyleSheet instanceof CSSStyleSheet); + }, "Values of CSSRule attributes"); + + test(function() { + assert_idl_attribute(rule, "selectorText"); + assert_equals(typeof rule.selectorText, "string"); + assert_idl_attribute(rule, "style"); + assert_readonly(rule, "style"); + }, "Existence, writability and type of CSSStyleRule attributes"); + + test(function() { + assert_equals(rule.selectorText, "div"); + assert_true(rule.style instanceof CSSStyleDeclaration); + }, "Values of CSSStyleRule attributes"); + + test(function() { + assert_equals(rule.style.margin, "10px"); + assert_equals(rule.style.padding, "0px"); + + rule.style.padding = "5px"; + rule.style.border = "1px solid"; + + assert_equals(rule.style.padding, "5px"); + assert_equals(rule.style.border, "1px solid"); + }, "Mutability of CSSStyleRule's style attribute"); + + + diff --git a/testing/web-platform/tests/cssom/MediaList.xhtml b/testing/web-platform/tests/cssom/MediaList.xhtml new file mode 100644 index 000000000000..fb1062cba87a --- /dev/null +++ b/testing/web-platform/tests/cssom/MediaList.xhtml @@ -0,0 +1,54 @@ + + + +CSS Test: the MediaList interface + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/OWNERS b/testing/web-platform/tests/cssom/OWNERS new file mode 100644 index 000000000000..fc98874a3222 --- /dev/null +++ b/testing/web-platform/tests/cssom/OWNERS @@ -0,0 +1,6 @@ +@zcorpan +@dbaron +@plinss +@rune-opera +@lilles +@therealglazou diff --git a/testing/web-platform/tests/cssom/computed-style-001.html b/testing/web-platform/tests/cssom/computed-style-001.html new file mode 100644 index 000000000000..2cdfc9eb8b42 --- /dev/null +++ b/testing/web-platform/tests/cssom/computed-style-001.html @@ -0,0 +1,78 @@ + + + + CSS Test: getComputedStyle + + + + + + + + + + + + + +
+
+ + + diff --git a/testing/web-platform/tests/cssom/css-style-attribute-modifications.html b/testing/web-platform/tests/cssom/css-style-attribute-modifications.html new file mode 100644 index 000000000000..6177c336d76e --- /dev/null +++ b/testing/web-platform/tests/cssom/css-style-attribute-modifications.html @@ -0,0 +1,13 @@ + + + + + +
+ diff --git a/testing/web-platform/tests/cssom/css-style-declaration-modifications.html b/testing/web-platform/tests/cssom/css-style-declaration-modifications.html new file mode 100644 index 000000000000..4db637d7de9e --- /dev/null +++ b/testing/web-platform/tests/cssom/css-style-declaration-modifications.html @@ -0,0 +1,63 @@ + + + + CSS Test: CSSStyleDeclaration Interface + + + + + + + + + +
+
+ + + diff --git a/testing/web-platform/tests/cssom/cssimportrule.html b/testing/web-platform/tests/cssom/cssimportrule.html new file mode 100644 index 000000000000..d4a3250e6807 --- /dev/null +++ b/testing/web-platform/tests/cssom/cssimportrule.html @@ -0,0 +1,88 @@ + + + + CSSOM CSSRule CSSImportRule interface + + + + + + + + + + + + +
+ + + + diff --git a/testing/web-platform/tests/cssom/cssom-cssText-serialize.html b/testing/web-platform/tests/cssom/cssom-cssText-serialize.html new file mode 100644 index 000000000000..27479f026df6 --- /dev/null +++ b/testing/web-platform/tests/cssom/cssom-cssText-serialize.html @@ -0,0 +1,28 @@ + + + + CSSOM Parsing Test: getting cssText must return the result of serializing the CSS declaration blocks. + + + + + + + + + + + +
+
+ + + diff --git a/testing/web-platform/tests/cssom/cssom-cssstyledeclaration-set.html b/testing/web-platform/tests/cssom/cssom-cssstyledeclaration-set.html new file mode 100644 index 000000000000..1fb7ccd32499 --- /dev/null +++ b/testing/web-platform/tests/cssom/cssom-cssstyledeclaration-set.html @@ -0,0 +1,37 @@ + + + + CSSOM: CSSStyleDeclaration on HTMLElement represents inline style changes + + + + + + + + + + + +
+ +
+ + + + + + diff --git a/testing/web-platform/tests/cssom/cssom-fontfacerule-constructors.html b/testing/web-platform/tests/cssom/cssom-fontfacerule-constructors.html new file mode 100644 index 000000000000..c94b63e9b31c --- /dev/null +++ b/testing/web-platform/tests/cssom/cssom-fontfacerule-constructors.html @@ -0,0 +1,63 @@ + + + + CSSOM Parsing Test: @font-face rules toString() as valid interfaces + + + + + + + + + + + +
+ + + + + + + + + + diff --git a/testing/web-platform/tests/cssom/cssom-fontfacerule.html b/testing/web-platform/tests/cssom/cssom-fontfacerule.html new file mode 100644 index 000000000000..06209101c38a --- /dev/null +++ b/testing/web-platform/tests/cssom/cssom-fontfacerule.html @@ -0,0 +1,58 @@ + + + + CSSOM Parsing Test: @font-face rules parsed into CSSOM CSSFontFaceRules + + + + + + + + + + +
+ + + + + + + + + + diff --git a/testing/web-platform/tests/cssom/cssom-setProperty-shorthand.html b/testing/web-platform/tests/cssom/cssom-setProperty-shorthand.html new file mode 100644 index 000000000000..fe2ad4731a1e --- /dev/null +++ b/testing/web-platform/tests/cssom/cssom-setProperty-shorthand.html @@ -0,0 +1,69 @@ + + + + CSSOM: CSSStyleDeclaration (set|remove)PropertyValue sets/removes shorthand properties + + + + + + + + + + + +
+ +
+ + + + diff --git a/testing/web-platform/tests/cssom/cssstyledeclaration-csstext.html b/testing/web-platform/tests/cssom/cssstyledeclaration-csstext.html new file mode 100644 index 000000000000..30d9bd87bde5 --- /dev/null +++ b/testing/web-platform/tests/cssom/cssstyledeclaration-csstext.html @@ -0,0 +1,102 @@ + + + + CSSOM Test: CSSStyleDeclaration.cssText Test + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/cssstyledeclaration-mutability.html b/testing/web-platform/tests/cssom/cssstyledeclaration-mutability.html new file mode 100644 index 000000000000..e7bde1bda639 --- /dev/null +++ b/testing/web-platform/tests/cssom/cssstyledeclaration-mutability.html @@ -0,0 +1,69 @@ + + + + CSSOM: CSSStyleDeclaration is mutable and immutable in various settings + + + + + + + + + + + +
+
+
+ + + + + diff --git a/testing/web-platform/tests/cssom/escape.html b/testing/web-platform/tests/cssom/escape.html new file mode 100644 index 000000000000..115e2c86a9a0 --- /dev/null +++ b/testing/web-platform/tests/cssom/escape.html @@ -0,0 +1,98 @@ + + +CSS#escape + + + +
+ diff --git a/testing/web-platform/tests/cssom/index-001.html b/testing/web-platform/tests/cssom/index-001.html new file mode 100644 index 000000000000..ca53e503297c --- /dev/null +++ b/testing/web-platform/tests/cssom/index-001.html @@ -0,0 +1,28 @@ + + + CSS OM: CSS Values + + + + + + + + +
+
+ + + + diff --git a/testing/web-platform/tests/cssom/index-002.html b/testing/web-platform/tests/cssom/index-002.html new file mode 100644 index 000000000000..29ec3a90a11a --- /dev/null +++ b/testing/web-platform/tests/cssom/index-002.html @@ -0,0 +1,79 @@ + + + CSS OM: CSS Values + + + + + + + + +
+
+ + + diff --git a/testing/web-platform/tests/cssom/index-003.html b/testing/web-platform/tests/cssom/index-003.html new file mode 100644 index 000000000000..354afd3c6c17 --- /dev/null +++ b/testing/web-platform/tests/cssom/index-003.html @@ -0,0 +1,95 @@ + + + CSS OM: CSS Values + + + + + + + + + + + + + + + +
+ + + + diff --git a/testing/web-platform/tests/cssom/inline-style-001.html b/testing/web-platform/tests/cssom/inline-style-001.html new file mode 100644 index 000000000000..3a9eebf7e723 --- /dev/null +++ b/testing/web-platform/tests/cssom/inline-style-001.html @@ -0,0 +1,100 @@ + + + + CSS Test: Inline CSSStyleDeclaration + + + + + + + + + + +
+
+ + + diff --git a/testing/web-platform/tests/cssom/interfaces.html b/testing/web-platform/tests/cssom/interfaces.html new file mode 100644 index 000000000000..cf43e94bc116 --- /dev/null +++ b/testing/web-platform/tests/cssom/interfaces.html @@ -0,0 +1,174 @@ + + +CSSOM automated IDL tests + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/medialist-interfaces-001.html b/testing/web-platform/tests/cssom/medialist-interfaces-001.html new file mode 100644 index 000000000000..ad95394d5c5e --- /dev/null +++ b/testing/web-platform/tests/cssom/medialist-interfaces-001.html @@ -0,0 +1,110 @@ + + + + CSS Test: CSSOM Media Query List Serialization + + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/medialist-interfaces-002.html b/testing/web-platform/tests/cssom/medialist-interfaces-002.html new file mode 100644 index 000000000000..d3dfff8e42b1 --- /dev/null +++ b/testing/web-platform/tests/cssom/medialist-interfaces-002.html @@ -0,0 +1,80 @@ + + + + CSS Test: CSSOM MediaList Interfaces + + + + + + + + + + + + + + +
+ + + + + + diff --git a/testing/web-platform/tests/cssom/medialist-interfaces-003.html b/testing/web-platform/tests/cssom/medialist-interfaces-003.html new file mode 100644 index 000000000000..717c39d618fe --- /dev/null +++ b/testing/web-platform/tests/cssom/medialist-interfaces-003.html @@ -0,0 +1,72 @@ + + + + CSS Test: CSSOM Media Query Serialization + + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/medialist-interfaces-004.html b/testing/web-platform/tests/cssom/medialist-interfaces-004.html new file mode 100644 index 000000000000..2fe6ff915d74 --- /dev/null +++ b/testing/web-platform/tests/cssom/medialist-interfaces-004.html @@ -0,0 +1,72 @@ + + + + CSS Test: CSSOM MediaList Interfaces + + + + + + + + + + + + + +
+ + + + + + diff --git a/testing/web-platform/tests/cssom/selectorSerialize.html b/testing/web-platform/tests/cssom/selectorSerialize.html new file mode 100644 index 000000000000..fc9445ca96a4 --- /dev/null +++ b/testing/web-platform/tests/cssom/selectorSerialize.html @@ -0,0 +1,107 @@ + + + + CSSOM Test: test serialized selector which is only one simple selector in the sequence of simple selectors + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/serialize-namespaced-type-selectors.html b/testing/web-platform/tests/cssom/serialize-namespaced-type-selectors.html new file mode 100644 index 000000000000..600008c7a9eb --- /dev/null +++ b/testing/web-platform/tests/cssom/serialize-namespaced-type-selectors.html @@ -0,0 +1,257 @@ + + + + CSSOM Test: test serialization of type selectors and namespace prefixes + + + + + + + + + +
+ + + + diff --git a/testing/web-platform/tests/cssom/serialize-variable-reference.html b/testing/web-platform/tests/cssom/serialize-variable-reference.html new file mode 100644 index 000000000000..d714b81518b3 --- /dev/null +++ b/testing/web-platform/tests/cssom/serialize-variable-reference.html @@ -0,0 +1,34 @@ + + +CSSOM - Serialization with variable preserves original serialization. + + +
+
+
+
+ diff --git a/testing/web-platform/tests/cssom/style-sheet-interfaces-001.html b/testing/web-platform/tests/cssom/style-sheet-interfaces-001.html new file mode 100644 index 000000000000..3f4956cb3ad4 --- /dev/null +++ b/testing/web-platform/tests/cssom/style-sheet-interfaces-001.html @@ -0,0 +1,128 @@ + + + + CSS Test: CSSOM StyleSheet Initial Values + + + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/style-sheet-interfaces-002.html b/testing/web-platform/tests/cssom/style-sheet-interfaces-002.html new file mode 100644 index 000000000000..ad5b1ac58616 --- /dev/null +++ b/testing/web-platform/tests/cssom/style-sheet-interfaces-002.html @@ -0,0 +1,51 @@ + + + + CSS Test: CSSOM StyleSheet Modify Rule List + + + + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/support/1x1-green.png b/testing/web-platform/tests/cssom/support/1x1-green.png new file mode 100644 index 000000000000..b98ca0ba0a03 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/1x1-green.png differ diff --git a/testing/web-platform/tests/cssom/support/1x1-lime.png b/testing/web-platform/tests/cssom/support/1x1-lime.png new file mode 100644 index 000000000000..cb397fb090e1 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/1x1-lime.png differ diff --git a/testing/web-platform/tests/cssom/support/1x1-maroon.png b/testing/web-platform/tests/cssom/support/1x1-maroon.png new file mode 100644 index 000000000000..3f86b0721955 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/1x1-maroon.png differ diff --git a/testing/web-platform/tests/cssom/support/1x1-navy.png b/testing/web-platform/tests/cssom/support/1x1-navy.png new file mode 100644 index 000000000000..9b9a03955bae Binary files /dev/null and b/testing/web-platform/tests/cssom/support/1x1-navy.png differ diff --git a/testing/web-platform/tests/cssom/support/1x1-red.png b/testing/web-platform/tests/cssom/support/1x1-red.png new file mode 100644 index 000000000000..6bd73ac10187 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/1x1-red.png differ diff --git a/testing/web-platform/tests/cssom/support/1x1-white.png b/testing/web-platform/tests/cssom/support/1x1-white.png new file mode 100644 index 000000000000..dd43faec54ae Binary files /dev/null and b/testing/web-platform/tests/cssom/support/1x1-white.png differ diff --git a/testing/web-platform/tests/cssom/support/60x60-gg-rr.png b/testing/web-platform/tests/cssom/support/60x60-gg-rr.png new file mode 100644 index 000000000000..84f5b2a4f1d1 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/60x60-gg-rr.png differ diff --git a/testing/web-platform/tests/cssom/support/60x60-green.png b/testing/web-platform/tests/cssom/support/60x60-green.png new file mode 100644 index 000000000000..b3c8cf3eb4c8 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/60x60-green.png differ diff --git a/testing/web-platform/tests/cssom/support/60x60-red.png b/testing/web-platform/tests/cssom/support/60x60-red.png new file mode 100644 index 000000000000..823f125b8e4a Binary files /dev/null and b/testing/web-platform/tests/cssom/support/60x60-red.png differ diff --git a/testing/web-platform/tests/cssom/support/README b/testing/web-platform/tests/cssom/support/README new file mode 100644 index 000000000000..2e5f2ad0738c --- /dev/null +++ b/testing/web-platform/tests/cssom/support/README @@ -0,0 +1,28 @@ +CSS Global Support Directory +============================ + +This directory contains common support files (such as images and external +style sheets). These are sync'ed into the support directories of all our +test suites. If you have test-suite-specific support files, please add +them to the appropriate test-suite-specific support/ directory. + +If you add to a support/ directory, please run the tools/supportprop.py +script from the top of the repository to cascade support files into the +lower-level support directories. + +Description of the Common Support File Collection +------------------------------------------------- + +The 1x1-* images are all exactly one pixel. + +The swatch-* images all use 15x15 cells. + +The square-* images all use 15x15 cells with one pixel borders. + +The pattern-* images use cells of various sizes: + + pattern-grg-rgr-grg.png 20x20 + pattern-rgr-grg-rgr.png 20x20 + pattern-tr.png 15x15 + pattern-grg-rrg-rgg.png 15x15 + diff --git a/testing/web-platform/tests/cssom/support/a-green.css b/testing/web-platform/tests/cssom/support/a-green.css new file mode 100644 index 000000000000..b0dbb071d5b0 --- /dev/null +++ b/testing/web-platform/tests/cssom/support/a-green.css @@ -0,0 +1 @@ +.a { color: green; } diff --git a/testing/web-platform/tests/cssom/support/b-green.css b/testing/web-platform/tests/cssom/support/b-green.css new file mode 100644 index 000000000000..a0473f5ca266 --- /dev/null +++ b/testing/web-platform/tests/cssom/support/b-green.css @@ -0,0 +1 @@ +.b { color: green; } \ No newline at end of file diff --git a/testing/web-platform/tests/cssom/support/c-red.css b/testing/web-platform/tests/cssom/support/c-red.css new file mode 100644 index 000000000000..d4ba5c64e954 --- /dev/null +++ b/testing/web-platform/tests/cssom/support/c-red.css @@ -0,0 +1 @@ +.c { color: red; } \ No newline at end of file diff --git a/testing/web-platform/tests/cssom/support/cat.png b/testing/web-platform/tests/cssom/support/cat.png new file mode 100644 index 000000000000..85dd7324815b Binary files /dev/null and b/testing/web-platform/tests/cssom/support/cat.png differ diff --git a/testing/web-platform/tests/cssom/support/import-green.css b/testing/web-platform/tests/cssom/support/import-green.css new file mode 100644 index 000000000000..537104e66336 --- /dev/null +++ b/testing/web-platform/tests/cssom/support/import-green.css @@ -0,0 +1 @@ +.import { color: green; } diff --git a/testing/web-platform/tests/cssom/support/import-red.css b/testing/web-platform/tests/cssom/support/import-red.css new file mode 100644 index 000000000000..9945ef47114c --- /dev/null +++ b/testing/web-platform/tests/cssom/support/import-red.css @@ -0,0 +1 @@ +.import { color: red; } diff --git a/testing/web-platform/tests/cssom/support/pattern-grg-rgr-grg.png b/testing/web-platform/tests/cssom/support/pattern-grg-rgr-grg.png new file mode 100644 index 000000000000..9b88fbd81149 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/pattern-grg-rgr-grg.png differ diff --git a/testing/web-platform/tests/cssom/support/pattern-grg-rrg-rgg.png b/testing/web-platform/tests/cssom/support/pattern-grg-rrg-rgg.png new file mode 100644 index 000000000000..fcf4f3fd7d95 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/pattern-grg-rrg-rgg.png differ diff --git a/testing/web-platform/tests/cssom/support/pattern-rgr-grg-rgr.png b/testing/web-platform/tests/cssom/support/pattern-rgr-grg-rgr.png new file mode 100644 index 000000000000..d454e3a630cd Binary files /dev/null and b/testing/web-platform/tests/cssom/support/pattern-rgr-grg-rgr.png differ diff --git a/testing/web-platform/tests/cssom/support/pattern-tr.png b/testing/web-platform/tests/cssom/support/pattern-tr.png new file mode 100644 index 000000000000..8b4b25364e0f Binary files /dev/null and b/testing/web-platform/tests/cssom/support/pattern-tr.png differ diff --git a/testing/web-platform/tests/cssom/support/ruler-h-50%.png b/testing/web-platform/tests/cssom/support/ruler-h-50%.png new file mode 100644 index 000000000000..cf2eea6b438a Binary files /dev/null and b/testing/web-platform/tests/cssom/support/ruler-h-50%.png differ diff --git a/testing/web-platform/tests/cssom/support/ruler-h-50px.png b/testing/web-platform/tests/cssom/support/ruler-h-50px.png new file mode 100644 index 000000000000..9f46583665ca Binary files /dev/null and b/testing/web-platform/tests/cssom/support/ruler-h-50px.png differ diff --git a/testing/web-platform/tests/cssom/support/ruler-v-100px.png b/testing/web-platform/tests/cssom/support/ruler-v-100px.png new file mode 100644 index 000000000000..a837eca22250 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/ruler-v-100px.png differ diff --git a/testing/web-platform/tests/cssom/support/ruler-v-50px.png b/testing/web-platform/tests/cssom/support/ruler-v-50px.png new file mode 100644 index 000000000000..84141028020b Binary files /dev/null and b/testing/web-platform/tests/cssom/support/ruler-v-50px.png differ diff --git a/testing/web-platform/tests/cssom/support/square-purple.png b/testing/web-platform/tests/cssom/support/square-purple.png new file mode 100644 index 000000000000..0f522d787284 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/square-purple.png differ diff --git a/testing/web-platform/tests/cssom/support/square-teal.png b/testing/web-platform/tests/cssom/support/square-teal.png new file mode 100644 index 000000000000..e567f51b91bb Binary files /dev/null and b/testing/web-platform/tests/cssom/support/square-teal.png differ diff --git a/testing/web-platform/tests/cssom/support/square-white.png b/testing/web-platform/tests/cssom/support/square-white.png new file mode 100644 index 000000000000..5853cbb238cb Binary files /dev/null and b/testing/web-platform/tests/cssom/support/square-white.png differ diff --git a/testing/web-platform/tests/cssom/support/support/README b/testing/web-platform/tests/cssom/support/support/README new file mode 100644 index 000000000000..ea8cb9ef357d --- /dev/null +++ b/testing/web-platform/tests/cssom/support/support/README @@ -0,0 +1,4 @@ +The swatch-green.png file in this directory is really a RED swatch, +and the swatch-red.png file is really a green swatch. + +This directory is used to test relative URIs. \ No newline at end of file diff --git a/testing/web-platform/tests/cssom/support/support/swatch-green.png b/testing/web-platform/tests/cssom/support/support/swatch-green.png new file mode 100644 index 000000000000..1caf25c992aa Binary files /dev/null and b/testing/web-platform/tests/cssom/support/support/swatch-green.png differ diff --git a/testing/web-platform/tests/cssom/support/support/swatch-red.png b/testing/web-platform/tests/cssom/support/support/swatch-red.png new file mode 100644 index 000000000000..0aa79b0c86bd Binary files /dev/null and b/testing/web-platform/tests/cssom/support/support/swatch-red.png differ diff --git a/testing/web-platform/tests/cssom/support/swatch-blue.png b/testing/web-platform/tests/cssom/support/swatch-blue.png new file mode 100644 index 000000000000..bf2759634d45 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/swatch-blue.png differ diff --git a/testing/web-platform/tests/cssom/support/swatch-green.png b/testing/web-platform/tests/cssom/support/swatch-green.png new file mode 100644 index 000000000000..0aa79b0c86bd Binary files /dev/null and b/testing/web-platform/tests/cssom/support/swatch-green.png differ diff --git a/testing/web-platform/tests/cssom/support/swatch-lime.png b/testing/web-platform/tests/cssom/support/swatch-lime.png new file mode 100644 index 000000000000..55fd7fdaedfc Binary files /dev/null and b/testing/web-platform/tests/cssom/support/swatch-lime.png differ diff --git a/testing/web-platform/tests/cssom/support/swatch-orange.png b/testing/web-platform/tests/cssom/support/swatch-orange.png new file mode 100644 index 000000000000..d3cd498b52bd Binary files /dev/null and b/testing/web-platform/tests/cssom/support/swatch-orange.png differ diff --git a/testing/web-platform/tests/cssom/support/swatch-red.png b/testing/web-platform/tests/cssom/support/swatch-red.png new file mode 100644 index 000000000000..1caf25c992aa Binary files /dev/null and b/testing/web-platform/tests/cssom/support/swatch-red.png differ diff --git a/testing/web-platform/tests/cssom/support/swatch-teal.png b/testing/web-platform/tests/cssom/support/swatch-teal.png new file mode 100644 index 000000000000..0293ce89dea5 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/swatch-teal.png differ diff --git a/testing/web-platform/tests/cssom/support/swatch-white.png b/testing/web-platform/tests/cssom/support/swatch-white.png new file mode 100644 index 000000000000..1a7d4323d772 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/swatch-white.png differ diff --git a/testing/web-platform/tests/cssom/support/swatch-yellow.png b/testing/web-platform/tests/cssom/support/swatch-yellow.png new file mode 100644 index 000000000000..1591aa0e2e27 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/swatch-yellow.png differ diff --git a/testing/web-platform/tests/cssom/support/test-bl.png b/testing/web-platform/tests/cssom/support/test-bl.png new file mode 100644 index 000000000000..904e24e996a3 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/test-bl.png differ diff --git a/testing/web-platform/tests/cssom/support/test-br.png b/testing/web-platform/tests/cssom/support/test-br.png new file mode 100644 index 000000000000..f413ff5c1a0f Binary files /dev/null and b/testing/web-platform/tests/cssom/support/test-br.png differ diff --git a/testing/web-platform/tests/cssom/support/test-inner-half-size.png b/testing/web-platform/tests/cssom/support/test-inner-half-size.png new file mode 100644 index 000000000000..e473bf80efc6 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/test-inner-half-size.png differ diff --git a/testing/web-platform/tests/cssom/support/test-outer.png b/testing/web-platform/tests/cssom/support/test-outer.png new file mode 100644 index 000000000000..82eeace7fc0c Binary files /dev/null and b/testing/web-platform/tests/cssom/support/test-outer.png differ diff --git a/testing/web-platform/tests/cssom/support/test-tl.png b/testing/web-platform/tests/cssom/support/test-tl.png new file mode 100644 index 000000000000..f6ac0ef7e8f6 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/test-tl.png differ diff --git a/testing/web-platform/tests/cssom/support/test-tr.png b/testing/web-platform/tests/cssom/support/test-tr.png new file mode 100644 index 000000000000..59843ae54b64 Binary files /dev/null and b/testing/web-platform/tests/cssom/support/test-tr.png differ diff --git a/testing/web-platform/tests/cssom/ttwf-cssom-doc-ext-load-count.html b/testing/web-platform/tests/cssom/ttwf-cssom-doc-ext-load-count.html new file mode 100644 index 000000000000..f507a961032d --- /dev/null +++ b/testing/web-platform/tests/cssom/ttwf-cssom-doc-ext-load-count.html @@ -0,0 +1,68 @@ + + + + CSSOM - Extensions to the Document Interface: StyleSheetList length reflects dynamically loaded and unloaded sheets + + + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/ttwf-cssom-doc-ext-load-tree-order.html b/testing/web-platform/tests/cssom/ttwf-cssom-doc-ext-load-tree-order.html new file mode 100644 index 000000000000..795ead02f4b2 --- /dev/null +++ b/testing/web-platform/tests/cssom/ttwf-cssom-doc-ext-load-tree-order.html @@ -0,0 +1,56 @@ + + + + CSSOM - Extensions to the Document Interface: Stylesheet header load order + + + + + + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/cssom/ttwf-cssom-document-extension.html b/testing/web-platform/tests/cssom/ttwf-cssom-document-extension.html new file mode 100644 index 000000000000..0c9116dc4b26 --- /dev/null +++ b/testing/web-platform/tests/cssom/ttwf-cssom-document-extension.html @@ -0,0 +1,25 @@ + + + + CSSOM - Extensions to the Document Interface: StyleSheetList length is 0 when no sheets loaded + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/custom-elements/custom-element-registry/per-global.html b/testing/web-platform/tests/custom-elements/custom-element-registry/per-global.html new file mode 100644 index 000000000000..3570dcf811db --- /dev/null +++ b/testing/web-platform/tests/custom-elements/custom-element-registry/per-global.html @@ -0,0 +1,14 @@ + + +Custom Elements: CustomElementRegistry is per global + + + + + + + + diff --git a/testing/web-platform/tests/custom-elements/microtasks-and-constructors.html b/testing/web-platform/tests/custom-elements/microtasks-and-constructors.html new file mode 100644 index 000000000000..78d2cba42c0c --- /dev/null +++ b/testing/web-platform/tests/custom-elements/microtasks-and-constructors.html @@ -0,0 +1,123 @@ + +Custom elements: performing a microtask checkpoint after construction + + + + + + + +
+ + + + + + + + + + + + diff --git a/testing/web-platform/tests/docs/_writing-tests/idlharness.html b/testing/web-platform/tests/docs/_writing-tests/idlharness.html deleted file mode 100644 index f9e18ef41fc0..000000000000 --- a/testing/web-platform/tests/docs/_writing-tests/idlharness.html +++ /dev/null @@ -1,11 +0,0 @@ ---- -layout: page -title: idlharness.js API -order: 6 ---- - - diff --git a/testing/web-platform/tests/resources/docs/idlharness.md b/testing/web-platform/tests/docs/_writing-tests/idlharness.md similarity index 99% rename from testing/web-platform/tests/resources/docs/idlharness.md rename to testing/web-platform/tests/docs/_writing-tests/idlharness.md index 141077b3a72a..76c121953c0e 100644 --- a/testing/web-platform/tests/resources/docs/idlharness.md +++ b/testing/web-platform/tests/docs/_writing-tests/idlharness.md @@ -1,3 +1,9 @@ +--- +layout: page +title: idlharness.js API +order: 6 +--- + ## Introduction ## `idlharness.js` automatically generates browser tests for WebIDL interfaces, using diff --git a/testing/web-platform/tests/docs/_writing-tests/index.md b/testing/web-platform/tests/docs/_writing-tests/index.md index a9ae0d747cf4..6454eb1edac8 100644 --- a/testing/web-platform/tests/docs/_writing-tests/index.md +++ b/testing/web-platform/tests/docs/_writing-tests/index.md @@ -47,7 +47,7 @@ however. ## Submitting Tests -Once you're written tests, please submit them using +Once you've written tests, please submit them using the [typical GitHub Pull Request workflow][submission-process]; please make sure you run the [`lint` script][lint-tool] before opening a pull request! diff --git a/testing/web-platform/tests/docs/_writing-tests/testharness-api.html b/testing/web-platform/tests/docs/_writing-tests/testharness-api.html deleted file mode 100644 index 80af9f0e1f01..000000000000 --- a/testing/web-platform/tests/docs/_writing-tests/testharness-api.html +++ /dev/null @@ -1,11 +0,0 @@ ---- -layout: page -title: testharness.js API -order: 5 ---- - - diff --git a/testing/web-platform/tests/resources/docs/api.md b/testing/web-platform/tests/docs/_writing-tests/testharness-api.md similarity index 93% rename from testing/web-platform/tests/resources/docs/api.md rename to testing/web-platform/tests/docs/_writing-tests/testharness-api.md index d2c0af198f3f..6f90007c879f 100644 --- a/testing/web-platform/tests/resources/docs/api.md +++ b/testing/web-platform/tests/docs/_writing-tests/testharness-api.md @@ -1,3 +1,9 @@ +--- +layout: page +title: testharness.js API +order: 5 +--- + ## Introduction ## testharness.js provides a framework for writing testcases. It is intended to @@ -522,6 +528,63 @@ object. These objects are structured as follows: * result - `{ type: "result", test: Test }` * complete - `{ type: "complete", tests: [Test, ...], status: TestsStatus }` +## Consolidating tests from other documents ## + +`fetch_tests_from_window` will aggregate tests from separate windows or iframes +into the current document as if they were all part of the same test suite. The +document of the second window (or iframe) should include `testharness.js`, but +not `testharnessreport.js`, and use `test`, `async_test`, and `promise_test` in +the usual manner. + +The current test suite will not report completion until +all fetched tests are complete, and errors in the child contexts will result in +failures for the suite in the current context. + +Here's an example that uses `window.open`. + +`child.html`: + +```html + + +Child context test(s) + + + + +
+ + + +``` + +`test.html`: + +```html + + +Primary test context + + + + + +
+ + + +``` + +The argument to `fetch_tests_from_window` is any [`Window`](https://html.spec.whatwg.org/multipage/browsers.html#the-window-object) +capable of accessing the browsing context as either an ancestor or opener. + ## Web Workers ## The `testharness.js` script can be used from within [dedicated workers, shared @@ -603,11 +666,13 @@ asserts that `actual` is strictly true asserts that `actual` is strictly false ### `assert_equals(actual, expected, description)` -asserts that `actual` is the same value as `expected` +asserts that `actual` is the same value as `expected`. +Relies on `===`, distinguishes between `-0` and `+0`, and has a specific check for `NaN`. ### `assert_not_equals(actual, expected, description)` asserts that `actual` is a different value to `expected`. This means that `expected` is a misnomer. +Relies on `===`, distinguishes between `-0` and `+0`, and has a specific check for `NaN`. ### `assert_in_array(actual, expected, description)` asserts that `expected` is an Array, and `actual` is equal to one of the diff --git a/testing/web-platform/tests/docs/_writing-tests/testharness.md b/testing/web-platform/tests/docs/_writing-tests/testharness.md index 3da618492895..84aef5887b61 100644 --- a/testing/web-platform/tests/docs/_writing-tests/testharness.md +++ b/testing/web-platform/tests/docs/_writing-tests/testharness.md @@ -80,6 +80,12 @@ creating a `FileAPI/Blob-constructor.any.js` as follows: This test could then be run from `FileAPI/Blob-constructor.any.worker.html` as well as `FileAPI/Blob-constructor.any.html`. +To check if your test is run from a window or worker you can use the following two methods that will +be made available by the framework: + + self.GLOBAL.isWindow() + self.GLOBAL.isWorker() + ### Including other JavaScript resources in auto-generated boilerplate tests Use `// META: script=link/to/resource.js` at the beginning of the resource. For example, @@ -95,5 +101,5 @@ Use `// META: timeout=long` at the beginning of the resource. [general guidelines]: {{ site.baseurl }}{% link _writing-tests/general-guidelines.md %} -[testharness-api]: {{ site.baseurl }}{% link _writing-tests/testharness-api.html %} -[idlharness]: {{ site.baseurl }}{% link _writing-tests/idlharness.html %} +[testharness-api]: {{ site.baseurl }}{% link _writing-tests/testharness-api.md %} +[idlharness]: {{ site.baseurl }}{% link _writing-tests/idlharness.md %} diff --git a/testing/web-platform/tests/docs/assets/_reftest_graph_example.dot b/testing/web-platform/tests/docs/assets/_reftest_graph_example.dot index d9bdef76d06d..9389f07dc2bd 100644 --- a/testing/web-platform/tests/docs/assets/_reftest_graph_example.dot +++ b/testing/web-platform/tests/docs/assets/_reftest_graph_example.dot @@ -1,3 +1,5 @@ +# Generate with `$ dot -Tsvg -oreftest_graph_example.svg _reftest_graph_example.dot` + digraph reftest_graph_example { "a.html" -> "b.html" [label="=="]; "a.html" -> "c.html" [label="=="]; diff --git a/testing/web-platform/tests/docs/assets/main.scss b/testing/web-platform/tests/docs/assets/main.scss index e2a5d80eefef..4dc5e5c4147b 100644 --- a/testing/web-platform/tests/docs/assets/main.scss +++ b/testing/web-platform/tests/docs/assets/main.scss @@ -93,18 +93,6 @@ nav.home { } -// TTWF include iframes -iframe.ttwf { - border: 1px solid grey; - width: 100%; - max-width: 990px; - height: 75vh; - margin: 0 auto; - display: block; - box-sizing: border-box; -} - - // Site nav (class name is to avoid conflict with minima defined .site-nav) .wpt-site-nav { float: right; diff --git a/testing/web-platform/tests/dom/events/EventListener-invoke-legacy.html b/testing/web-platform/tests/dom/events/EventListener-invoke-legacy.html index a969c8072b44..85a4b0a5fe64 100644 --- a/testing/web-platform/tests/dom/events/EventListener-invoke-legacy.html +++ b/testing/web-platform/tests/dom/events/EventListener-invoke-legacy.html @@ -43,7 +43,7 @@ function runLegacyEventTest(type, legacyType, ctor, setup) { assert_unreached("listener of " + legacyType + " should not be invoked again"); return; } - elem.dispatchEvent(new ctor(type)); + elem.dispatchEvent(new window[ctor](type)); t.done(); })); setup(elem); @@ -65,8 +65,8 @@ function setupAnimation(elem) { elem.style.animation = 'test 30ms 2'; } -runLegacyEventTest('transitionend', 'webkitTransitionEnd', TransitionEvent, setupTransition); -runLegacyEventTest('animationend', 'webkitAnimationEnd', AnimationEvent, setupAnimation); -runLegacyEventTest('animationiteration', 'webkitAnimationIteration', AnimationEvent, setupAnimation); -runLegacyEventTest('animationstart', 'webkitAnimationStart', AnimationEvent, setupAnimation); +runLegacyEventTest('transitionend', 'webkitTransitionEnd', "TransitionEvent", setupTransition); +runLegacyEventTest('animationend', 'webkitAnimationEnd', "AnimationEvent", setupAnimation); +runLegacyEventTest('animationiteration', 'webkitAnimationIteration', "AnimationEvent", setupAnimation); +runLegacyEventTest('animationstart', 'webkitAnimationStart', "AnimationEvent", setupAnimation); diff --git a/testing/web-platform/tests/dom/interfaces.html b/testing/web-platform/tests/dom/interfaces.html index a8d827bde98a..e6b12e3cbd4c 100644 --- a/testing/web-platform/tests/dom/interfaces.html +++ b/testing/web-platform/tests/dom/interfaces.html @@ -8,571 +8,18 @@

DOM IDL tests

- - diff --git a/testing/web-platform/tests/dom/nodes/Document-createEvent.html b/testing/web-platform/tests/dom/nodes/Document-createEvent.html index 29657e05b886..93b5ec4efef7 100644 --- a/testing/web-platform/tests/dom/nodes/Document-createEvent.html +++ b/testing/web-platform/tests/dom/nodes/Document-createEvent.html @@ -81,7 +81,6 @@ var someNonCreateableEvents = [ "ClipboardEvent", "CommandEvent", "DataContainerEvent", - "DeviceLightEvent", "ExtendableEvent", "ExtendableMessageEvent", "FetchEvent", diff --git a/testing/web-platform/tests/dom/nodes/Element-classlist.html b/testing/web-platform/tests/dom/nodes/Element-classlist.html index 5beee0942064..ece938e6f904 100644 --- a/testing/web-platform/tests/dom/nodes/Element-classlist.html +++ b/testing/web-platform/tests/dom/nodes/Element-classlist.html @@ -424,7 +424,7 @@ function testClassList(e, desc) { // Implementations agree on the first one here, so I test it, but disagree on // the second, so no test until the spec decides what to say. checkReplace("a b c", "c", "a", "a b"); - //checkReplace("c b a", "c", "a", ???); + checkReplace("c b a", "c", "a", "a b"); checkReplace("a b a", "a", "c", "c b"); checkReplace("a b a", "b", "c", "a c"); checkReplace(" a a b", "a", "c", "c b"); diff --git a/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-xht.xht b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-xht.xht index 7a673202b95a..3915aee42cff 100644 --- a/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-xht.xht +++ b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-xht.xht @@ -14,12 +14,18 @@ + + + + + +

This test examines the ARIA properties for doc-abstract.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-acknowledgments-manual.html b/testing/web-platform/tests/dpub-aam/doc-acknowledgments-manual.html new file mode 100644 index 000000000000..763cd3255098 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-acknowledgments-manual.html @@ -0,0 +1,127 @@ + + + + doc-acknowledgments + + + + + + + + +

This test examines the ARIA properties for doc-acknowledgments.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-afterword-manual.html b/testing/web-platform/tests/dpub-aam/doc-afterword-manual.html new file mode 100644 index 000000000000..7b9d16cc254f --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-afterword-manual.html @@ -0,0 +1,127 @@ + + + + doc-afterword + + + + + + + + +

This test examines the ARIA properties for doc-afterword.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-appendix-manual.html b/testing/web-platform/tests/dpub-aam/doc-appendix-manual.html new file mode 100644 index 000000000000..943a7c256480 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-appendix-manual.html @@ -0,0 +1,127 @@ + + + + doc-appendix + + + + + + + + +

This test examines the ARIA properties for doc-appendix.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-backlink-manual.html b/testing/web-platform/tests/dpub-aam/doc-backlink-manual.html new file mode 100644 index 000000000000..bc5e6cb15784 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-backlink-manual.html @@ -0,0 +1,161 @@ + + + + doc-backlink + + + + + + + + +

This test examines the ARIA properties for doc-backlink.

+
+
child 1
+
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-biblioentry-manual.html b/testing/web-platform/tests/dpub-aam/doc-biblioentry-manual.html new file mode 100644 index 000000000000..80924875fd90 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-biblioentry-manual.html @@ -0,0 +1,123 @@ + + + + doc-biblioentry + + + + + + + + +

This test examines the ARIA properties for doc-biblioentry.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-bibliography-manual.html b/testing/web-platform/tests/dpub-aam/doc-bibliography-manual.html new file mode 100644 index 000000000000..25d9e7556472 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-bibliography-manual.html @@ -0,0 +1,127 @@ + + + + doc-bibliography + + + + + + + + +

This test examines the ARIA properties for doc-bibliography.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-biblioref-manual.html b/testing/web-platform/tests/dpub-aam/doc-biblioref-manual.html new file mode 100644 index 000000000000..649d13055385 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-biblioref-manual.html @@ -0,0 +1,161 @@ + + + + doc-biblioref + + + + + + + + +

This test examines the ARIA properties for doc-biblioref.

+
+
child 1
+
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-chapter-manual.html b/testing/web-platform/tests/dpub-aam/doc-chapter-manual.html new file mode 100644 index 000000000000..1f8eda3d371f --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-chapter-manual.html @@ -0,0 +1,127 @@ + + + + doc-chapter + + + + + + + + +

This test examines the ARIA properties for doc-chapter.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-colophon-manual.html b/testing/web-platform/tests/dpub-aam/doc-colophon-manual.html new file mode 100644 index 000000000000..17a349048ff4 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-colophon-manual.html @@ -0,0 +1,115 @@ + + + + doc-colophon + + + + + + + + +

This test examines the ARIA properties for doc-colophon.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-conclusion-manual.html b/testing/web-platform/tests/dpub-aam/doc-conclusion-manual.html new file mode 100644 index 000000000000..e14d1e4cf9bf --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-conclusion-manual.html @@ -0,0 +1,127 @@ + + + + doc-conclusion + + + + + + + + +

This test examines the ARIA properties for doc-conclusion.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-cover-manual.html b/testing/web-platform/tests/dpub-aam/doc-cover-manual.html new file mode 100644 index 000000000000..3987abe12065 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-cover-manual.html @@ -0,0 +1,111 @@ + + + + doc-cover + + + + + + + + +

This test examines the ARIA properties for doc-cover.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-credit-manual.html b/testing/web-platform/tests/dpub-aam/doc-credit-manual.html new file mode 100644 index 000000000000..77ef255a9b06 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-credit-manual.html @@ -0,0 +1,115 @@ + + + + doc-credit + + + + + + + + +

This test examines the ARIA properties for doc-credit.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-credits-manual.html b/testing/web-platform/tests/dpub-aam/doc-credits-manual.html new file mode 100644 index 000000000000..fe3aec29b98c --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-credits-manual.html @@ -0,0 +1,127 @@ + + + + doc-credits + + + + + + + + +

This test examines the ARIA properties for doc-credits.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-dedication-manual.html b/testing/web-platform/tests/dpub-aam/doc-dedication-manual.html new file mode 100644 index 000000000000..fa44872248aa --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-dedication-manual.html @@ -0,0 +1,115 @@ + + + + doc-dedication + + + + + + + + +

This test examines the ARIA properties for doc-dedication.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-endnote-manual.html b/testing/web-platform/tests/dpub-aam/doc-endnote-manual.html new file mode 100644 index 000000000000..faae9bd2735f --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-endnote-manual.html @@ -0,0 +1,123 @@ + + + + doc-endnote + + + + + + + + +

This test examines the ARIA properties for doc-endnote.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-endnotes-manual.html b/testing/web-platform/tests/dpub-aam/doc-endnotes-manual.html new file mode 100644 index 000000000000..06e7a597977c --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-endnotes-manual.html @@ -0,0 +1,127 @@ + + + + doc-endnotes + + + + + + + + +

This test examines the ARIA properties for doc-endnotes.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-epigraph-manual.html b/testing/web-platform/tests/dpub-aam/doc-epigraph-manual.html new file mode 100644 index 000000000000..a57f8a10acd0 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-epigraph-manual.html @@ -0,0 +1,115 @@ + + + + doc-epigraph + + + + + + + + +

This test examines the ARIA properties for doc-epigraph.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-epilogue-manual.html b/testing/web-platform/tests/dpub-aam/doc-epilogue-manual.html new file mode 100644 index 000000000000..2a99c45d8cd2 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-epilogue-manual.html @@ -0,0 +1,127 @@ + + + + doc-epilogue + + + + + + + + +

This test examines the ARIA properties for doc-epilogue.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-errata-manual.html b/testing/web-platform/tests/dpub-aam/doc-errata-manual.html new file mode 100644 index 000000000000..4d46af3d853a --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-errata-manual.html @@ -0,0 +1,127 @@ + + + + doc-errata + + + + + + + + +

This test examines the ARIA properties for doc-errata.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-example-manual.html b/testing/web-platform/tests/dpub-aam/doc-example-manual.html new file mode 100644 index 000000000000..72926aaf69ad --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-example-manual.html @@ -0,0 +1,115 @@ + + + + doc-example + + + + + + + + +

This test examines the ARIA properties for doc-example.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-footnote-manual.html b/testing/web-platform/tests/dpub-aam/doc-footnote-manual.html new file mode 100644 index 000000000000..0a2602216c05 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-footnote-manual.html @@ -0,0 +1,115 @@ + + + + doc-footnote + + + + + + + + +

This test examines the ARIA properties for doc-footnote.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-foreword-manual.html b/testing/web-platform/tests/dpub-aam/doc-foreword-manual.html new file mode 100644 index 000000000000..3854cfbb7679 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-foreword-manual.html @@ -0,0 +1,127 @@ + + + + doc-foreword + + + + + + + + +

This test examines the ARIA properties for doc-foreword.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-glossary-manual.html b/testing/web-platform/tests/dpub-aam/doc-glossary-manual.html new file mode 100644 index 000000000000..6d761b49391a --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-glossary-manual.html @@ -0,0 +1,127 @@ + + + + doc-glossary + + + + + + + + +

This test examines the ARIA properties for doc-glossary.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-glossref-manual.html b/testing/web-platform/tests/dpub-aam/doc-glossref-manual.html new file mode 100644 index 000000000000..24007145d836 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-glossref-manual.html @@ -0,0 +1,161 @@ + + + + doc-glossref + + + + + + + + +

This test examines the ARIA properties for doc-glossref.

+
+
child 1
+
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-index-manual.html b/testing/web-platform/tests/dpub-aam/doc-index-manual.html new file mode 100644 index 000000000000..c22d6a9f9e26 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-index-manual.html @@ -0,0 +1,127 @@ + + + + doc-index + + + + + + + + +

This test examines the ARIA properties for doc-index.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-introduction-manual.html b/testing/web-platform/tests/dpub-aam/doc-introduction-manual.html new file mode 100644 index 000000000000..7fb3fb7f061a --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-introduction-manual.html @@ -0,0 +1,127 @@ + + + + doc-introduction + + + + + + + + +

This test examines the ARIA properties for doc-introduction.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-noteref-manual.html b/testing/web-platform/tests/dpub-aam/doc-noteref-manual.html new file mode 100644 index 000000000000..2c47e833dd03 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-noteref-manual.html @@ -0,0 +1,161 @@ + + + + doc-noteref + + + + + + + + +

This test examines the ARIA properties for doc-noteref.

+
+
child 1
+
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-notice-manual.html b/testing/web-platform/tests/dpub-aam/doc-notice-manual.html new file mode 100644 index 000000000000..48c8edffa037 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-notice-manual.html @@ -0,0 +1,115 @@ + + + + doc-notice + + + + + + + + +

This test examines the ARIA properties for doc-notice.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-pagebreak-manual.html b/testing/web-platform/tests/dpub-aam/doc-pagebreak-manual.html new file mode 100644 index 000000000000..cfd7c8fdf73b --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-pagebreak-manual.html @@ -0,0 +1,117 @@ + + + + doc-pagebreak + + + + + + + + +

This test examines the ARIA properties for doc-pagebreak.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-pagelist-manual.html b/testing/web-platform/tests/dpub-aam/doc-pagelist-manual.html new file mode 100644 index 000000000000..7bcbdd21cdc4 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-pagelist-manual.html @@ -0,0 +1,127 @@ + + + + doc-pagelist + + + + + + + + +

This test examines the ARIA properties for doc-pagelist.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-part-manual.html b/testing/web-platform/tests/dpub-aam/doc-part-manual.html new file mode 100644 index 000000000000..35cc4312933f --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-part-manual.html @@ -0,0 +1,127 @@ + + + + doc-part + + + + + + + + +

This test examines the ARIA properties for doc-part.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-preface-manual.html b/testing/web-platform/tests/dpub-aam/doc-preface-manual.html new file mode 100644 index 000000000000..9e79c5743d0b --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-preface-manual.html @@ -0,0 +1,127 @@ + + + + doc-preface + + + + + + + + +

This test examines the ARIA properties for doc-preface.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-prologue-manual.html b/testing/web-platform/tests/dpub-aam/doc-prologue-manual.html new file mode 100644 index 000000000000..c5887f556256 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-prologue-manual.html @@ -0,0 +1,127 @@ + + + + doc-prologue + + + + + + + + +

This test examines the ARIA properties for doc-prologue.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-pullquote-manual.html b/testing/web-platform/tests/dpub-aam/doc-pullquote-manual.html new file mode 100644 index 000000000000..ab454dad255e --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-pullquote-manual.html @@ -0,0 +1,115 @@ + + + + doc-pullquote + + + + + + + + +

This test examines the ARIA properties for doc-pullquote.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-qna-manual.html b/testing/web-platform/tests/dpub-aam/doc-qna-manual.html new file mode 100644 index 000000000000..b8e2e5546112 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-qna-manual.html @@ -0,0 +1,115 @@ + + + + doc-qna + + + + + + + + +

This test examines the ARIA properties for doc-qna.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-subtitle-manual.html b/testing/web-platform/tests/dpub-aam/doc-subtitle-manual.html new file mode 100644 index 000000000000..9c43c7488536 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-subtitle-manual.html @@ -0,0 +1,115 @@ + + + + doc-subtitle + + + + + + + + +

This test examines the ARIA properties for doc-subtitle.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-tip-manual.html b/testing/web-platform/tests/dpub-aam/doc-tip-manual.html new file mode 100644 index 000000000000..6367a02c150d --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-tip-manual.html @@ -0,0 +1,115 @@ + + + + doc-tip + + + + + + + + +

This test examines the ARIA properties for doc-tip.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/dpub-aam/doc-toc-manual.html b/testing/web-platform/tests/dpub-aam/doc-toc-manual.html new file mode 100644 index 000000000000..3a53c85d3a00 --- /dev/null +++ b/testing/web-platform/tests/dpub-aam/doc-toc-manual.html @@ -0,0 +1,127 @@ + + + + doc-toc + + + + + + + + +

This test examines the ARIA properties for doc-toc.

+
Text
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/editing/data/README.md b/testing/web-platform/tests/editing/data/README.md new file mode 100644 index 000000000000..606c67182ca3 --- /dev/null +++ b/testing/web-platform/tests/editing/data/README.md @@ -0,0 +1,166 @@ +# editing/data/*.js Format # + +In the interests of keeping file size down, the format of these +(machine-generated) data files is relatively concise. Unfortunately, this +means they can appear slightly cryptic to the untrained eye: + + ["foo[bar]baz", + [["stylewithcss","false"],["bold",""]], + "foo[bar]baz", + [true,true], + {"stylewithcss":[false,true,"",false,false,""],"bold":[false,false,"",false,true,""]}], + +But never fear! It's not actually so complicated (assuming you understand the +relevant APIs to begin with). Each line has the following format, which we +will explain in due course: + + ["initial HTML", + [["command1", "arg1"], ["command2", "arg2"]], + "expected HTML", + [expected retval from command1, expected retval from command2], + {"command1":[expected original/final indeterm/state/value 1], + "command2":[expected original/final indeterm/state/value 2]}], + +## Line 1: Initial HTML ## + + -> ["foo[bar]baz", + [["stylewithcss","false"],["bold",""]], + "foo[bar]baz", + [true,true], + {"stylewithcss":[false,true,"",false,false,""],"bold":[false,false,"",false,true,""]}], + +When testing, first a contenteditable div's innerHTML is set to the value given +here. Then the characters []{} are located and removed, and the selection is +set to where they used to be, as follows: + + * [ and ] indicate the left or right endpoint of the selection, if it's in + a text node. + * { and } indicate the left or right endpoint of the selection, if it's not + in a text node. + +Thus `[foo]` means the selection start and end are (foo, 0) and (foo, +3), while `{foo}` means they're (``, 0) and (``, 1). +`[foo}` and `{foo]` are also possible. There is no way to +describe backwards selections (i.e., distinguish anchor/focus). + +In cases where you want the selection in a place where it's not possible to +place text, like `{}
`, another format +exists using data-start and data-end attributes. It's only used in a few +tests, so it is not documented here. + +## Line 2: commands ## + + ["foo[bar]baz", + -> [["stylewithcss","false"],["bold",""]], + "foo[bar]baz", + [true,true], + {"stylewithcss":[false,true,"",false,false,""],"bold":[false,false,"",false,true,""]}], + +After the innerHTML of the editing host is filled in, the commands given here +are run in order, like this: + + document.execCommand("stylewithcss", false, "false"); + document.execCommand("bold", false, ""); + +Most tests have only one command run. The exceptions are: + + 1. styleWithCSS. Tests that involve formatting elements or styles are run + twice, once with styleWithCSS on and once with it off. + 2. defaultParagraphSeparator. Tests that involve `

`s or `

`s are run + twice, once with defaultParagraphSeparator set to "div" and once "p". + 3. multitest.js tests interactions between different commands, so it contains + arbitrary combinations of commands. + +## Line 3: expected HTML ## + + ["foo[bar]baz", + [["stylewithcss","false"],["bold",""]], + -> "foo[bar]baz", + [true,true], + {"stylewithcss":[false,true,"",false,false,""],"bold":[false,false,"",false,true,""]}], + +After the commands are run, we check that the innerHTML of the editing host +matches the expected HTML provided here. As on line 1, the characters []{} +(and data-start/data-end attributes) have special meaning and are not really +expected to be in the HTML. However, on this line they don't affect the test's +processing -- there are no tests of what the final selection is. + +## Line 4: expected return values ## + + ["foo[bar]baz", + [["stylewithcss","false"],["bold",""]], + "foo[bar]baz", + -> [true,true], + {"stylewithcss":[false,true,"",false,false,""],"bold":[false,false,"",false,true,""]}], + +execCommand() returns a boolean: true if all went well, false if not (e.g., +invalid value). This line says what value each execCommand() call from line 2 +was supposed to return. Usually they'll all be true, but for tests of +error-handling they'll sometimes be false. + +## Line 5: expected indeterm/state/value ## + + ["foo[bar]baz", + [["stylewithcss","false"],["bold",""]], + "foo[bar]baz", + [true,true], + -> {"stylewithcss":[false,true,"",false,false,""],"bold":[false,false,"",false,true,""]}], + +For each command that we're running, we check queryCommandIndeterm(), +queryCommandState(), and queryCommandValue() before we begin running any of our +commands, and again after we've finished the last one. (We don't run these +checks in between commands.) For each command, this line gives an array of six +expected values, in order: + + 1. Indeterm before + 2. State before + 3. Value before + 4. Indeterm after + 5. State after + 6. Value after + +You can remember this by keeping in mind that the three "before" values come +before the three "after" values, and each set of three values is in +alphabetical order (indeterm/state/value). + +## Analysis of a real-world example ## + +Let's look back at the example we started with and see what it means: + + ["foo[bar]baz", + [["stylewithcss","false"],["bold",""]], + "foo[bar]baz", + [true,true], + {"stylewithcss":[false,true,"",false,false,""],"bold":[false,false,"",false,true,""]}], + +Line 1: Set the innerHTML of our editing host to `foobarbaz`, and set the +selection's start and end inside the resulting text node, selecting the letters +"bar". (We actually first set the innerHTML to `foo[bar]baz` and remove the +brackets afterwards.) + +Line 2: Execute the commands: + + document.execCommand("stylewithcss", false, "false"); + document.execCommand("bold", false, ""); + +Before doing this, we record the indeterm/state/value for both "stylewithcss" +and "bold", and afterwards, we record them again. We also record the return +value of both execCommand() calls. + +Line 3: Our new innerHTML should be `foobarbaz`. The [ and ] say where +we would theoretically want the selection to be, but no actual test is run. + +Line 4: Both execCommands we ran should return true. + +Line 5: We expect the indeterm for styleWithCSS to be false both before and +after, and the value to be "" before and after -- since they always are for +this command. The state for styleWithCSS should be true beforehand, because +that's the way the previous test left it -- the testing framework doesn't clear +these settings in between tests. (Thus the first test of styleWithCSS on the +page also tests the default value of the state.) But we set it to false, so +after the tests it should be false. + +We expect the indeterm for bold to be false both before and after, because +before nothing is bold, and after everything is bold. Value should be "" +before and after, because it always is for bold. The state before should be +false, but after should have changed to true. diff --git a/testing/web-platform/tests/editing/data/backcolor.js b/testing/web-platform/tests/editing/data/backcolor.js index be8bda01af29..4d6e77e21d1b 100644 --- a/testing/web-platform/tests/editing/data/backcolor.js +++ b/testing/web-platform/tests/editing/data/backcolor.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["backcolor","#00FFFF"]], diff --git a/testing/web-platform/tests/editing/data/bold.js b/testing/web-platform/tests/editing/data/bold.js index e9f04726be54..61ccf4f8adfb 100644 --- a/testing/web-platform/tests/editing/data/bold.js +++ b/testing/web-platform/tests/editing/data/bold.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["bold",""]], diff --git a/testing/web-platform/tests/editing/data/createlink.js b/testing/web-platform/tests/editing/data/createlink.js index 275fcbd59959..87e59d281e5a 100644 --- a/testing/web-platform/tests/editing/data/createlink.js +++ b/testing/web-platform/tests/editing/data/createlink.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["createlink","http://www.google.com/"]], diff --git a/testing/web-platform/tests/editing/data/delete.js b/testing/web-platform/tests/editing/data/delete.js index bfea92831421..8a2bd7075314 100644 --- a/testing/web-platform/tests/editing/data/delete.js +++ b/testing/web-platform/tests/editing/data/delete.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["delete",""]], diff --git a/testing/web-platform/tests/editing/data/fontname.js b/testing/web-platform/tests/editing/data/fontname.js index 9f0cebd3e683..f4193a9bce72 100644 --- a/testing/web-platform/tests/editing/data/fontname.js +++ b/testing/web-platform/tests/editing/data/fontname.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["fontname","sans-serif"]], diff --git a/testing/web-platform/tests/editing/data/fontsize.js b/testing/web-platform/tests/editing/data/fontsize.js index 8ab0f24c278f..eb741b4f331d 100644 --- a/testing/web-platform/tests/editing/data/fontsize.js +++ b/testing/web-platform/tests/editing/data/fontsize.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["fontsize","4"]], diff --git a/testing/web-platform/tests/editing/data/forecolor.js b/testing/web-platform/tests/editing/data/forecolor.js index 5278f0953baf..57deb5b434ae 100644 --- a/testing/web-platform/tests/editing/data/forecolor.js +++ b/testing/web-platform/tests/editing/data/forecolor.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["forecolor","#0000FF"]], diff --git a/testing/web-platform/tests/editing/data/formatblock.js b/testing/web-platform/tests/editing/data/formatblock.js index 39c20e2680af..e69c8bb89c75 100644 --- a/testing/web-platform/tests/editing/data/formatblock.js +++ b/testing/web-platform/tests/editing/data/formatblock.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar

extra", [["defaultparagraphseparator","div"],["formatblock","

"]], diff --git a/testing/web-platform/tests/editing/data/forwarddelete.js b/testing/web-platform/tests/editing/data/forwarddelete.js index 66cf6cf33780..eb8d14ee0e59 100644 --- a/testing/web-platform/tests/editing/data/forwarddelete.js +++ b/testing/web-platform/tests/editing/data/forwarddelete.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]", [["forwarddelete",""]], diff --git a/testing/web-platform/tests/editing/data/hilitecolor.js b/testing/web-platform/tests/editing/data/hilitecolor.js index e1f561d8fa4c..257061963218 100644 --- a/testing/web-platform/tests/editing/data/hilitecolor.js +++ b/testing/web-platform/tests/editing/data/hilitecolor.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["hilitecolor","#00FFFF"]], diff --git a/testing/web-platform/tests/editing/data/indent.js b/testing/web-platform/tests/editing/data/indent.js index 283271630601..6d18fc35b730 100644 --- a/testing/web-platform/tests/editing/data/indent.js +++ b/testing/web-platform/tests/editing/data/indent.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar

extra", [["indent",""]], diff --git a/testing/web-platform/tests/editing/data/inserthorizontalrule.js b/testing/web-platform/tests/editing/data/inserthorizontalrule.js index 9d12d6809be1..998822789f15 100644 --- a/testing/web-platform/tests/editing/data/inserthorizontalrule.js +++ b/testing/web-platform/tests/editing/data/inserthorizontalrule.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["inserthorizontalrule",""]], diff --git a/testing/web-platform/tests/editing/data/inserthtml.js b/testing/web-platform/tests/editing/data/inserthtml.js index 78581bf533d7..0c6cff86c604 100644 --- a/testing/web-platform/tests/editing/data/inserthtml.js +++ b/testing/web-platform/tests/editing/data/inserthtml.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["stylewithcss","true"],["inserthtml","abcd"]], diff --git a/testing/web-platform/tests/editing/data/insertimage.js b/testing/web-platform/tests/editing/data/insertimage.js index d1874e652121..c2e26cb56d46 100644 --- a/testing/web-platform/tests/editing/data/insertimage.js +++ b/testing/web-platform/tests/editing/data/insertimage.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["insertimage","/img/lion.svg"]], diff --git a/testing/web-platform/tests/editing/data/insertlinebreak.js b/testing/web-platform/tests/editing/data/insertlinebreak.js index 2793cbb1c5f6..a37483eddb0a 100644 --- a/testing/web-platform/tests/editing/data/insertlinebreak.js +++ b/testing/web-platform/tests/editing/data/insertlinebreak.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[bar]baz", [["insertlinebreak",""]], diff --git a/testing/web-platform/tests/editing/data/insertorderedlist.js b/testing/web-platform/tests/editing/data/insertorderedlist.js index 76bda2d4babd..31259552cd17 100644 --- a/testing/web-platform/tests/editing/data/insertorderedlist.js +++ b/testing/web-platform/tests/editing/data/insertorderedlist.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["insertorderedlist",""]], diff --git a/testing/web-platform/tests/editing/data/insertparagraph.js b/testing/web-platform/tests/editing/data/insertparagraph.js index a9a3be4e7033..432f0e0de352 100644 --- a/testing/web-platform/tests/editing/data/insertparagraph.js +++ b/testing/web-platform/tests/editing/data/insertparagraph.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[bar]baz", [["defaultparagraphseparator","div"],["insertparagraph",""]], diff --git a/testing/web-platform/tests/editing/data/inserttext.js b/testing/web-platform/tests/editing/data/inserttext.js index 8d4e31c17a2b..4012510fcb63 100644 --- a/testing/web-platform/tests/editing/data/inserttext.js +++ b/testing/web-platform/tests/editing/data/inserttext.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[bar]baz", [["inserttext","a"]], diff --git a/testing/web-platform/tests/editing/data/insertunorderedlist.js b/testing/web-platform/tests/editing/data/insertunorderedlist.js index ad4a7236faed..c7b6bf52e338 100644 --- a/testing/web-platform/tests/editing/data/insertunorderedlist.js +++ b/testing/web-platform/tests/editing/data/insertunorderedlist.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["insertunorderedlist",""]], diff --git a/testing/web-platform/tests/editing/data/italic.js b/testing/web-platform/tests/editing/data/italic.js index 96ee0d9565c2..b7bd63f95b99 100644 --- a/testing/web-platform/tests/editing/data/italic.js +++ b/testing/web-platform/tests/editing/data/italic.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["italic",""]], diff --git a/testing/web-platform/tests/editing/data/justifycenter.js b/testing/web-platform/tests/editing/data/justifycenter.js index 76491ee44c52..8e4c80b46655 100644 --- a/testing/web-platform/tests/editing/data/justifycenter.js +++ b/testing/web-platform/tests/editing/data/justifycenter.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar

extra", [["stylewithcss","true"],["defaultparagraphseparator","div"],["justifycenter",""]], diff --git a/testing/web-platform/tests/editing/data/justifyfull.js b/testing/web-platform/tests/editing/data/justifyfull.js index c8beca840cfa..602ae11893ab 100644 --- a/testing/web-platform/tests/editing/data/justifyfull.js +++ b/testing/web-platform/tests/editing/data/justifyfull.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar

extra", [["stylewithcss","true"],["defaultparagraphseparator","div"],["justifyfull",""]], diff --git a/testing/web-platform/tests/editing/data/justifyleft.js b/testing/web-platform/tests/editing/data/justifyleft.js index c08033744beb..e0a48e3e20f2 100644 --- a/testing/web-platform/tests/editing/data/justifyleft.js +++ b/testing/web-platform/tests/editing/data/justifyleft.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar

extra", [["justifyleft",""]], diff --git a/testing/web-platform/tests/editing/data/justifyright.js b/testing/web-platform/tests/editing/data/justifyright.js index 595f7376eee1..c07f5d0bdd6b 100644 --- a/testing/web-platform/tests/editing/data/justifyright.js +++ b/testing/web-platform/tests/editing/data/justifyright.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar

extra", [["stylewithcss","true"],["defaultparagraphseparator","div"],["justifyright",""]], diff --git a/testing/web-platform/tests/editing/data/misc.js b/testing/web-platform/tests/editing/data/misc.js index a3477cf75d83..83c02ab769f5 100644 --- a/testing/web-platform/tests/editing/data/misc.js +++ b/testing/web-platform/tests/editing/data/misc.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[bar]baz", [["defaultparagraphseparator",""]], diff --git a/testing/web-platform/tests/editing/data/multitest.js b/testing/web-platform/tests/editing/data/multitest.js index 040e41eb2c60..338b9c905d66 100644 --- a/testing/web-platform/tests/editing/data/multitest.js +++ b/testing/web-platform/tests/editing/data/multitest.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["bold",""],["inserttext","a"]], diff --git a/testing/web-platform/tests/editing/data/outdent.js b/testing/web-platform/tests/editing/data/outdent.js index 18d48d0cb988..271824bee51e 100644 --- a/testing/web-platform/tests/editing/data/outdent.js +++ b/testing/web-platform/tests/editing/data/outdent.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["

foo[bar]

baz

extra", [["outdent",""]], diff --git a/testing/web-platform/tests/editing/data/removeformat.js b/testing/web-platform/tests/editing/data/removeformat.js index 0ff0a76ce966..cfc355d88541 100644 --- a/testing/web-platform/tests/editing/data/removeformat.js +++ b/testing/web-platform/tests/editing/data/removeformat.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["removeformat",""]], diff --git a/testing/web-platform/tests/editing/data/strikethrough.js b/testing/web-platform/tests/editing/data/strikethrough.js index 97170708df32..9817f4f0f851 100644 --- a/testing/web-platform/tests/editing/data/strikethrough.js +++ b/testing/web-platform/tests/editing/data/strikethrough.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["strikethrough",""]], diff --git a/testing/web-platform/tests/editing/data/subscript.js b/testing/web-platform/tests/editing/data/subscript.js index af6ae8965408..212981438b64 100644 --- a/testing/web-platform/tests/editing/data/subscript.js +++ b/testing/web-platform/tests/editing/data/subscript.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["subscript",""]], diff --git a/testing/web-platform/tests/editing/data/superscript.js b/testing/web-platform/tests/editing/data/superscript.js index 337c70d30e7b..e06fe6f4b175 100644 --- a/testing/web-platform/tests/editing/data/superscript.js +++ b/testing/web-platform/tests/editing/data/superscript.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["superscript",""]], diff --git a/testing/web-platform/tests/editing/data/underline.js b/testing/web-platform/tests/editing/data/underline.js index 3414214386e0..4dac89f66e1c 100644 --- a/testing/web-platform/tests/editing/data/underline.js +++ b/testing/web-platform/tests/editing/data/underline.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["underline",""]], diff --git a/testing/web-platform/tests/editing/data/unlink.js b/testing/web-platform/tests/editing/data/unlink.js index 8e5ea4489abf..84f8600f1bc2 100644 --- a/testing/web-platform/tests/editing/data/unlink.js +++ b/testing/web-platform/tests/editing/data/unlink.js @@ -1,3 +1,4 @@ +// For documentation of the format, see README in this directory. var browserTests = [ ["foo[]bar", [["unlink",""]], diff --git a/testing/web-platform/tests/encrypted-media/content/content-metadata.js b/testing/web-platform/tests/encrypted-media/content/content-metadata.js index 8ba5bcf06c29..580cc2bdfe4e 100644 --- a/testing/web-platform/tests/encrypted-media/content/content-metadata.js +++ b/testing/web-platform/tests/encrypted-media/content/content-metadata.js @@ -81,29 +81,6 @@ content = addMemberListToObject( { initDataType: 'cenc', initData: 'AAAAjXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAG0IARIQ7nNWTsiokPB472hx+kvhixoIY2FzdGxhYnMiRGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRNbk5sYzNOcGIyNGlMQ0oyWVhKcFlXNTBTV1FpT2lKclpYa3lJbjA9MgdkZWZhdWx0AAADwnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAA6KiAwAAAQABAJgDPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBUAGwAWgB6ADcAcQBqAEkAOABKAEIANAA3ADIAaAB4ACsAawB2AGgAaQB3AD0APQA8AC8ASwBJAEQAPgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcABzADoALwAvAGwAaQBjAC4AcwB0AGEAZwBpAG4AZwAuAGQAcgBtAHQAbwBkAGEAeQAuAGMAbwBtAC8AbABpAGMAZQBuAHMAZQAtAHAAcgBvAHgAeQAtAGgAZQBhAGQAZQByAGEAdQB0AGgALwBkAHIAbQB0AG8AZABhAHkALwBSAGkAZwBoAHQAcwBNAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA8AC8ATABBAF8AVQBSAEwAPgA8AEwAVQBJAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAFUASQBfAFUAUgBMAD4APABDAEgARQBDAEsAUwBVAE0APgB4AEQASwBBAFkAMAB2AFoAaABVAFUAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=' } ] }, - 'mp4-basic-key1' : { assetId: 'mp4-multikey-sequential', - variantId: 'key1', - initDataType: 'cenc', - audio: { type: 'audio/mp4;codecs="mp4a.40.2"', - path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' }, - video: { type: 'video/mp4;codecs="avc1.4d401e"', - path: '/encrypted-media/content/video_512x288_h264-360k_multikey_key1_dashinit.mp4' }, - keys: [ { kid: [0x8a, 0x0d, 0x85, 0x45, 0x21, 0x05, 0xd4, 0x15, 0x35, 0x8f, 0xea, 0x8f, 0x68, 0xe6, 0xc1, 0x91], - key: [0x76, 0x6f, 0xab, 0xc1, 0x68, 0x3f, 0xf8, 0xef, 0x4e, 0x76, 0x00, 0x24, 0xc5, 0x23, 0x8f, 0x10], - initDataType: 'cenc', - initData: 'AAAAlXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAHUIARIQig2FRSEF1BU1j+qPaObBkRoIY2FzdGxhYnMiTGV5SmhjM05sZEVsa0lqb2liWEEwTFcxMWJIUnBhMlY1TFhObGNYVmxiblJwWVd3aUxDSjJZWEpwWVc1MFNXUWlPaUpyWlhreEluMD0yB2RlZmF1bHQAAANYcHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAADODgDAAABAAEALgM8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AFIAWQBVAE4AaQBnAFUAaABGAGQAUQAxAGoAKwBxAFAAYQBPAGIAQgBrAFEAPQA9ADwALwBLAEkARAA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwATABVAEkAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwBwAGwAYQB5AHIAZQBhAGQAeQAtAHUAaQAuAGUAeABhAG0AcABsAGUALgBjAG8AbQA8AC8ATABVAEkAXwBVAFIATAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AcQBOAEkAZQBiAFQAWABzAG8AcgBnAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A' } ] - }, - 'mp4-basic-key2' : { assetId: 'mp4-multikey-sequential', - variantId: 'key2', - initDataType: 'cenc', - audio: { type: 'audio/mp4;codecs="mp4a.40.2"', - path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' }, - video: { type: 'video/mp4;codecs="avc1.4d401e"', - path: '/encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4' }, - keys: [ { kid: [0xfb, 0xb4, 0xb7, 0xf3, 0x4a, 0xbd, 0x31, 0x87, 0x34, 0x4b, 0xce, 0xc4, 0x5f, 0x96, 0x68, 0x88], - key: [0x26, 0x52, 0xc3, 0x1d, 0xf7, 0x92, 0xd1, 0x7b, 0x08, 0xa6, 0xfa, 0xd3, 0x7c, 0xb6, 0x25, 0x60], - initDataType: 'cenc', - initData: 'AAAAlXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAHUIARIQ+7S380q9MYc0S87EX5ZoiBoIY2FzdGxhYnMiTGV5SmhjM05sZEVsa0lqb2liWEEwTFcxMWJIUnBhMlY1TFhObGNYVmxiblJwWVd3aUxDSjJZWEpwWVc1MFNXUWlPaUpyWlhreUluMD0yB2RlZmF1bHQAAANYcHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAADODgDAAABAAEALgM8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADgANwBlADAAKwA3ADEASwBoAHoARQAwAFMAOAA3AEUAWAA1AFoAbwBpAEEAPQA9ADwALwBLAEkARAA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwATABVAEkAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwBwAGwAYQB5AHIAZQBhAGQAeQAtAHUAaQAuAGUAeABhAG0AcABsAGUALgBjAG8AbQA8AC8ATABVAEkAXwBVAFIATAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4ARgB0AGkASQBoADYAUwBKAG0AcABZAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A' } ] }, 'mp4-multikey-sequential' : { assetId: 'mp4-multikey-sequential', initDataType: 'cenc', diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4 deleted file mode 100644 index 0b9b457a6b3a..000000000000 Binary files a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4 and /dev/null differ diff --git a/testing/web-platform/tests/eventsource/README.md b/testing/web-platform/tests/eventsource/README.md index 6b58a1ef51eb..60bbea3f3b97 100644 --- a/testing/web-platform/tests/eventsource/README.md +++ b/testing/web-platform/tests/eventsource/README.md @@ -1,54 +1,2 @@ -# Server-Sent Events Test Collection - -Server-Sent Events [latest draft](http://dev.w3.org/html5/eventsource/). - -Following up work done during the TestTWF 2012 Paris event: - -Most tests comes from [Opera](http://tc.labs.opera.com/apis/EventSource/), are from august 2010 and probably only valid against [spec rev. ~1.139](http://dev.w3.org/cvsweb/~checkout~/html5/eventsource/Overview.html?rev=1.139;content-type=text%2Fhtml). You can check the following diff : - -[diff between 1.139 (23 Jul 2010) and 1.229 (25 Oct. 2012) revisions](http://dev.w3.org/cvsweb/html5/eventsource/Overview.html.diff?r1=text&tr1=1.139&r2=text&tr2=1.229) - -to get an idea of what needs to get updated. - -##DONE (updated against rev. 1.229): -- **eventsource-constructor-url-bogus.htm**: whatwg r6602: renamed SYNTAX_ERR to SyntaxError - -- **eventsource-constructor-stringify.htm**: still valid. bugfix. - -##TODO (need to be updated against rev. 1.229): -- **eventsource-cross-origin.htm**, **eventsource-constructor-non-same-origin.htm**: whatwg 6255 6257: allow CORS - -##TOCHECK (need to check if the test is still valid against rev.1.229): -eventsource-close.htm -eventsource-constructor-document-domain.htm -eventsource-constructor-url-multi-window.htm -eventsource-eventtarget.htm -eventsource-onmessage.htm -eventsource-onopen.htm -eventsource-prototype.htm -eventsource-reconnect.htm -eventsource-url.htm -format-bom-2.htm -format-bom.htm -format-comments.htm -format-field-data.htm -format-field-event-empty.htm -format-field-event.htm -format-field-id-2.htm -format-field-id.htm -format-field-parsing.htm -format-field-retry-bogus.htm -format-field-retry-empty.htm -format-field-retry.htm -format-field-unknown.htm -format-leading-space.htm -format-mime-bogus.htm -format-mime-trailing-semicolon.htm -format-mime-valid-bogus.htm -format-newlines.htm -format-utf-8.htm -request-accept.htm -request-cache-control.htm -request-credentials.htm -request-redirect.htm -request-status-error.htm +These are the Server-sent events (`EventSource`) tests for the +[Server-sent events chapter of the HTML Standard](https://html.spec.whatwg.org/multipage/comms.html#server-sent-events). diff --git a/testing/web-platform/tests/fetch/api/basic/block-mime-as-script.html b/testing/web-platform/tests/fetch/api/basic/block-mime-as-script.html new file mode 100644 index 000000000000..37c38839d175 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/basic/block-mime-as-script.html @@ -0,0 +1,39 @@ + + +Block mime type as script + + +

+ diff --git a/testing/web-platform/tests/fetch/api/headers/headers-idl.html b/testing/web-platform/tests/fetch/api/headers/headers-idl.html index fe24fa34c6a5..078c9d014951 100644 --- a/testing/web-platform/tests/fetch/api/headers/headers-idl.html +++ b/testing/web-platform/tests/fetch/api/headers/headers-idl.html @@ -12,10 +12,10 @@ diff --git a/testing/web-platform/tests/geolocation-API/getCurrentPosition_permission_allow.https.html b/testing/web-platform/tests/geolocation-API/getCurrentPosition_permission_allow.https.html index dfadcb09d197..951710991594 100644 --- a/testing/web-platform/tests/geolocation-API/getCurrentPosition_permission_allow.https.html +++ b/testing/web-platform/tests/geolocation-API/getCurrentPosition_permission_allow.https.html @@ -14,31 +14,21 @@ var t = async_test('User allows access, check that success callback is called or error callback is called with correct code.'), onSuccess, onError, hasMethodReturned = false; -onSuccess = t.step_func(function(pos) { - // Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00031 - test(function() { +t.step(function() { + onSuccess = t.step_func_done(function(pos) { + // Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00031 assert_true(hasMethodReturned); - }, 'Check that getCurrentPosition returns synchronously before any callbacks are invoked.'); + }); - done(); -}); - -onError = t.step_func(function(err) { - // Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00031 - test(function() { + onError = t.step_func_done(function(err) { + // Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00031 assert_true(hasMethodReturned); - }, 'Check that getCurrentPosition returns synchronously before any callbacks are invoked.'); + assert_false(isUsingPreemptivePermission); + assert_equals(err.code, err.POSITION_UNAVAILABLE, errorToString(err)); + }); - assert_true(!isUsingPreemptivePermission && err.code === err.POSITION_UNAVAILABLE); - done(); -}); - -try { geo.getCurrentPosition(onSuccess, onError); hasMethodReturned = true; -} catch(e) { - t.step(function() { - assert_unreached('An exception was thrown unexpectedly: ' + e.message); - }); -} +}); + diff --git a/testing/web-platform/tests/geolocation-API/getCurrentPosition_permission_deny.https.html b/testing/web-platform/tests/geolocation-API/getCurrentPosition_permission_deny.https.html index 26fe8899eda0..50129608ac7e 100644 --- a/testing/web-platform/tests/geolocation-API/getCurrentPosition_permission_deny.https.html +++ b/testing/web-platform/tests/geolocation-API/getCurrentPosition_permission_deny.https.html @@ -15,20 +15,18 @@ var t = async_test('User denies access, check that error callback is called with onSuccess, onError, hasMethodReturned = false; t.step(function() { - onSuccess = t.step_func(function(pos) { + onSuccess = t.step_func_done(function(pos) { assert_unreached('A success callback was invoked unexpectedly with position ' + positionToString(pos)); }); - onError = t.step_func(function(err) { + onError = t.step_func_done(function(err) { // http://dev.w3.org/geo/api/test-suite/t.html?00031 assert_true(hasMethodReturned, 'Check that getCurrentPosition returns synchronously before any callbacks are invoked'); - assert_equals(err.code, err.PERMISSION_DENIED, - 'PossitionError code: ' + err.code, + ', message: ' + err.message); - done(); + assert_equals(err.code, err.PERMISSION_DENIED, errorToString(err)); }); geo.getCurrentPosition(onSuccess, onError); hasMethodReturned = true; }); - + diff --git a/testing/web-platform/tests/geolocation-API/support.js b/testing/web-platform/tests/geolocation-API/support.js index c85b5c87f91c..960b5721c376 100644 --- a/testing/web-platform/tests/geolocation-API/support.js +++ b/testing/web-platform/tests/geolocation-API/support.js @@ -2,7 +2,7 @@ var geo; setup(function() { geo = navigator.geolocation; -}, {explicit_done: true}); +}); // The spec states that an implementation SHOULD acquire user permission before // beggining the position acquisition steps. If an implementation follows this diff --git a/testing/web-platform/tests/geolocation-API/watchPosition_permission_deny.https.html b/testing/web-platform/tests/geolocation-API/watchPosition_permission_deny.https.html index 831a1544fdf6..1e2a3c4bf4c4 100644 --- a/testing/web-platform/tests/geolocation-API/watchPosition_permission_deny.https.html +++ b/testing/web-platform/tests/geolocation-API/watchPosition_permission_deny.https.html @@ -14,18 +14,15 @@ var t = async_test('Check that watchPosition returns synchronously before any callbacks are invoked.'), id, checkMethodHasReturned, hasMethodReturned = false; -checkMethodHasReturned = t.step_func(function() { +checkMethodHasReturned = t.step_func_done(function() { assert_true(hasMethodReturned); - done(); }); try { id = geo.watchPosition(checkMethodHasReturned, checkMethodHasReturned); hasMethodReturned = true; } catch(e) { - t.step(function() { - assert_unreached('An exception was thrown unexpectedly: ' + e.message); - }); + t.unreached_func('An exception was thrown unexpectedly: ' + e.message); } // Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00151 diff --git a/testing/web-platform/tests/gyroscope/Gyroscope.https.html b/testing/web-platform/tests/gyroscope/Gyroscope.https.html new file mode 100644 index 000000000000..8435912fb079 --- /dev/null +++ b/testing/web-platform/tests/gyroscope/Gyroscope.https.html @@ -0,0 +1,16 @@ + + +Gyroscope Test + + + + + +
+ + diff --git a/testing/web-platform/tests/gyroscope/Gyroscope_insecure_context.html b/testing/web-platform/tests/gyroscope/Gyroscope_insecure_context.html new file mode 100644 index 000000000000..f772b0a25405 --- /dev/null +++ b/testing/web-platform/tests/gyroscope/Gyroscope_insecure_context.html @@ -0,0 +1,20 @@ + + +Gyroscope Test: insecure context + + + + + +
+

Precondition

+
    +
  1. + Run test in an insecure context, e.g. http://example.com/. +
  2. +
+ diff --git a/testing/web-platform/tests/gyroscope/Gyroscope_onerror-manual.https.html b/testing/web-platform/tests/gyroscope/Gyroscope_onerror-manual.https.html new file mode 100644 index 000000000000..f0126151a24a --- /dev/null +++ b/testing/web-platform/tests/gyroscope/Gyroscope_onerror-manual.https.html @@ -0,0 +1,20 @@ + + +Gyroscope Test: onerror + + + + + +
+

Precondition

+
    +
  1. + Disable the Gyroscope Sensor or run test on a device without Gyroscope Sensor. +
  2. +
+ diff --git a/testing/web-platform/tests/gyroscope/idlharness.https.html b/testing/web-platform/tests/gyroscope/idlharness.https.html index 53d3b81cce6d..da1f67b65835 100644 --- a/testing/web-platform/tests/gyroscope/idlharness.https.html +++ b/testing/web-platform/tests/gyroscope/idlharness.https.html @@ -2,7 +2,8 @@ Gyroscope Sensor IDL tests - + + @@ -18,24 +19,24 @@ interface Event { }; -interface EventTarget { -}; - -interface EventHandler { -}; - interface Error { }; dictionary EventInit { }; + +interface EventTarget { +}; + +interface EventHandler { +};
 [SecureContext]
 interface Sensor : EventTarget {
-  readonly attribute SensorState state;
-  readonly attribute SensorReading? reading;
+  readonly attribute boolean activated;
+  readonly attribute DOMHighResTimeStamp? timestamp;
   void start();
   void stop();
   attribute EventHandler onchange;
@@ -47,18 +48,6 @@ dictionary SensorOptions {
   double? frequency;
 };
 
-enum SensorState {
-  "idle",
-  "activating",
-  "activated",
-  "errored"
-};
-
-[SecureContext]
-interface SensorReading {
-  readonly attribute DOMHighResTimeStamp timeStamp;
-};
-
 [SecureContext, Constructor(DOMString type, SensorErrorEventInit errorEventInitDict)]
 interface SensorErrorEvent : Event {
   readonly attribute Error error;
@@ -67,42 +56,31 @@ interface SensorErrorEvent : Event {
 dictionary SensorErrorEventInit : EventInit {
   required Error error;
 };
-
 
 [Constructor(optional SensorOptions sensorOptions)]
 interface Gyroscope : Sensor {
-  readonly attribute GyroscopeReading? reading;
-};
-
-[Constructor(GyroscopeReadingInit GyroscopeReadingInit)]
-interface GyroscopeReading : SensorReading {
-    readonly attribute unrestricted double x;
-    readonly attribute unrestricted double y;
-    readonly attribute unrestricted double z;
-};
-
-dictionary GyroscopeReadingInit {
-    unrestricted double x = 0;
-    unrestricted double y = 0;
-    unrestricted double z = 0;
+  readonly attribute unrestricted double? x;
+  readonly attribute unrestricted double? y;
+  readonly attribute unrestricted double? z;
 };
 
diff --git a/testing/web-platform/tests/gyroscope/support-iframe.html b/testing/web-platform/tests/gyroscope/support-iframe.html new file mode 100644 index 000000000000..5efbbcd54cfa --- /dev/null +++ b/testing/web-platform/tests/gyroscope/support-iframe.html @@ -0,0 +1,10 @@ + + + diff --git a/testing/web-platform/tests/html-media-capture/capture_audio-manual.html b/testing/web-platform/tests/html-media-capture/capture_audio-manual.html index a1f0c3716ef8..d9eb11aac4aa 100644 --- a/testing/web-platform/tests/html-media-capture/capture_audio-manual.html +++ b/testing/web-platform/tests/html-media-capture/capture_audio-manual.html @@ -2,8 +2,8 @@ HTML Media Capture Test: capture audio to produce one audio file - - + + diff --git a/testing/web-platform/tests/html-media-capture/capture_audio_cancel-manual.html b/testing/web-platform/tests/html-media-capture/capture_audio_cancel-manual.html index 73e486000d47..7c70d29364cc 100644 --- a/testing/web-platform/tests/html-media-capture/capture_audio_cancel-manual.html +++ b/testing/web-platform/tests/html-media-capture/capture_audio_cancel-manual.html @@ -2,8 +2,8 @@ HTML Media Capture Test: user denial of captured audio leading to no capture - - + +

Clear all microphone permissions before running this test. If prompted for permission, please allow.

diff --git a/testing/web-platform/tests/html-media-capture/capture_fallback_file_upload-manual.html b/testing/web-platform/tests/html-media-capture/capture_fallback_file_upload-manual.html index 2d25aa14f84a..d0e0678f5d43 100644 --- a/testing/web-platform/tests/html-media-capture/capture_fallback_file_upload-manual.html +++ b/testing/web-platform/tests/html-media-capture/capture_fallback_file_upload-manual.html @@ -4,8 +4,8 @@ HTML Media Capture Test: capture_fallback_file_upload - - + + diff --git a/testing/web-platform/tests/html-media-capture/capture_image_cancel-manual.html b/testing/web-platform/tests/html-media-capture/capture_image_cancel-manual.html index fafb5d5118fd..42137b999136 100644 --- a/testing/web-platform/tests/html-media-capture/capture_image_cancel-manual.html +++ b/testing/web-platform/tests/html-media-capture/capture_image_cancel-manual.html @@ -2,8 +2,8 @@ HTML Media Capture Test: user denial of captured image leading to no capture - - + +

Clear all camera permissions before running this test. If prompted for permission, please allow.

diff --git a/testing/web-platform/tests/html-media-capture/capture_image_environment-manual.html b/testing/web-platform/tests/html-media-capture/capture_image_environment-manual.html new file mode 100644 index 000000000000..b974222713d2 --- /dev/null +++ b/testing/web-platform/tests/html-media-capture/capture_image_environment-manual.html @@ -0,0 +1,41 @@ + + +HTML Media Capture Test: capture image with 'environment' facing mode to produce one image file + + + + + + + + +

Clear all camera permissions before running this test. If prompted for permission, please allow.

+ +

After hitting the button below, the camera must be launched with viewing the environment mode.

+ +

(Note: If the user agent is unable to support the preferred facing mode, it can fall back to the implementation-specific default facing mode.)

+ +

Capture an image and then confirm the capturing.

+ +

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

+ + + +
+ + + diff --git a/testing/web-platform/tests/html-media-capture/capture_image_invalid-manual.html b/testing/web-platform/tests/html-media-capture/capture_image_invalid-manual.html new file mode 100644 index 000000000000..eb416e009dde --- /dev/null +++ b/testing/web-platform/tests/html-media-capture/capture_image_invalid-manual.html @@ -0,0 +1,39 @@ + + +HTML Media Capture Test: capture image with implementation-specific default facing mode(invalid value default) to produce one image file + + + + + + + + +

Clear all camera permissions before running this test. If prompted for permission, please allow.

+ +

After hitting the button below, the camera must be launched with the default facing mode.

+ +

Capture an image and then confirm the capturing.

+ +

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

+ + + +
+ + + diff --git a/testing/web-platform/tests/html-media-capture/capture_image-manual.html b/testing/web-platform/tests/html-media-capture/capture_image_missing-manual.html similarity index 68% rename from testing/web-platform/tests/html-media-capture/capture_image-manual.html rename to testing/web-platform/tests/html-media-capture/capture_image_missing-manual.html index 1b15fb3691f0..405f69a24459 100644 --- a/testing/web-platform/tests/html-media-capture/capture_image-manual.html +++ b/testing/web-platform/tests/html-media-capture/capture_image_missing-manual.html @@ -1,9 +1,9 @@ -HTML Media Capture Test: capture image to produce one image file +HTML Media Capture Test: capture image with implementation-specific default facing mode(missing value default) to produce one image file - - + + @@ -11,7 +11,9 @@

Clear all camera permissions before running this test. If prompted for permission, please allow.

-

After hitting the button below, capture an image and then confirm the capturing.

+

After hitting the button below, the camera must be launched with the default facing mode.

+ +

Capture an image and then confirm the capturing.

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

diff --git a/testing/web-platform/tests/html-media-capture/capture_image_user-manual.html b/testing/web-platform/tests/html-media-capture/capture_image_user-manual.html new file mode 100644 index 000000000000..a2d8c0ecca3d --- /dev/null +++ b/testing/web-platform/tests/html-media-capture/capture_image_user-manual.html @@ -0,0 +1,41 @@ + + +HTML Media Capture Test: capture image with 'user' facing mode to produce one image file + + + + + + + + +

Clear all camera permissions before running this test. If prompted for permission, please allow.

+ +

After hitting the button below, the camera must be launched with self-view mode.

+ +

(Note: If the user agent is unable to support the preferred facing mode, it can fall back to the implementation-specific default facing mode.)

+ +

Capture an image and then confirm the capturing.

+ +

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

+ + + +
+ + + diff --git a/testing/web-platform/tests/html-media-capture/capture_reflect.html b/testing/web-platform/tests/html-media-capture/capture_reflect.html index 6dd40cc9b0ea..39f391eb674d 100644 --- a/testing/web-platform/tests/html-media-capture/capture_reflect.html +++ b/testing/web-platform/tests/html-media-capture/capture_reflect.html @@ -4,9 +4,7 @@ HTML Media Capture Test: capture_reflect - - - + @@ -15,43 +13,52 @@
       partial interface HTMLInputElement {
-                attribute boolean capture;
+        attribute CaptureFacingMode capture;
+      };
+      enum CaptureFacingMode {
+        "user",
+        "environment"
       };
     
- - - + + + +
diff --git a/testing/web-platform/tests/html-media-capture/capture_video_cancel-manual.html b/testing/web-platform/tests/html-media-capture/capture_video_cancel-manual.html index 645473701c83..45aee19f4815 100644 --- a/testing/web-platform/tests/html-media-capture/capture_video_cancel-manual.html +++ b/testing/web-platform/tests/html-media-capture/capture_video_cancel-manual.html @@ -2,8 +2,8 @@ HTML Media Capture Test: user denial of captured video leading to no capture - - + +

Clear all camera/microphone permissions before running this test. If prompted for permission, please allow.

diff --git a/testing/web-platform/tests/html-media-capture/capture_video_environment-manual.html b/testing/web-platform/tests/html-media-capture/capture_video_environment-manual.html new file mode 100644 index 000000000000..03a691e8a61b --- /dev/null +++ b/testing/web-platform/tests/html-media-capture/capture_video_environment-manual.html @@ -0,0 +1,41 @@ + + +HTML Media Capture Test: capture video with 'environment' facing mode to produce one video file + + + + + + + + +

Clear all camera/microphone permissions before running this test. If prompted for permission, please allow.

+ +

After hitting the button below, the camera must be launched with viewing the environment mode.

+ +

(Note: If the user agent is unable to support the preferred facing mode, it can fall back to the implementation-specific default facing mode.)

+ +

Capture a video and then confirm the capturing.

+ +

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

+ + + +
+ + + diff --git a/testing/web-platform/tests/html-media-capture/capture_video_invalid-manual.html b/testing/web-platform/tests/html-media-capture/capture_video_invalid-manual.html new file mode 100644 index 000000000000..f6c0c3510ed8 --- /dev/null +++ b/testing/web-platform/tests/html-media-capture/capture_video_invalid-manual.html @@ -0,0 +1,39 @@ + + +HTML Media Capture Test: capture video with implementation-specific default facing mode(invalid value default) to produce one video file + + + + + + + + +

Clear all camera/microphone permissions before running this test. If prompted for permission, please allow.

+ +

After hitting the button below, the camera must be launched with the default facing mode.

+ +

Capture an video and then confirm the capturing.

+ +

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

+ + + +
+ + + diff --git a/testing/web-platform/tests/html-media-capture/capture_video-manual.html b/testing/web-platform/tests/html-media-capture/capture_video_missing-manual.html similarity index 68% rename from testing/web-platform/tests/html-media-capture/capture_video-manual.html rename to testing/web-platform/tests/html-media-capture/capture_video_missing-manual.html index b54abae0eb53..ed637445758a 100644 --- a/testing/web-platform/tests/html-media-capture/capture_video-manual.html +++ b/testing/web-platform/tests/html-media-capture/capture_video_missing-manual.html @@ -1,9 +1,9 @@ -HTML Media Capture Test: capture video to produce one video file +HTML Media Capture Test: capture video with implementation-specific default facing mode(missing value default) to produce one video file - - + + @@ -11,7 +11,9 @@

Clear all camera/microphone permissions before running this test. If prompted for permission, please allow.

-

After hitting the button below, capture an video and then confirm the capturing.

+

After hitting the button below, the camera must be launched with the default facing mode.

+ +

Capture an video and then confirm the capturing.

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

diff --git a/testing/web-platform/tests/html-media-capture/capture_video_user-manual.html b/testing/web-platform/tests/html-media-capture/capture_video_user-manual.html new file mode 100644 index 000000000000..47a6732ecf5f --- /dev/null +++ b/testing/web-platform/tests/html-media-capture/capture_video_user-manual.html @@ -0,0 +1,41 @@ + + +HTML Media Capture Test: capture video with 'user' facing mode to produce one video file + + + + + + + + +

Clear all camera/microphone permissions before running this test. If prompted for permission, please allow.

+ +

After hitting the button below, the camera must be launched with self-view mode.

+ +

(Note: If the user agent is unable to support the preferred facing mode, it can fall back to the implementation-specific default facing mode.)

+ +

Capture a video and then confirm the capturing.

+ +

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

+ + + +
+ + + diff --git a/testing/web-platform/tests/html-media-capture/idlharness.html b/testing/web-platform/tests/html-media-capture/idlharness.html index a204764ae873..22b3e05ee9df 100644 --- a/testing/web-platform/tests/html-media-capture/idlharness.html +++ b/testing/web-platform/tests/html-media-capture/idlharness.html @@ -4,8 +4,7 @@ HTML Media Capture IDL tests - - + @@ -26,12 +25,16 @@
- +
+ + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_iframe.html b/testing/web-platform/tests/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_iframe.html new file mode 100644 index 000000000000..d3d5260af3f1 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_iframe.html @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-innerwidth-innerheight.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-innerwidth-innerheight.html new file mode 100644 index 000000000000..7f55f1bb1d80 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-innerwidth-innerheight.html @@ -0,0 +1,75 @@ + + +HTML: window.open `features`: negative values for legacy `innerwidth`, `innerheight` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-screenx-screeny.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-screenx-screeny.html new file mode 100644 index 000000000000..09fb2d6b0a5a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-screenx-screeny.html @@ -0,0 +1,67 @@ + + +HTML: window.open `features`: negative values for legacy `screenx`, `screeny` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-top-left.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-top-left.html new file mode 100644 index 000000000000..15b3103db3cc --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-top-left.html @@ -0,0 +1,68 @@ + + +HTML: window.open `features`: negative values for `top`, `left` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-width-height.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-width-height.html new file mode 100644 index 000000000000..30b70926f2c7 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-width-height.html @@ -0,0 +1,75 @@ + + +HTML: window.open `features`: negative values for `width`, `height` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-height.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-height.html new file mode 100644 index 000000000000..08d127e84b1d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-height.html @@ -0,0 +1,91 @@ + + +HTML: window.open `features`: non-integer values for feature `height` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerheight.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerheight.html new file mode 100644 index 000000000000..5ee752caedc8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerheight.html @@ -0,0 +1,76 @@ + + +HTML: window.open `features`: non-integer values for legacy feature `innerheight` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerwidth.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerwidth.html new file mode 100644 index 000000000000..972beef48abb --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerwidth.html @@ -0,0 +1,75 @@ + + +HTML: window.open `features`: non-integer values for legacy feature `innerwidth` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-left.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-left.html new file mode 100644 index 000000000000..fbb2a30ee226 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-left.html @@ -0,0 +1,76 @@ + + +HTML: window.open `features`: non-integer values for feature `left` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screenx.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screenx.html new file mode 100644 index 000000000000..2aeab9bb796e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screenx.html @@ -0,0 +1,75 @@ + + +HTML: window.open `features`: non-integer values for legacy feature `screenx` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screeny.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screeny.html new file mode 100644 index 000000000000..cb4e873f26d0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screeny.html @@ -0,0 +1,76 @@ + + +HTML: window.open `features`: non-integer values for legacy feature `screeny` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-top.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-top.html new file mode 100644 index 000000000000..d4f4e90d96ed --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-top.html @@ -0,0 +1,73 @@ + + +HTML: window.open `features`: non-integer values for feature `top` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-width.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-width.html new file mode 100644 index 000000000000..a746abed3f36 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-width.html @@ -0,0 +1,91 @@ + + +HTML: window.open `features`: non-integer values for feature `width` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-innerheight-innerwidth.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-innerheight-innerwidth.html new file mode 100644 index 000000000000..c839c6ca0661 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-innerheight-innerwidth.html @@ -0,0 +1,55 @@ + + +HTML: window.open `features`: tokenization -- legacy size features `innerheight`, `innerwidth` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-noopener.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-noopener.html new file mode 100644 index 000000000000..cac23648ade4 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-noopener.html @@ -0,0 +1,150 @@ + + +HTML: window.open `features`: tokenization -- `noopener` + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-screenx-screeny.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-screenx-screeny.html new file mode 100644 index 000000000000..bb6fc4b84bfb --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-screenx-screeny.html @@ -0,0 +1,55 @@ + + +HTML: window.open `features`: tokenization -- legacy position features `screenx`, `screeny` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-top-left.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-top-left.html new file mode 100644 index 000000000000..ef098a1062c6 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-top-left.html @@ -0,0 +1,69 @@ + + +HTML: window.open `features`: tokenization -- position features `top` and `left` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-width-height.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-width-height.html new file mode 100644 index 000000000000..cac4ae639b2f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-width-height.html @@ -0,0 +1,71 @@ + + +HTML: window.open `features`: tokenization -- size features `width` and `height` + + + + + + + + + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/close-self.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/close-self.html new file mode 100644 index 000000000000..0c0cf9fc4911 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/close-self.html @@ -0,0 +1,3 @@ + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/message-opener.html b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/message-opener.html new file mode 100644 index 000000000000..e6c164bfae53 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/resources/message-opener.html @@ -0,0 +1,12 @@ + + diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-strict.html b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-strict.html index 610941fc8794..e059b1226165 100644 --- a/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-strict.html +++ b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-strict.html @@ -23,15 +23,24 @@ test(function() { assert_throws(new TypeError(), function() { window[0] = "foo"; }); + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { value: "bar" })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { get() { return "baz" } })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { set(v) { return "qux" } })) assert_equals(window[0], document.getElementsByTagName("iframe")[0].contentWindow); + assert_throws(new TypeError(), () => delete window[0]); }); test(function() { "use strict"; assert_throws(new TypeError(), function() { window[1] = "foo"; }); + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { value: "bar" })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { get() { return "baz" } })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { set(v) { return "qux" } })) assert_equals(window[1], undefined); + assert_equals(Object.getOwnPropertyDescriptor(window, 1), undefined); + assert_equals(delete window[1], true); }); test(function() { "use strict"; diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties.html b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties.html index 9577ab8fbce9..17d0eb729ae1 100644 --- a/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties.html +++ b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties.html @@ -19,12 +19,21 @@ test(function() { }); test(function() { window[0] = "foo"; + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { value: "bar" })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { get() { return "baz" } })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { set() { return "quz" } })) assert_equals(window[0], document.getElementsByTagName("iframe")[0].contentWindow); + assert_equals(delete window[0], false); }); test(function() { window[1] = "foo"; + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { value: "bar" })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { get() { return "baz" } })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { set(v) { return "quz" } })) assert_equals(window[1], undefined); + assert_equals(Object.getOwnPropertyDescriptor(window, 1), undefined); + assert_equals(delete window[1], true); }); test(function() { var proto = Window.prototype; diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/001-1.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/001-1.html deleted file mode 100644 index d413c3019ff1..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/001-1.html +++ /dev/null @@ -1,8 +0,0 @@ - -001-1 - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/001.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/001.html deleted file mode 100644 index 2478cdc8fac1..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/001.html +++ /dev/null @@ -1,22 +0,0 @@ - -Link with target=_blank, rel=noreferrer - - -
-Link - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/002-1.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/002-1.html deleted file mode 100644 index ca8a485de613..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/002-1.html +++ /dev/null @@ -1,8 +0,0 @@ - -002-1 - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/002.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/002.html deleted file mode 100644 index 4a1df8e4d039..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/002.html +++ /dev/null @@ -1,25 +0,0 @@ - -Link with target=_blank, no rel - - -
-Link - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html deleted file mode 100644 index 2eaba22f6fa8..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html +++ /dev/null @@ -1,25 +0,0 @@ - - -HTML Test: Choose browsing context - the given name is same as an existing browsing context's name - - - -
- - - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-004.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-004.html deleted file mode 100644 index ca98f66d1723..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-004.html +++ /dev/null @@ -1,16 +0,0 @@ - - -HTML Test: Choose browsing context - '_parent' (case-sensitivity) - - -
- - - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html deleted file mode 100644 index 99d7fe7d3feb..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html +++ /dev/null @@ -1,20 +0,0 @@ - - -HTML Test: Choose browsing context - the given name is '_self' - - - -
- - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html deleted file mode 100644 index e25a5b44240b..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html +++ /dev/null @@ -1,20 +0,0 @@ - - -HTML Test: Choose browsing context - the given name is empty string - - - -
- - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-_blank.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_blank-001.html similarity index 100% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-_blank.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_blank-001.html diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_blank-002.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_blank-002.html new file mode 100644 index 000000000000..aba9d52ba097 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_blank-002.html @@ -0,0 +1,21 @@ + +Link with target=_blank, rel=noreferrer + + + +
+Link + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_blank-003.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_blank-003.html new file mode 100644 index 000000000000..6912300ab2d9 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_blank-003.html @@ -0,0 +1,20 @@ + +Link with target=_blank, no rel + + + +
+Link + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-001.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-001.html similarity index 81% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-001.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-001.html index e1495beb8b18..35cbc101c7b3 100644 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-001.html +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-001.html @@ -12,4 +12,4 @@ async_test(t => { })); }, 'The parent browsing context must be chosen if the given name is `_parent`'); - + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-002.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-002.html similarity index 87% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-002.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-002.html index 9cdef8349f38..7b7d561030e5 100644 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-002.html +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-002.html @@ -12,6 +12,6 @@ async_test(t => { assert_equals(e.data.name, 'iframeParent'); assert_false(e.data.isTop, 'window.parent is not top'); })); - topWindow = window.open('resources/parent-top.html', '_blank'); + topWindow = window.open('resources/choose-_parent-002-window.html', '_blank'); }, 'choosing _parent context: multiple nested contexts'); diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-003.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-003.html similarity index 85% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-003.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-003.html index f0a165e6844c..20dc9b0d2ac4 100644 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent-003.html +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-003.html @@ -12,6 +12,6 @@ async_test(t => { assert_equals(e.data.name, 'parentTopReplace'); assert_equals(e.data.isTop, true); })); - topWindow = window.open('resources/parent-top-replace.html', 'parentTopReplace'); + topWindow = window.open('resources/choose-_parent-003-window.html', 'parentTopReplace'); }, '_parent should reuse window.parent context'); diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-004.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-004.html new file mode 100644 index 000000000000..c79378018a37 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_parent-004.html @@ -0,0 +1,40 @@ + + +HTML Test: Choose browsing context - '_parent' (case-sensitivity) + + + + +
+ + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_self-001.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_self-001.html new file mode 100644 index 000000000000..ed7666846d5c --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_self-001.html @@ -0,0 +1,15 @@ + + +HTML Test: Choose browsing context - the given name is '_self' + + + +
+ + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_self-002.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_self-002.html new file mode 100644 index 000000000000..2e798f5493f9 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_self-002.html @@ -0,0 +1,46 @@ + + +HTML Test: Choose browsing context - '_self' (case-sensitivity) + + + + +
+ + + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_top-001.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_top-001.html new file mode 100644 index 000000000000..de4c6ad115e8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_top-001.html @@ -0,0 +1,34 @@ + +HTML Test: Browsing context name - _top (current is top) + + + +
+ diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_top-002.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_top-002.html new file mode 100644 index 000000000000..f29da80c6eef --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_top-002.html @@ -0,0 +1,33 @@ + +HTML Test: Browsing context name - _top + + + +
+ diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_top-003.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_top-003.html new file mode 100644 index 000000000000..e068f8cc1fbb --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-_top-003.html @@ -0,0 +1,39 @@ + + +HTML Test: Choose browsing context - '_top' (case-sensitivity) + + + + +
+ + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-default-name.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-default-001.html similarity index 84% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-default-name.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-default-001.html index 470e244643cf..c21159e0a618 100644 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/browsing-context-default-name.html +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-default-001.html @@ -20,10 +20,4 @@ test(t => { assert_equals(win.name, ""); win.close(); }, "A browsing context which is opened by window.open() method with '_blank' parameter has empty-string default name"); - -//This test must be run when the current browsing context's name is not set -test(t => { - assert_equals(window.name, ""); -}, "A browsing context has an empty-string default name"); - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-default-002.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-default-002.html new file mode 100644 index 000000000000..748ee6897318 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-default-002.html @@ -0,0 +1,16 @@ + + +HTML Test: Browsing context names - empty string + + + +
+ + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-existing-001.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-existing-001.html new file mode 100644 index 000000000000..fdf74b8a797b --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/choose-existing-001.html @@ -0,0 +1,17 @@ + + +HTML Test: Choose browsing context - the given name is same as an existing browsing context's name + + + +
+ + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-1.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-001-iframe-1.html similarity index 77% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-1.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-001-iframe-1.html index 3d7accffd780..04dd74f1a53b 100644 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-1.html +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-001-iframe-1.html @@ -2,4 +2,4 @@ HTML Test: browsing context name - parent - + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-top-nested.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-002-iframe.html similarity index 63% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-top-nested.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-002-iframe.html index ffe351132339..52da8986b0ad 100644 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-top-nested.html +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-002-iframe.html @@ -1,4 +1,4 @@ HTML Test: browsing context name - parent: nested context - + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-top.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-002-window.html similarity index 80% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-top.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-002-window.html index 6ad72f969be9..558193742f68 100644 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-top.html +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-002-window.html @@ -1,7 +1,7 @@ HTML Test: browsing context name - parent: top-level context - + + + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-004-iframe-2.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-004-iframe-2.html new file mode 100644 index 000000000000..33ead5a53856 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_parent-004-iframe-2.html @@ -0,0 +1,9 @@ + + +HTML Test: browsing context name - parent (case-insensitive) + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/self2.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_self-001-iframe.html similarity index 68% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/self2.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_self-001-iframe.html index b3b4f59b5359..0ad79d6e1640 100644 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/self2.html +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_self-001-iframe.html @@ -3,9 +3,7 @@ HTML Test: browsing context name - self diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_self-002-iframe.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_self-002-iframe.html new file mode 100644 index 000000000000..9d88305e09da --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_self-002-iframe.html @@ -0,0 +1,11 @@ + + +HTML Test: browsing context name - self (case-insensitive) + + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_top-002-window.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_top-002-window.html new file mode 100644 index 000000000000..d71384b72f69 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_top-002-window.html @@ -0,0 +1,16 @@ + + + +HTML Test: browsing context name - _top + + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-1.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-1.html new file mode 100644 index 000000000000..aecc2fd88a2c --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-1.html @@ -0,0 +1,15 @@ + + +HTML Test: browsing context name - top (case-insensitive) + + + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-2.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-2.html new file mode 100644 index 000000000000..a1a7e1dda7ee --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-_top-003-iframe-2.html @@ -0,0 +1,10 @@ + + +HTML Test: browsing context name - top (case-insensitive) + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-default-002-iframe.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-default-002-iframe.html new file mode 100644 index 000000000000..567e4ea3103f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-default-002-iframe.html @@ -0,0 +1,17 @@ + + + +HTML Test: browsing context name - Empty string + + + + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/existing.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-existing-001-iframe.html similarity index 65% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/existing.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-existing-001-iframe.html index 6023319cebfd..cb0b554854fe 100644 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/existing.html +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/choose-existing-001-iframe.html @@ -3,9 +3,5 @@ This is a test page diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-2.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/open-in-_parent.html similarity index 100% rename from testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-2.html rename to testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/open-in-_parent.html diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/open-in-_top.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/open-in-_top.html new file mode 100644 index 000000000000..929d52d15e27 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/open-in-_top.html @@ -0,0 +1,9 @@ + + + +HTML Test: browsing context name - _top + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-1.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-1.html deleted file mode 100644 index 8ddbf44a3b5e..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-1.html +++ /dev/null @@ -1,4 +0,0 @@ - - -HTML Test: browsing context name - parent - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-2.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-2.html deleted file mode 100644 index 38d6b2f42848..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/parent-iframe-insensitive-2.html +++ /dev/null @@ -1,8 +0,0 @@ - - -HTML Test: browsing context name - parent (case-insensitive) - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/post-to-top-or-close.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/post-to-top-or-close.html deleted file mode 100644 index 2ccb6731d7ba..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/post-to-top-or-close.html +++ /dev/null @@ -1,16 +0,0 @@ - - -HTML Test: post window's name to top browsing context - - diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/report-has-opener.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/report-has-opener.html new file mode 100644 index 000000000000..37d8cedc6da4 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/report-has-opener.html @@ -0,0 +1,8 @@ + + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/report-is-top.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/report-is-top.html new file mode 100644 index 000000000000..871123598232 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/resources/report-is-top.html @@ -0,0 +1,10 @@ + + + + diff --git a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/self1.html b/testing/web-platform/tests/html/browsers/windows/browsing-context-names/self1.html deleted file mode 100644 index d72df6f86420..000000000000 --- a/testing/web-platform/tests/html/browsers/windows/browsing-context-names/self1.html +++ /dev/null @@ -1,11 +0,0 @@ - - -HTML Test: browsing context name - self - - diff --git a/testing/web-platform/tests/html/dom/elements-metadata.js b/testing/web-platform/tests/html/dom/elements-metadata.js index 73cbfc1a4542..7c4d373b8005 100644 --- a/testing/web-platform/tests/html/dom/elements-metadata.js +++ b/testing/web-platform/tests/html/dom/elements-metadata.js @@ -12,7 +12,12 @@ var metadataElements = { crossOrigin: {type: "enum", keywords: ["anonymous", "use-credentials"], nonCanon:{"": "anonymous"}, isNullable: true, defaultVal: null, invalidVal: "anonymous"}, rel: "string", relList: {type: "tokenlist", domAttrName: "rel"}, - // as: {}, XXX TODO: reflecting IDL attribute is an IDL enumeration + as: { + type: "enum", + keywords: ["", "audio", "document", "embed", "font", "image", "manifest", "object", "report", "script", "serviceworker", "sharedworker", "style", "track", "video", "worker", "xslt"], + defaultVal: "", + invalidVal: "" + }, media: "string", nonce: "string", integrity: "string", diff --git a/testing/web-platform/tests/html/dom/elements-tabular.js b/testing/web-platform/tests/html/dom/elements-tabular.js index bb54ade30565..ee66f7a47b6e 100644 --- a/testing/web-platform/tests/html/dom/elements-tabular.js +++ b/testing/web-platform/tests/html/dom/elements-tabular.js @@ -68,8 +68,8 @@ var tabularElements = { }, td: { // HTMLTableCellElement (Conforming) - colSpan: {type: "unsigned long", defaultVal: 1}, - rowSpan: {type: "unsigned long", defaultVal: 1}, + colSpan: {type: "clamped unsigned long", defaultVal: 1, min: 1, max: 1000}, + rowSpan: {type: "clamped unsigned long", defaultVal: 1, min: 0, max: 65534}, headers: "settable tokenlist", scope: {type: "enum", keywords: ["row", "col", "rowgroup", "colgroup"]}, abbr: "string", @@ -87,8 +87,8 @@ var tabularElements = { }, th: { // HTMLTableCellElement (Conforming) - colSpan: {type: "unsigned long", defaultVal: 1}, - rowSpan: {type: "unsigned long", defaultVal: 1}, + colSpan: {type: "clamped unsigned long", defaultVal: 1, min: 1, max: 1000}, + rowSpan: {type: "clamped unsigned long", defaultVal: 1, min: 0, max: 65534}, headers: "settable tokenlist", scope: {type: "enum", keywords: ["row", "col", "rowgroup", "colgroup"]}, abbr: "string", diff --git a/testing/web-platform/tests/html/dom/interfaces.html b/testing/web-platform/tests/html/dom/interfaces.html index dc751e0f2dcb..84406156e8ac 100644 --- a/testing/web-platform/tests/html/dom/interfaces.html +++ b/testing/web-platform/tests/html/dom/interfaces.html @@ -30,10 +30,10 @@ function createInput(type) { return input; } -function doTest([untested, tested]) { +function doTest([html, dom, cssom, uievents, touchevents]) { var idlArray = new IdlArray(); - idlArray.add_untested_idls(untested); - idlArray.add_idls(tested); + idlArray.add_untested_idls(dom + cssom + uievents + touchevents); + idlArray.add_idls(html); idlArray.add_objects({ NodeList: ['document.getElementsByName("name")'], @@ -227,8 +227,11 @@ function waitForLoad() { promise_test(function() { // Have to wait for onload - return Promise.all([fetchData("resources/untested-interfaces.idl"), - fetchData("resources/interfaces.idl"), + return Promise.all([fetchData("/interfaces/html.idl"), + fetchData("/interfaces/dom.idl"), + fetchData("/interfaces/cssom.idl"), + fetchData("/interfaces/touchevents.idl"), + fetchData("/interfaces/uievents.idl"), waitForLoad()]) .then(doTest); }, "Test driver"); diff --git a/testing/web-platform/tests/html/dom/reflection.js b/testing/web-platform/tests/html/dom/reflection.js index e3ff41574c49..b50e99b247ed 100644 --- a/testing/web-platform/tests/html/dom/reflection.js +++ b/testing/web-platform/tests/html/dom/reflection.js @@ -454,6 +454,37 @@ ReflectionTests.typeMap = { "idlTests": [0, 1, maxInt, maxInt + 1, maxUnsigned], "idlDomExpected": [null, 1, maxInt, null, null] }, + /** + * "If a reflecting IDL attribute has an unsigned integer type (unsigned + * long) that is clamped to the range [min, max], then on getting, the + * content attribute must first be parsed according to the rules for + * parsing non-negative integers, and if that is successful, and the value + * is between min and max inclusive, the resulting value must be returned. + * If it fails, the default value must be returned. If it succeeds but the + * value is less than min, min must be returned. If it succeeds but the + * value is greater than max, max must be returned. On setting, it behaves + * the same as a regular reflected unsigned integer." + * + * The data object passed to reflects must contain the keys defaultVal, + * min, and max. As with enum, domExpected is generated later once we have + * access to the min and max. + */ + "clamped unsigned long": { + "jsType": "number", + "domTests": [minInt - 1, minInt, -36, -1, 0, 1, maxInt, + maxInt + 1, maxUnsigned, maxUnsigned + 1, "", "-1", "-0", "0", "1", + "\u00097", "\u000B7", "\u000C7", "\u00207", "\u00A07", "\uFEFF7", + "\u000A7", "\u000D7", "\u20287", "\u20297", "\u16807", "\u180E7", + "\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057", + "\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7", + "\u30007", + " " + binaryString + " foo ", undefined, 1.5, true, false, + {"test": 6}, NaN, +Infinity, -Infinity, "\0", + {toString:function() {return 2;}, valueOf: null}, + {valueOf:function() {return 3;}}], + "idlTests": [0, 1, 257, maxInt, "-0", maxInt + 1, maxUnsigned], + "idlDomExpected": [0, 1, 257, maxInt, 0, null, null], + }, /** * "If a reflecting IDL attribute is a floating point number type (double), * then, on getting, the content attribute must be parsed according to the @@ -681,6 +712,54 @@ ReflectionTests.reflects = function(data, idlName, idlObj, domName, domObj) { } } break; + + case "clamped unsigned long": + [data.min - 1, data.min, data.max, data.max + 1].forEach(function(val) { + if (domTests.indexOf(val) == -1) { + domTests.push(val); + } + if (idlTests.indexOf(val) == -1 && 0 <= val && val <= maxUnsigned) { + idlTests.push(val); + if (typeof val != "number") { + val = ReflectionTests.parseNonneg(val); + } + idlDomExpected.push(val > maxInt ? null : val); + } + }); + + // Rewrite expected values + domExpected = domTests.map(function(val) { + var parsed = ReflectionTests.parseNonneg(String(val)); + if (parsed === false) { + return defaultVal; + } + if (parsed < data.min) { + return data.min; + } + if (parsed > data.max) { + return data.max; + } + return parsed; + }); + idlIdlExpected = idlTests.map(function(val) { + if (typeof val != "number") { + val = ReflectionTests.parseNonneg(val); + } + if (val < 0 || val > maxUnsigned) { + throw "Test bug: val should be an unsigned long"; + } + if (val > maxInt) { + return defaultVal; + } + if (val < data.min) { + return data.min; + } + if (val > data.max) { + return data.max; + } + return val; + }); + break; } if (domObj.tagName.toLowerCase() == "canvas" && (domName == "width" || domName == "height")) { // Opera tries to allocate a canvas with the given width and height, so diff --git a/testing/web-platform/tests/html/dom/self-origin.sub.html b/testing/web-platform/tests/html/dom/self-origin.sub.html index 4143a4a20ab4..539494a96bb9 100644 --- a/testing/web-platform/tests/html/dom/self-origin.sub.html +++ b/testing/web-platform/tests/html/dom/self-origin.sub.html @@ -48,7 +48,7 @@ function nextMessageTest() { window.onmessage = function(e) { var testData = messageTests[curTest++]; - testData[3].step_func(function() { + testData[3].step(function() { assert_equals(e.data, testData[2]) }); testData[3].done(); diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html new file mode 100644 index 000000000000..68dcc54702ce --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html @@ -0,0 +1,7 @@ + + + +Reference file for spellcheck tests + +
This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.
+ diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html new file mode 100644 index 000000000000..4a5fd4104104 --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html @@ -0,0 +1,15 @@ + + + +Turning off spellcheck on editing hosts + + + + +
This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.
+ + diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html new file mode 100644 index 000000000000..44f1ea842e29 --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html @@ -0,0 +1,16 @@ + + + +Turning off spellcheck on editable elements + + + + +
This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.
+ + diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html new file mode 100644 index 000000000000..9c88660e2817 --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html @@ -0,0 +1,15 @@ + + + +Turning off spellcheck on editing hosts while keeping them editable + + + + +
This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.
+ + diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html new file mode 100644 index 000000000000..fdeb90648c07 --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html @@ -0,0 +1,16 @@ + + + +Turning off spellcheck on editable elements while keeping them editable + + + + +
This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.
+ + diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html new file mode 100644 index 000000000000..9ab7a3ed6dcc --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html @@ -0,0 +1,16 @@ + + + +Turning off spellcheck on editable elements via an ancestor + + + + +
This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.
+ + diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html new file mode 100644 index 000000000000..f0b54da15b5b --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html @@ -0,0 +1,18 @@ + + + +Turning off spellcheck via an ancestor of the editing host + + + + +
+
This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.
+
+ + diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html new file mode 100644 index 000000000000..4bbeca9a32c4 --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html @@ -0,0 +1,25 @@ + + + +Turning off spellcheck by making textareas readonly + + + + + + + + + diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html new file mode 100644 index 000000000000..5ed72abb84db --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html @@ -0,0 +1,25 @@ + + + +Turning off spellcheck by making textareas disabled + + + + + + + + + diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html new file mode 100644 index 000000000000..577ffd895bcf --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html @@ -0,0 +1,25 @@ + + + +Turning off spellcheck by making input elements readonly + + + + + + + + + diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html new file mode 100644 index 000000000000..6a2e1046b895 --- /dev/null +++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html @@ -0,0 +1,25 @@ + + + +Turning off spellcheck by making input elements disabled + + + + + + + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html new file mode 100644 index 000000000000..8902de49cfb1 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html @@ -0,0 +1,35 @@ + +SharedArrayBuffer cannot cross agent clusters, BroadcastChannel edition + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success.html new file mode 100644 index 000000000000..f9cf7a87cfc3 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success.html @@ -0,0 +1,58 @@ + + +Structured cloning of SharedArrayBuffers: BroadcastChannel within the same agent cluster + + + + + + +
+ + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html new file mode 100644 index 000000000000..91110867d7b4 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html @@ -0,0 +1,64 @@ + + +SharedArrayBuffers, when cloned, do not give back the same object + + + + + + +
+ + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-dedicatedworker.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-dedicatedworker.html new file mode 100644 index 000000000000..de097b26c417 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-dedicatedworker.html @@ -0,0 +1,14 @@ + + +Structured cloning of SharedArrayBuffers into a dedicated worker nested inside a dedicated worker + + + + + +
+ + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-sharedworker.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-sharedworker.html new file mode 100644 index 000000000000..cf328be87996 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success-sharedworker.html @@ -0,0 +1,14 @@ + + +Structured cloning of SharedArrayBuffers into a dedicated worker nested inside a shared worker + + + + + +
+ + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.js new file mode 100644 index 000000000000..e1a28436e0af --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.js @@ -0,0 +1,11 @@ +"use strict"; +importScripts("/resources/testharness.js"); +importScripts("resources/test-incrementer.js"); + +promise_test(t => { + const worker = new Worker("resources/incrementer-worker.js"); + + return testSharingViaIncrementerScript(t, worker, "parent worker", worker, "sub-worker"); +}, "postMessaging to a dedicated sub-worker allows them to see each others' modifications"); + +done(); diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html new file mode 100644 index 000000000000..ece74e271944 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html @@ -0,0 +1,31 @@ + + +SharedArrayBuffers cannot be transferred + + + + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/blank.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/blank.html new file mode 100644 index 000000000000..eec1b2cc8e36 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/blank.html @@ -0,0 +1,2 @@ + +Used as a service worker-controlled iframe diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html new file mode 100644 index 000000000000..792d6fd20138 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html @@ -0,0 +1,19 @@ + + +A test page that messes with a given SharedArrayBuffer sent from a BroadcastChannel + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-sharedworker.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-sharedworker.js new file mode 100644 index 000000000000..310e0e935844 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-sharedworker.js @@ -0,0 +1,7 @@ +const channel = new BroadcastChannel("anne was here"); +channel.onmessageerror = ({ data }) => { + if(data === null) { + channel.postMessage("sw-success"); + } +} +channel.postMessage("hi"); diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-worker.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-worker.js new file mode 100644 index 000000000000..36369cde5004 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-worker.js @@ -0,0 +1,9 @@ +const channel = new BroadcastChannel("anne was here"); +channel.onmessage = ({ data }) => { + if(data === "hi" || data === "sw-success") { + return; + } else if(data instanceof SharedArrayBuffer) { + channel.postMessage("dw-success"); + } +} +channel.postMessage("hi"); diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-iframe.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-iframe.html new file mode 100644 index 000000000000..c4fd5824a1c6 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-iframe.html @@ -0,0 +1,11 @@ + + +A test page that echos back anything postMessaged to it to its parent + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-worker.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-worker.js new file mode 100644 index 000000000000..cbbde8a73c8c --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/echo-worker.js @@ -0,0 +1,5 @@ +"use strict"; + +self.onmessage = ({ data }) => { + self.postMessage(data); +}; diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe-domain.sub.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe-domain.sub.html new file mode 100644 index 000000000000..a6dd70177584 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe-domain.sub.html @@ -0,0 +1,11 @@ + + +A test page that messes with a given SharedArrayBuffer and also sets document.domain + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe.html new file mode 100644 index 000000000000..6f27ad7d5bec --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe.html @@ -0,0 +1,10 @@ + + +A test page that messes with a given SharedArrayBuffer + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-popup.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-popup.html new file mode 100644 index 000000000000..e583b5c4161b --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-popup.html @@ -0,0 +1,10 @@ + + +A test page that messes with a given SharedArrayBuffer + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker-with-channel.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker-with-channel.js new file mode 100644 index 000000000000..c74fd26d3fd6 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker-with-channel.js @@ -0,0 +1,7 @@ +"use strict"; +importScripts("./test-incrementer.js"); + +self.onmessage = ({ data }) => { + // data will be a MessagePort + setupDestinationIncrementer(data, data); +}; diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker.js new file mode 100644 index 000000000000..5801bd2b97c8 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker.js @@ -0,0 +1,4 @@ +"use strict"; +importScripts("./test-incrementer.js"); + +setupDestinationIncrementer(self, self); diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-1.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-1.html new file mode 100644 index 000000000000..fe93cc0c4b0f --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-1.html @@ -0,0 +1,5 @@ + + +Nesting level 1 + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-2.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-2.html new file mode 100644 index 000000000000..fad52ce9de39 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-2.html @@ -0,0 +1,5 @@ + + +Nesting level 2 + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-3.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-3.html new file mode 100644 index 000000000000..7971022b2cdc --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-3.html @@ -0,0 +1,5 @@ + + +Nesting level 3 + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-4-incrementer.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-4-incrementer.html new file mode 100644 index 000000000000..d374515bdc73 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-4-incrementer.html @@ -0,0 +1,10 @@ + + +A test page that messes with a given SharedArrayBuffer, nested 4 levels deep in iframes + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-failure.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-failure.js new file mode 100644 index 000000000000..c6f2046878cc --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-failure.js @@ -0,0 +1,32 @@ +"use strict"; +self.importScripts("/resources/testharness.js"); + +let state = "start in worker"; + +self.onmessage = e => { + if (e.data === "start in window") { + assert_equals(state, "start in worker"); + e.source.postMessage(state); + state = "we are expecting a messageerror due to the window sending us a SAB"; + } else if (e.data === "we are expecting a messageerror due to the worker sending us a SAB") { + assert_equals(state, "onmessageerror was received in worker"); + e.source.postMessage(new SharedArrayBuffer()); + state = "done in worker"; + } else { + e.source.postMessage(`worker onmessage was reached when in state "${state}" and data ${e.data}`); + } +}; + +self.onmessageerror = e => { + if (state === "we are expecting a messageerror due to the window sending us a SAB") { + assert_equals(e.data, null, "data"); + assert_equals(e.origin, self.origin, "origin"); + assert_not_equals(e.source, null, "source"); + assert_equals(e.ports.length, 0, "ports length"); + + state = "onmessageerror was received in worker"; + e.source.postMessage(state); + } else { + e.source.postMessage(`worker onmessageerror was reached when in state "${state}" and data ${e.data}`); + } +}; diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/sharedworker-failure.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/sharedworker-failure.js new file mode 100644 index 000000000000..a11ccbc1f309 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/sharedworker-failure.js @@ -0,0 +1,17 @@ +let state = "send-sw-failure" +onconnect = initialE => { + initialE.source.postMessage(state) + initialE.source.onmessage = e => { + if(state === "" && e.data === "send-window-failure") { + e.postMessage(new SharedArrayBuffer()) + } else { + e.postMessage("failure") + } + } + initialE.source.onmessageerror = e => { + if(state === "send-sw-failure") { + e.postMessage("send-sw-failure-success") + state = "" + } + } +} diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-incrementer.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-incrementer.js new file mode 100644 index 000000000000..2bdd2bae66e1 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-incrementer.js @@ -0,0 +1,73 @@ +"use strict"; + +self.getViewValue = (view, index) => { + if(view instanceof DataView) { + return view.getInt8(index); + } + return view[index]; +}; + +self.setViewValue = (view, index, value) => { + if(view instanceof DataView) { + view.setInt8(index, value); + } else { + view[index] = value; + } +}; + +self.testSharingViaIncrementerScript = (t, whereToListen, whereToListenLabel, whereToSend, whereToSendLabel, origin, type = "Int32Array") => { + return new Promise(resolve => { + const sab = new SharedArrayBuffer(8); + const view = new self[type](sab); + setViewValue(view, 0, 1); + + whereToListen.onmessage = t.step_func(({ data }) => { + switch (data.message) { + case "initial payload received": { + assert_equals(data.value, 1, `The ${whereToSendLabel} must see the same value in the SharedArrayBuffer`); + break; + } + + case "changed to 2": { + assert_equals(getViewValue(view, 0), 2, `The ${whereToListenLabel} must see changes made in the ${whereToSendLabel}`); + + setViewValue(view, 0, 3); + whereToSend.postMessage({ message: "changed to 3" }, origin); + + break; + } + + case "changed to 3 received": { + assert_equals(data.value, 3, `The ${whereToSendLabel} must see changes made in the ${whereToListenLabel}`); + resolve(); + break; + } + } + }); + + whereToSend.postMessage({ message: "initial payload", view }, origin); + }); +}; + +self.setupDestinationIncrementer = (whereToListen, whereToSendBackTo, origin) => { + let view; + whereToListen.onmessage = ({ data }) => { + switch (data.message) { + case "initial payload": { + view = data.view; + whereToSendBackTo.postMessage({ message: "initial payload received", value: getViewValue(view, 0) }, origin); + + setViewValue(view, 0, 2); + whereToSendBackTo.postMessage({ message: "changed to 2" }, origin); + + break; + } + + case "changed to 3": { + whereToSendBackTo.postMessage({ message: "changed to 3 received", value: getViewValue(view, 0) }, origin); + + break; + } + } + }; +}; diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-sab.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-sab.js new file mode 100644 index 000000000000..6d6efda00db2 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/test-sab.js @@ -0,0 +1,15 @@ +"use strict"; + +self.assertSABsHaveSameBackingBlock = (originalSAB, clonedSAB) => { + const originalView = new Uint8Array(originalSAB); + const clonedView = new Uint8Array(clonedSAB); + + assert_not_equals(originalSAB, clonedSAB, "the clone must not be the same object"); + + assert_equals(originalView[0], 0, "originalView[0] starts 0"); + assert_equals(clonedView[0], 0, "clonedView[0] starts 0"); + + originalView[0] = 5; + assert_equals(originalView[0], 5, "originalView[0] ends up 5"); + assert_equals(clonedView[0], 5, "clonedView[0] ends up 5"); +}; diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html new file mode 100644 index 000000000000..49d341f47f9b --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html @@ -0,0 +1,36 @@ + + +SharedArrayBuffers cloning via history's methods invoking StructuredSerializeForStorage + + + + + + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.js new file mode 100644 index 000000000000..4eb25eb85467 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.js @@ -0,0 +1,40 @@ +// META: script=/IndexedDB/support.js +"use strict"; + +async_test(t => { + const openReq = createdb(t); + + openReq.onupgradeneeded = e => { + const db = e.target.result; + const store = db.createObjectStore("store", { keyPath: "key" }); + + assert_throws("DataCloneError", () => { + store.put({ key: 1, property: new SharedArrayBuffer() }); + }); + t.done(); + }; +}, "SharedArrayBuffer cloning via IndexedDB: basic case"); + +async_test(t => { + const openReq = createdb(t); + + openReq.onupgradeneeded = e => { + const db = e.target.result; + const store = db.createObjectStore("store", { keyPath: "key" }); + + let getter1Called = false; + let getter2Called = false; + + assert_throws("DataCloneError", () => { + store.put({ key: 1, property: [ + { get x() { getter1Called = true; return 5; } }, + new SharedArrayBuffer(), + { get x() { getter2Called = true; return 5; } } + ]}); + }); + + assert_true(getter1Called, "The getter before the SAB must have been called"); + assert_false(getter2Called, "The getter after the SAB must not have been called"); + t.done(); + }; +}, "SharedArrayBuffer cloning via the IndexedDB: is interleaved correctly"); diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-notifications-api.any.js b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-notifications-api.any.js new file mode 100644 index 000000000000..2c3fb7be034b --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-notifications-api.any.js @@ -0,0 +1,23 @@ +"use strict"; + +test(() => { + assert_throws("DataCloneError", () => { + new Notification("Bob: Hi", { data: new SharedArrayBuffer() }); + }) +}, "SharedArrayBuffer cloning via the Notifications API's data member: basic case"); + +test(() => { + let getter1Called = false; + let getter2Called = false; + + assert_throws("DataCloneError", () => { + new Notification("Bob: Hi", { data: [ + { get x() { getter1Called = true; return 5; } }, + new SharedArrayBuffer(), + { get x() { getter2Called = true; return 5; } } + ]}); + }); + + assert_true(getter1Called, "The getter before the SAB must have been called"); + assert_false(getter2Called, "The getter after the SAB must not have been called"); +}, "SharedArrayBuffer cloning via the Notifications API's data member: is interleaved correctly"); diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html new file mode 100644 index 000000000000..9205d01df26e --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html @@ -0,0 +1,26 @@ + + +Structured cloning of SharedArrayBuffers into same-origin-domain windows + + + + + + +
+ + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html new file mode 100644 index 000000000000..cd67e5b2c955 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html @@ -0,0 +1,22 @@ + + +Structured cloning of SharedArrayBuffers using MessageChannel + + + + + + +
+ + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-failure.https.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-failure.https.html new file mode 100644 index 000000000000..ff7449a93177 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-failure.https.html @@ -0,0 +1,54 @@ + + +SharedArrayBuffer cannot cross agent clusters, service worker edition + + + + + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html new file mode 100644 index 000000000000..023cb5acdef1 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html @@ -0,0 +1,31 @@ + +SharedArrayBuffer cannot cross agent clusters, shared worker edition + + + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html new file mode 100644 index 000000000000..e25fc9002d02 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html @@ -0,0 +1,26 @@ + + +Structured cloning of SharedArrayBuffers to similar-origin, but not same-origin, windows + + + + + + +
+ + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html new file mode 100644 index 000000000000..4b86f9befa6a --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html @@ -0,0 +1,70 @@ + + +Structured cloning of SharedArrayBuffers: simple success cases that don't need dedicated files + + + + + + +
+ + diff --git a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/structured_clone_blob.html b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/structured_clone_blob.html new file mode 100644 index 000000000000..6b1abf5ef8d3 --- /dev/null +++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/structured_clone_blob.html @@ -0,0 +1,35 @@ + + + + +Safe passing of structured data - Blob + + + + + + + diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/iframe-body-margin-attributes.html b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/iframe-body-margin-attributes.html new file mode 100644 index 000000000000..e1f4fb51540f --- /dev/null +++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/iframe-body-margin-attributes.html @@ -0,0 +1,32 @@ + +iframe and body margin attributes + + + + + + diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/iframe-marginwidth-marginheight.html b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/iframe-marginwidth-marginheight.html new file mode 100644 index 000000000000..b5b49d1b8678 --- /dev/null +++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/iframe-marginwidth-marginheight.html @@ -0,0 +1,11 @@ + +iframe marginwidth and marginheight + + + + diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/support/body-marginwidth-marginheight.html b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/support/body-marginwidth-marginheight.html new file mode 100644 index 000000000000..5d825e345566 --- /dev/null +++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/support/body-marginwidth-marginheight.html @@ -0,0 +1,2 @@ + + diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/support/body-topmargin-leftmargin.html b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/support/body-topmargin-leftmargin.html new file mode 100644 index 000000000000..7ba5e5333054 --- /dev/null +++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/support/body-topmargin-leftmargin.html @@ -0,0 +1,2 @@ + + diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html index 142024e67b77..01df0c547a5c 100644 --- a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html +++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html @@ -3,6 +3,10 @@ Canvas fallback content +

This text should be green on a white background diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href.html new file mode 100644 index 000000000000..6a3f18de9860 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href.html @@ -0,0 +1,13 @@ + + +Obtaining a new stylesheet removes styles from the previous stylesheet. + + + +

This text should be green on a white background diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-canvas-element/imagedata.html b/testing/web-platform/tests/html/semantics/embedded-content/the-canvas-element/imagedata.html new file mode 100644 index 000000000000..b5b4d0de2757 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-canvas-element/imagedata.html @@ -0,0 +1,58 @@ + + +ImageData Tests + + + diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_harness.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_harness.js index f4ef511d1de2..2b43c54e2f2e 100644 --- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_harness.js +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_harness.js @@ -1,15 +1,16 @@ function get_test_results(id) { async_test(function(test) { - var timer = window.setInterval(test.step_func(loop), 100); + test.step_timeout(loop, 100); function loop() { var xhr = new XMLHttpRequest(); xhr.open('GET', 'stash.py?id=' + id); - xhr.onreadystatechange = test.step_func(function() { + xhr.onload = test.step_func(function() { assert_equals(xhr.status, 200); if (xhr.responseText) { assert_equals(xhr.responseText, "OK"); test.done(); - window.clearTimeout(timer); + } else { + test.step_timeout(loop, 100); } }); xhr.send(); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-img-element/delay-load-event.html b/testing/web-platform/tests/html/semantics/embedded-content/the-img-element/delay-load-event.html new file mode 100644 index 000000000000..c67074a40d89 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-img-element/delay-load-event.html @@ -0,0 +1,17 @@ + + +Image element delays window's load event + + + + diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-img-element/document-adopt-base-url.html b/testing/web-platform/tests/html/semantics/embedded-content/the-img-element/document-adopt-base-url.html new file mode 100644 index 000000000000..ea63114d570d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-img-element/document-adopt-base-url.html @@ -0,0 +1,14 @@ + + +Document base URL adopted img test + + + + + diff --git a/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form_attribute.html b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form_attribute.html new file mode 100644 index 000000000000..dde3250dbf7c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form_attribute.html @@ -0,0 +1,233 @@ + + + + + + + +

+
+
+ + + +
+ +
+ +
+
+ + + + diff --git a/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form_owner_and_table.html b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form_owner_and_table.html new file mode 100644 index 000000000000..1aa75c27b355 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form_owner_and_table.html @@ -0,0 +1,50 @@ + + + + + + + +
+
+ + + + +
+ + + +
+ + + + diff --git a/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form_owner_and_table_2.html b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form_owner_and_table_2.html new file mode 100644 index 000000000000..d9aee12b5f35 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form_owner_and_table_2.html @@ -0,0 +1,45 @@ + + + + + + + +
+
+ + + + + +
+ + + +
+ + + + diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-after-content-change.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-after-content-change.html index 90ebc28a2380..b77bf50d4fca 100644 --- a/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-after-content-change.html +++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-after-content-change.html @@ -3,16 +3,142 @@ Selection indices after content change + + + + diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-autocomplete.html b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-autocomplete.html index c50ea73170d0..5c1d05b301e7 100644 --- a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-autocomplete.html +++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-autocomplete.html @@ -47,12 +47,14 @@ autocompletetest(document.forms.autocomplete_off, ["off", "off", "on", "off", ""], "form autocomplete attribute off"); autocompletetest(document.forms.autocomplete_invalid, ["on", "on", "on", "off", ""], "form autocomplete attribute invalid"); - var keywords = [ "name", "honorific-prefix", "given-name", "additional-name", "family-name", "honorific-suffix", "nickname", "username", "new-password", "current-password", "organization-title", "organization", "street-address", "address-line1", "address-line2", "address-line3", "address-level4", "address-level3", "address-level2", "address-level1", "country", "country-name", "postal-code", "cc-name", "cc-given-name", "cc-additional-name", "cc-family-name", "cc-number", "cc-exp", "cc-exp-month", "cc-exp-year", "cc-csc", "cc-type", "transaction-currency", "transaction-amount", "language", "bday", "bday-day", "bday-month", "bday-year", "sex", "url", "photo", "tel", "tel-country-code", "tel-national", "tel-area-code", "tel-local", "tel-local-prefix", "tel-local-suffix", "tel-extension", "email", "impp" ]; + var keywords = [ "on", "off", "name", "honorific-prefix", "given-name", "additional-name", "family-name", "honorific-suffix", "nickname", "username", "new-password", "current-password", "organization-title", "organization", "street-address", "address-line1", "address-line2", "address-line3", "address-level4", "address-level3", "address-level2", "address-level1", "country", "country-name", "postal-code", "cc-name", "cc-given-name", "cc-additional-name", "cc-family-name", "cc-number", "cc-exp", "cc-exp-month", "cc-exp-year", "cc-csc", "cc-type", "transaction-currency", "transaction-amount", "language", "bday", "bday-day", "bday-month", "bday-year", "sex", "url", "photo", "tel", "tel-country-code", "tel-national", "tel-area-code", "tel-local", "tel-local-prefix", "tel-local-suffix", "tel-extension", "email", "impp" ]; keywords.forEach(function(keyword) { test(function(){ var input = document.createElement("input"); - input.setAttribute("autocomplete", keyword); + // Include whitespace to test splitting tokens on whitespace. + // Convert to uppercase to ensure that the tokens are normalized to lowercase. + input.setAttribute("autocomplete", " " + keyword.toUpperCase() + "\t"); assert_equals(input.autocomplete, keyword); }, keyword + " is an allowed autocomplete field name"); }); diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/centering-iframe.sub.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/centering-iframe.sub.html new file mode 100644 index 000000000000..2f9721eee86f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/centering-iframe.sub.html @@ -0,0 +1,28 @@ + + +dialog element centered frame + + +
+ X +
+ + diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/centering.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/centering.html new file mode 100644 index 000000000000..8df2d3052320 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/centering.html @@ -0,0 +1,51 @@ + + +dialog element: centered alignment + + + + +
+ + diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-menu-element/menuitem-label.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-menu-element/menuitem-label.html new file mode 100644 index 000000000000..3f0f9abf9db7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-menu-element/menuitem-label.html @@ -0,0 +1,19 @@ + + + + +item2 + item 3 +item4 + + + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html new file mode 100644 index 000000000000..a9556b1a29e2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html @@ -0,0 +1,22 @@ + + + + + + html-script-module-instantiation-error-1 + + + + +

html-script-module-instantiation-error-1

+ + + + + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.js new file mode 100644 index 000000000000..e317b01cc213 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.js @@ -0,0 +1 @@ +import something from "./instantiation-error-1.js"; diff --git a/testing/web-platform/tests/html/semantics/tabular-data/processing-model-1/span-limits.html b/testing/web-platform/tests/html/semantics/tabular-data/processing-model-1/span-limits.html new file mode 100644 index 000000000000..176ce09925ce --- /dev/null +++ b/testing/web-platform/tests/html/semantics/tabular-data/processing-model-1/span-limits.html @@ -0,0 +1,65 @@ + +Limits on colSpan/rowSpan + + +
+ + +
aa + +
a +
+ + +
aa + +
a +
+ + + +
a + +
+ + + +
a + +
+ + diff --git a/testing/web-platform/tests/html/semantics/text-level-semantics/the-a-element/a.rel-getter-01.html b/testing/web-platform/tests/html/semantics/text-level-semantics/the-a-element/a.rel-getter-01.html new file mode 100644 index 000000000000..8e47121eb8ca --- /dev/null +++ b/testing/web-platform/tests/html/semantics/text-level-semantics/the-a-element/a.rel-getter-01.html @@ -0,0 +1,19 @@ + +HTMLAnchorElement.rel getter + + + + +
+
+ +
+ diff --git a/testing/web-platform/tests/html/semantics/text-level-semantics/the-a-element/a.rel-setter-01.html b/testing/web-platform/tests/html/semantics/text-level-semantics/the-a-element/a.rel-setter-01.html new file mode 100644 index 000000000000..83c69de30142 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/text-level-semantics/the-a-element/a.rel-setter-01.html @@ -0,0 +1,20 @@ + +HTMLAnchorElement.rel setter + + + + +
+
+ +
+ diff --git a/testing/web-platform/tests/html/syntax/serializing-html-fragments/serializing.html b/testing/web-platform/tests/html/syntax/serializing-html-fragments/serializing.html index 6b7e678a355e..6a6f0c1d7464 100644 --- a/testing/web-platform/tests/html/syntax/serializing-html-fragments/serializing.html +++ b/testing/web-platform/tests/html/syntax/serializing-html-fragments/serializing.html @@ -178,7 +178,7 @@ var text_tests = [ var void_elements = [ "area", "base", "basefont", "bgsound", "br", "col", "embed", - "frame", "hr", "img", "input", "keygen", "link", "menuitem", + "frame", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr" ]; diff --git a/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-dedicatedworker.html b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-dedicatedworker.html new file mode 100644 index 000000000000..0d559999f3fa --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-dedicatedworker.html @@ -0,0 +1,13 @@ + + +[[CanBlock]] in a dedicated worker agent + + + + + + + diff --git a/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-serviceworker.https.html b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-serviceworker.https.html new file mode 100644 index 000000000000..6bfd29e8c74b --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-serviceworker.https.html @@ -0,0 +1,14 @@ + + +[[CanBlock]] in a service worker agent + + + + + + + + diff --git a/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-sharedworker.html b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-sharedworker.html new file mode 100644 index 000000000000..beb7c6467b24 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-sharedworker.html @@ -0,0 +1,13 @@ + + +[[CanBlock]] in a shared worker agent + + + + + + + diff --git a/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-window.html b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-window.html new file mode 100644 index 000000000000..369ce77b0b62 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-window.html @@ -0,0 +1,21 @@ + + +[[CanBlock]] in a similar-origin window agent + + + + + + + diff --git a/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-failure.js b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-failure.js new file mode 100644 index 000000000000..586c8ba38764 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-failure.js @@ -0,0 +1,13 @@ +"use strict"; +importScripts("/resources/testharness.js"); + +test(() => { + const sab = new SharedArrayBuffer(16); + const ta = new Int32Array(sab); + + assert_throws(new TypeError(), () => { + Atomics.wait(ta, 0, 0, 10); + }); +}, `[[CanBlock]] in a ${self.constructor.name}`); + +done(); diff --git a/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-success.js b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-success.js new file mode 100644 index 000000000000..2ed54143ee55 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/worker-that-requires-success.js @@ -0,0 +1,11 @@ +"use strict"; +importScripts("/resources/testharness.js"); + +test(() => { + const sab = new SharedArrayBuffer(16); + const ta = new Int32Array(sab); + + assert_equals(Atomics.wait(ta, 0, 0, 10), "timed-out"); +}, `[[CanBlock]] in a ${self.constructor.name}`); + +done(); diff --git a/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events-onerror.html b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events-onerror.html index 386af169a641..c76d531c43ec 100644 --- a/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events-onerror.html +++ b/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events-onerror.html @@ -27,9 +27,11 @@ async_test(function(t) { }; var p = Promise.reject(e); - setTimeout(t.step_func(function() { - // This will cause onrejectionhandled - p.catch(function() {}); - }), 1); + setTimeout(function() { + setTimeout(t.step_func(function() { + // This will cause onrejectionhandled + p.catch(function() {}); + }), 0); + }, 0); }, 'Throwing inside an unhandledrejection handler invokes the error handler.'); diff --git a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js b/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js deleted file mode 100644 index 9ba7defa1fbb..000000000000 --- a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js +++ /dev/null @@ -1,4 +0,0 @@ -importScripts("/resources/testharness.js") -importScripts("NavigatorID.js") -run_test(); -done(); diff --git a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js b/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator.any.js similarity index 97% rename from testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js rename to testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator.any.js index 78706f44d741..8cfaef024a0a 100644 --- a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js +++ b/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator.any.js @@ -1,4 +1,3 @@ -function run_test() { var compatibilityMode; if (navigator.userAgent.includes("Chrome")) { compatibilityMode = "Chrome"; @@ -50,7 +49,7 @@ function run_test() { async_test(function() { var request = new XMLHttpRequest(); request.onload = this.step_func_done(function() { - assert_equals("user-agent: " + navigator.userAgent + "\n", + assert_equals("User-Agent: " + navigator.userAgent + "\n", request.response, "userAgent should return the value sent in the " + "User-Agent header"); @@ -103,4 +102,5 @@ function run_test() { assert_false("oscpu" in navigator); } }, "oscpu"); -} + +done() diff --git a/testing/web-platform/tests/html/webappapis/timers/negative-setinterval.html b/testing/web-platform/tests/html/webappapis/timers/negative-setinterval.html new file mode 100644 index 000000000000..430d13c58aab --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/timers/negative-setinterval.html @@ -0,0 +1,17 @@ + +Negative timeout in setInterval + + + diff --git a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html b/testing/web-platform/tests/html/webappapis/timers/negative-settimeout.html similarity index 54% rename from testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html rename to testing/web-platform/tests/html/webappapis/timers/negative-settimeout.html index 1956a202cee1..57e88ee701d8 100644 --- a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html +++ b/testing/web-platform/tests/html/webappapis/timers/negative-settimeout.html @@ -1,10 +1,8 @@ - -NavigatorID +Negative timeout in setTimeout - -
diff --git a/testing/web-platform/tests/html/webappapis/timers/type-long-setinterval.html b/testing/web-platform/tests/html/webappapis/timers/type-long-setinterval.html new file mode 100644 index 000000000000..af0299599846 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/timers/type-long-setinterval.html @@ -0,0 +1,13 @@ + +Type long timeout for setInterval + + + diff --git a/testing/web-platform/tests/html/webappapis/timers/type-long-settimeout.html b/testing/web-platform/tests/html/webappapis/timers/type-long-settimeout.html new file mode 100644 index 000000000000..31fa4f126421 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/timers/type-long-settimeout.html @@ -0,0 +1,8 @@ + +Type long timeout for setTimeout + + + diff --git a/testing/web-platform/tests/images/apng.png b/testing/web-platform/tests/images/apng.png new file mode 100644 index 000000000000..e96e6471e6a8 Binary files /dev/null and b/testing/web-platform/tests/images/apng.png differ diff --git a/testing/web-platform/tests/interfaces/cssom.idl b/testing/web-platform/tests/interfaces/cssom.idl new file mode 100644 index 000000000000..e5a998ebf5d8 --- /dev/null +++ b/testing/web-platform/tests/interfaces/cssom.idl @@ -0,0 +1,294 @@ +interface MediaList { + stringifier attribute DOMString mediaText; + readonly attribute unsigned long length; + getter DOMString item(unsigned long index); + void appendMedium(DOMString medium); + void deleteMedium(DOMString medium); +}; + +interface StyleSheet { + readonly attribute DOMString type; + readonly attribute DOMString href; + readonly attribute Node ownerNode; + readonly attribute StyleSheet parentStyleSheet; + readonly attribute DOMString title; + [PutForwards=mediaText] readonly attribute MediaList media; + attribute boolean disabled; +}; + +interface CSSStyleSheet : StyleSheet { + readonly attribute CSSRule ownerRule; + readonly attribute CSSRuleList cssRules; + unsigned long insertRule(DOMString rule, unsigned long index); + void deleteRule(unsigned long index); +}; + +typedef sequence StyleSheetList; + +partial interface Document { + [SameObject] readonly attribute StyleSheetList styleSheets; +}; + +[NoInterfaceObject] interface LinkStyle { + readonly attribute StyleSheet sheet; +}; + +ProcessingInstruction implements LinkStyle; + +typedef sequence CSSRuleList; + +interface CSSRule { + // Types + const unsigned short STYLE_RULE = 1; + const unsigned short IMPORT_RULE = 3; + const unsigned short MEDIA_RULE = 4; + const unsigned short FONT_FACE_RULE = 5; + const unsigned short PAGE_RULE = 6; + const unsigned short NAMESPACE_RULE = 10; + readonly attribute unsigned short type; + + // Parsing and serialization + attribute DOMString cssText; + + // Context + readonly attribute CSSRule parentRule; + readonly attribute CSSStyleSheet parentStyleSheet; +}; + +interface CSSStyleRule : CSSRule { + attribute DOMString selectorText; + readonly attribute CSSStyleDeclaration style; +}; + +interface CSSImportRule : CSSRule { + readonly attribute DOMString href; + [PutForwards=mediaText] readonly attribute MediaList media; + readonly attribute CSSStyleSheet styleSheet; +}; + +interface CSSMediaRule : CSSRule { + [PutForwards=mediaText] readonly attribute MediaList media; + readonly attribute CSSRuleList cssRules; + unsigned long insertRule(DOMString rule, unsigned long index); + void deleteRule(unsigned long index); +}; + +interface CSSFontFaceRule : CSSRule { + readonly attribute CSSStyleDeclaration style; +}; + +interface CSSPageRule : CSSRule { + attribute DOMString selectorText; + readonly attribute CSSStyleDeclaration style; +}; + +interface CSSNamespaceRule : CSSRule { + readonly attribute DOMString namespaceURI; + readonly attribute DOMString? prefix; +}; + +interface CSSStyleDeclaration { + attribute DOMString cssText; + + readonly attribute unsigned long length; + DOMString item(unsigned long index); + + DOMString getPropertyValue(DOMString property); + DOMString getPropertyPriority(DOMString property); + void setProperty(DOMString property, DOMString value, optional DOMString priority); + DOMString removeProperty(DOMString property); + + readonly attribute CSSStyleDeclarationValue values; + + readonly attribute CSSRule parentRule; + + // CSS Properties + attribute DOMString azimuth; + attribute DOMString background; + attribute DOMString backgroundAttachment; + attribute DOMString backgroundColor; + attribute DOMString backgroundImage; + attribute DOMString backgroundPosition; + attribute DOMString backgroundRepeat; + attribute DOMString border; + attribute DOMString borderCollapse; + attribute DOMString borderColor; + attribute DOMString borderSpacing; + attribute DOMString borderStyle; + attribute DOMString borderTop; + attribute DOMString borderRight; + attribute DOMString borderBottom; + attribute DOMString borderLeft; + attribute DOMString borderTopColor; + attribute DOMString borderRightColor; + attribute DOMString borderBottomColor; + attribute DOMString borderLeftColor; + attribute DOMString borderTopStyle; + attribute DOMString borderRightStyle; + attribute DOMString borderBottomStyle; + attribute DOMString borderLeftStyle; + attribute DOMString borderTopWidth; + attribute DOMString borderRightWidth; + attribute DOMString borderBottomWidth; + attribute DOMString borderLeftWidth; + attribute DOMString borderWidth; + attribute DOMString bottom; + attribute DOMString captionSide; + attribute DOMString clear; + attribute DOMString clip; + attribute DOMString color; + attribute DOMString content; + attribute DOMString counterIncrement; + attribute DOMString counterReset; + attribute DOMString cue; + attribute DOMString cueAfter; + attribute DOMString cueBefore; + attribute DOMString cursor; + attribute DOMString direction; + attribute DOMString display; + attribute DOMString elevation; + attribute DOMString emptyCells; + attribute DOMString cssFloat; + attribute DOMString font; + attribute DOMString fontFamily; + attribute DOMString fontSize; + attribute DOMString fontSizeAdjust; + attribute DOMString fontStretch; + attribute DOMString fontStyle; + attribute DOMString fontVariant; + attribute DOMString fontWeight; + attribute DOMString height; + attribute DOMString left; + attribute DOMString letterSpacing; + attribute DOMString lineHeight; + attribute DOMString listStyle; + attribute DOMString listStyleImage; + attribute DOMString listStylePosition; + attribute DOMString listStyleType; + attribute DOMString margin; + attribute DOMString marginTop; + attribute DOMString marginRight; + attribute DOMString marginBottom; + attribute DOMString marginLeft; + attribute DOMString marks; + attribute DOMString maxHeight; + attribute DOMString maxWidth; + attribute DOMString minHeight; + attribute DOMString minWidth; + attribute DOMString orphans; + attribute DOMString outline; + attribute DOMString outlineColor; + attribute DOMString outlineStyle; + attribute DOMString outlineWidth; + attribute DOMString overflow; + attribute DOMString padding; + attribute DOMString paddingTop; + attribute DOMString paddingRight; + attribute DOMString paddingBottom; + attribute DOMString paddingLeft; + attribute DOMString page; + attribute DOMString pageBreakAfter; + attribute DOMString pageBreakBefore; + attribute DOMString pageBreakInside; + attribute DOMString pause; + attribute DOMString pauseAfter; + attribute DOMString pauseBefore; + attribute DOMString pitch; + attribute DOMString pitchRange; + attribute DOMString playDuring; + attribute DOMString position; + attribute DOMString quotes; + attribute DOMString richness; + attribute DOMString right; + attribute DOMString size; + attribute DOMString speak; + attribute DOMString speakHeader; + attribute DOMString speakNumeral; + attribute DOMString speakPunctuation; + attribute DOMString speechRate; + attribute DOMString stress; + attribute DOMString tableLayout; + attribute DOMString textAlign; + attribute DOMString textDecoration; + attribute DOMString textIndent; + attribute DOMString textShadow; + attribute DOMString textTransform; + attribute DOMString top; + attribute DOMString unicodeBidi; + attribute DOMString verticalAlign; + attribute DOMString visibility; + attribute DOMString voiceFamily; + attribute DOMString volume; + attribute DOMString whiteSpace; + attribute DOMString widows; + attribute DOMString width; + attribute DOMString wordSpacing; + attribute DOMString zIndex; +}; + +interface CSSStyleDeclarationValue { + // ... + + // CSS Properties + +}; + +interface CSSPropertyValue { + attribute DOMString cssText; +}; + +[NoInterfaceObject] interface CSSMapValue { + getter CSSValue (DOMString name); +}; + +[NoInterfaceObject] interface CSSPropertyValueList { + readonly attribute CSSValue[] list; +}; + +[NoInterfaceObject] interface CSSComponentValue { + readonly attribute DOMString type; + attribute any value; +}; + +[NoInterfaceObject] interface CSSStringComponentValue { + attribute DOMString string; +}; + +[NoInterfaceObject] interface CSSKeywordComponentValue { + attribute DOMString keyword; +}; + +[NoInterfaceObject] interface CSSIdentifierComponentValue { + attribute DOMString identifier; +}; + +[NoInterfaceObject] interface CSSColorComponentValue { + attribute short red; + attribute short green; + attribute short blue; + attribute float alpha; +}; + +[NoInterfaceObject] interface CSSLengthComponentValue { + attribute float em; + attribute float ex; + attribute float px; + // figure out what to do with absolute lengths +}; + +[NoInterfaceObject] interface CSSPercentageComponentValue { + attribute float percent; +}; + +[NoInterfaceObject] interface CSSURLComponentValue { + attribute DOMString? url; +}; + +[NoInterfaceObject] interface ElementCSSInlineStyle { + readonly attribute CSSStyleDeclaration style; +}; + +//partial interface Window { +// CSSStyleDeclaration getComputedStyle(Element elt); +// CSSStyleDeclaration getComputedStyle(Element elt, DOMString pseudoElt); +//}; diff --git a/testing/web-platform/tests/html/dom/resources/untested-interfaces.idl b/testing/web-platform/tests/interfaces/dom.idl similarity index 57% rename from testing/web-platform/tests/html/dom/resources/untested-interfaces.idl rename to testing/web-platform/tests/interfaces/dom.idl index 9a897cfa73df..7e2667ff7d35 100644 --- a/testing/web-platform/tests/html/dom/resources/untested-interfaces.idl +++ b/testing/web-platform/tests/interfaces/dom.idl @@ -1,6 +1,5 @@ -// DOM IDLs -[Constructor(DOMString type, optional EventInit eventInitDict), - Exposed=(Window,Worker)] +[Constructor(DOMString type, optional EventInit eventInitDict)/*, + Exposed=(Window,Worker)*/] interface Event { readonly attribute DOMString type; readonly attribute EventTarget? target; @@ -32,8 +31,8 @@ dictionary EventInit { }; -[Constructor(DOMString type, optional CustomEventInit eventInitDict), - Exposed=(Window,Worker)] +[Constructor(DOMString type, optional CustomEventInit eventInitDict)/*, + Exposed=(Window,Worker)*/] interface CustomEvent : Event { readonly attribute any detail; @@ -45,7 +44,7 @@ dictionary CustomEventInit : EventInit { }; -[Exposed=(Window,Worker)] +//[Exposed=(Window,Worker)] interface EventTarget { void addEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); @@ -548,373 +547,3 @@ interface DOMTokenList { [CEReactions] stringifier attribute DOMString value; // iterable; }; - -// UI Events IDLs -[Constructor(DOMString type, optional UIEventInit eventInitDict)] -interface UIEvent : Event { - readonly attribute WindowProxy? view; - readonly attribute long detail; -}; - -dictionary UIEventInit : EventInit { - WindowProxy? view = null; - long detail = 0; -}; - -[Constructor(DOMString typeArg, optional MouseEventInit mouseEventInitDict)] -interface MouseEvent : UIEvent { - readonly attribute long screenX; - readonly attribute long screenY; - readonly attribute long clientX; - readonly attribute long clientY; - readonly attribute boolean ctrlKey; - readonly attribute boolean shiftKey; - readonly attribute boolean altKey; - readonly attribute boolean metaKey; - readonly attribute short button; - readonly attribute EventTarget? relatedTarget; - // Introduced in DOM Level 3 - readonly attribute unsigned short buttons; - boolean getModifierState (DOMString keyArg); -}; - -dictionary MouseEventInit : EventModifierInit { - long screenX = 0; - long screenY = 0; - long clientX = 0; - long clientY = 0; - short button = 0; - unsigned short buttons = 0; - EventTarget? relatedTarget = null; -}; - -dictionary EventModifierInit : UIEventInit { - boolean ctrlKey = false; - boolean shiftKey = false; - boolean altKey = false; - boolean metaKey = false; - boolean keyModifierStateAltGraph = false; - boolean keyModifierStateCapsLock = false; - boolean keyModifierStateFn = false; - boolean keyModifierStateFnLock = false; - boolean keyModifierStateHyper = false; - boolean keyModifierStateNumLock = false; - boolean keyModifierStateOS = false; - boolean keyModifierStateScrollLock = false; - boolean keyModifierStateSuper = false; - boolean keyModifierStateSymbol = false; - boolean keyModifierStateSymbolLock = false; -}; - -partial interface MouseEvent { - // Deprecated in DOM Level 3 - void initMouseEvent (DOMString typeArg, boolean bubblesArg, boolean cancelableArg, Window? viewArg, long detailArg, long screenXArg, long screenYArg, long clientXArg, long clientYArg, boolean ctrlKeyArg, boolean altKeyArg, boolean shiftKeyArg, boolean metaKeyArg, short buttonArg, EventTarget? relatedTargetArg); -}; - -// Touch Events IDLs -interface Touch { - readonly attribute long identifier; - readonly attribute EventTarget target; - readonly attribute long screenX; - readonly attribute long screenY; - readonly attribute long clientX; - readonly attribute long clientY; - readonly attribute long pageX; - readonly attribute long pageY; -}; - -// CSSOM IDLs -interface MediaList { - stringifier attribute DOMString mediaText; - readonly attribute unsigned long length; - getter DOMString item(unsigned long index); - void appendMedium(DOMString medium); - void deleteMedium(DOMString medium); -}; - -interface StyleSheet { - readonly attribute DOMString type; - readonly attribute DOMString href; - readonly attribute Node ownerNode; - readonly attribute StyleSheet parentStyleSheet; - readonly attribute DOMString title; - [PutForwards=mediaText] readonly attribute MediaList media; - attribute boolean disabled; -}; - -interface CSSStyleSheet : StyleSheet { - readonly attribute CSSRule ownerRule; - readonly attribute CSSRuleList cssRules; - unsigned long insertRule(DOMString rule, unsigned long index); - void deleteRule(unsigned long index); -}; - -typedef sequence StyleSheetList; - -partial interface Document { - [SameObject] readonly attribute StyleSheetList styleSheets; -}; - -[NoInterfaceObject] interface LinkStyle { - readonly attribute StyleSheet sheet; -}; - -ProcessingInstruction implements LinkStyle; - -typedef sequence CSSRuleList; - -interface CSSRule { - // Types - const unsigned short STYLE_RULE = 1; - const unsigned short IMPORT_RULE = 3; - const unsigned short MEDIA_RULE = 4; - const unsigned short FONT_FACE_RULE = 5; - const unsigned short PAGE_RULE = 6; - const unsigned short NAMESPACE_RULE = 10; - readonly attribute unsigned short type; - - // Parsing and serialization - attribute DOMString cssText; - - // Context - readonly attribute CSSRule parentRule; - readonly attribute CSSStyleSheet parentStyleSheet; -}; - -interface CSSStyleRule : CSSRule { - attribute DOMString selectorText; - readonly attribute CSSStyleDeclaration style; -}; - -interface CSSImportRule : CSSRule { - readonly attribute DOMString href; - [PutForwards=mediaText] readonly attribute MediaList media; - readonly attribute CSSStyleSheet styleSheet; -}; - -interface CSSMediaRule : CSSRule { - [PutForwards=mediaText] readonly attribute MediaList media; - readonly attribute CSSRuleList cssRules; - unsigned long insertRule(DOMString rule, unsigned long index); - void deleteRule(unsigned long index); -}; - -interface CSSFontFaceRule : CSSRule { - readonly attribute CSSStyleDeclaration style; -}; - -interface CSSPageRule : CSSRule { - attribute DOMString selectorText; - readonly attribute CSSStyleDeclaration style; -}; - -interface CSSNamespaceRule : CSSRule { - readonly attribute DOMString namespaceURI; - readonly attribute DOMString? prefix; -}; - -interface CSSStyleDeclaration { - attribute DOMString cssText; - - readonly attribute unsigned long length; - DOMString item(unsigned long index); - - DOMString getPropertyValue(DOMString property); - DOMString getPropertyPriority(DOMString property); - void setProperty(DOMString property, DOMString value, optional DOMString priority); - DOMString removeProperty(DOMString property); - - readonly attribute CSSStyleDeclarationValue values; - - readonly attribute CSSRule parentRule; - - // CSS Properties - attribute DOMString azimuth; - attribute DOMString background; - attribute DOMString backgroundAttachment; - attribute DOMString backgroundColor; - attribute DOMString backgroundImage; - attribute DOMString backgroundPosition; - attribute DOMString backgroundRepeat; - attribute DOMString border; - attribute DOMString borderCollapse; - attribute DOMString borderColor; - attribute DOMString borderSpacing; - attribute DOMString borderStyle; - attribute DOMString borderTop; - attribute DOMString borderRight; - attribute DOMString borderBottom; - attribute DOMString borderLeft; - attribute DOMString borderTopColor; - attribute DOMString borderRightColor; - attribute DOMString borderBottomColor; - attribute DOMString borderLeftColor; - attribute DOMString borderTopStyle; - attribute DOMString borderRightStyle; - attribute DOMString borderBottomStyle; - attribute DOMString borderLeftStyle; - attribute DOMString borderTopWidth; - attribute DOMString borderRightWidth; - attribute DOMString borderBottomWidth; - attribute DOMString borderLeftWidth; - attribute DOMString borderWidth; - attribute DOMString bottom; - attribute DOMString captionSide; - attribute DOMString clear; - attribute DOMString clip; - attribute DOMString color; - attribute DOMString content; - attribute DOMString counterIncrement; - attribute DOMString counterReset; - attribute DOMString cue; - attribute DOMString cueAfter; - attribute DOMString cueBefore; - attribute DOMString cursor; - attribute DOMString direction; - attribute DOMString display; - attribute DOMString elevation; - attribute DOMString emptyCells; - attribute DOMString cssFloat; - attribute DOMString font; - attribute DOMString fontFamily; - attribute DOMString fontSize; - attribute DOMString fontSizeAdjust; - attribute DOMString fontStretch; - attribute DOMString fontStyle; - attribute DOMString fontVariant; - attribute DOMString fontWeight; - attribute DOMString height; - attribute DOMString left; - attribute DOMString letterSpacing; - attribute DOMString lineHeight; - attribute DOMString listStyle; - attribute DOMString listStyleImage; - attribute DOMString listStylePosition; - attribute DOMString listStyleType; - attribute DOMString margin; - attribute DOMString marginTop; - attribute DOMString marginRight; - attribute DOMString marginBottom; - attribute DOMString marginLeft; - attribute DOMString marks; - attribute DOMString maxHeight; - attribute DOMString maxWidth; - attribute DOMString minHeight; - attribute DOMString minWidth; - attribute DOMString orphans; - attribute DOMString outline; - attribute DOMString outlineColor; - attribute DOMString outlineStyle; - attribute DOMString outlineWidth; - attribute DOMString overflow; - attribute DOMString padding; - attribute DOMString paddingTop; - attribute DOMString paddingRight; - attribute DOMString paddingBottom; - attribute DOMString paddingLeft; - attribute DOMString page; - attribute DOMString pageBreakAfter; - attribute DOMString pageBreakBefore; - attribute DOMString pageBreakInside; - attribute DOMString pause; - attribute DOMString pauseAfter; - attribute DOMString pauseBefore; - attribute DOMString pitch; - attribute DOMString pitchRange; - attribute DOMString playDuring; - attribute DOMString position; - attribute DOMString quotes; - attribute DOMString richness; - attribute DOMString right; - attribute DOMString size; - attribute DOMString speak; - attribute DOMString speakHeader; - attribute DOMString speakNumeral; - attribute DOMString speakPunctuation; - attribute DOMString speechRate; - attribute DOMString stress; - attribute DOMString tableLayout; - attribute DOMString textAlign; - attribute DOMString textDecoration; - attribute DOMString textIndent; - attribute DOMString textShadow; - attribute DOMString textTransform; - attribute DOMString top; - attribute DOMString unicodeBidi; - attribute DOMString verticalAlign; - attribute DOMString visibility; - attribute DOMString voiceFamily; - attribute DOMString volume; - attribute DOMString whiteSpace; - attribute DOMString widows; - attribute DOMString width; - attribute DOMString wordSpacing; - attribute DOMString zIndex; -}; - -interface CSSStyleDeclarationValue { - // ... - - // CSS Properties - -}; - -interface CSSPropertyValue { - attribute DOMString cssText; -}; - -[NoInterfaceObject] interface CSSMapValue { - getter CSSValue (DOMString name); -}; - -[NoInterfaceObject] interface CSSPropertyValueList { - readonly attribute CSSValue[] list; -}; - -[NoInterfaceObject] interface CSSComponentValue { - readonly attribute DOMString type; - attribute any value; -}; - -[NoInterfaceObject] interface CSSStringComponentValue { - attribute DOMString string; -}; - -[NoInterfaceObject] interface CSSKeywordComponentValue { - attribute DOMString keyword; -}; - -[NoInterfaceObject] interface CSSIdentifierComponentValue { - attribute DOMString identifier; -}; - -[NoInterfaceObject] interface CSSColorComponentValue { - attribute short red; - attribute short green; - attribute short blue; - attribute float alpha; -}; - -[NoInterfaceObject] interface CSSLengthComponentValue { - attribute float em; - attribute float ex; - attribute float px; - // figure out what to do with absolute lengths -}; - -[NoInterfaceObject] interface CSSPercentageComponentValue { - attribute float percent; -}; - -[NoInterfaceObject] interface CSSURLComponentValue { - attribute DOMString? url; -}; - -[NoInterfaceObject] interface ElementCSSInlineStyle { - readonly attribute CSSStyleDeclaration style; -}; - -//partial interface Window { -// CSSStyleDeclaration getComputedStyle(Element elt); -// CSSStyleDeclaration getComputedStyle(Element elt, DOMString pseudoElt); -//}; diff --git a/testing/web-platform/tests/html/dom/resources/interfaces.idl b/testing/web-platform/tests/interfaces/html.idl similarity index 98% rename from testing/web-platform/tests/html/dom/resources/interfaces.idl rename to testing/web-platform/tests/interfaces/html.idl index 26c8cff17a9b..e51b2a12b223 100644 --- a/testing/web-platform/tests/html/dom/resources/interfaces.idl +++ b/testing/web-platform/tests/interfaces/html.idl @@ -168,7 +168,7 @@ interface HTMLLinkElement : HTMLElement { [CEReactions] attribute USVString href; [CEReactions] attribute DOMString? crossOrigin; [CEReactions] attribute DOMString rel; - // [CEReactions] attribute RequestDestination as; // (default "") XXX TODO + [CEReactions] attribute DOMString as; // (default "") [CEReactions, SameObject, PutForwards=value] readonly attribute DOMTokenList relList; [CEReactions] attribute DOMString media; [CEReactions] attribute DOMString nonce; @@ -1621,19 +1621,22 @@ interface DocumentAndElementEventHandlers { [NoInterfaceObject] interface WindowEventHandlers { - attribute EventHandler onafterprint; - attribute EventHandler onbeforeprint; - attribute OnBeforeUnloadEventHandler onbeforeunload; - attribute EventHandler onhashchange; - attribute EventHandler onlanguagechange; - attribute EventHandler onmessage; - attribute EventHandler onoffline; - attribute EventHandler ononline; - attribute EventHandler onpagehide; - attribute EventHandler onpageshow; - attribute EventHandler onpopstate; - attribute EventHandler onstorage; - attribute EventHandler onunload; + attribute EventHandler onafterprint; + attribute EventHandler onbeforeprint; + attribute OnBeforeUnloadEventHandler onbeforeunload; + attribute EventHandler onhashchange; + attribute EventHandler onlanguagechange; + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; + attribute EventHandler onoffline; + attribute EventHandler ononline; + attribute EventHandler onpagehide; + attribute EventHandler onpageshow; + attribute EventHandler onpopstate; + attribute EventHandler onrejectionhandled; + attribute EventHandler onstorage; + attribute EventHandler onunhandledrejection; + attribute EventHandler onunload; }; typedef (DOMString or Function) TimerHandler; @@ -1871,23 +1874,24 @@ interface MessageChannel { readonly attribute MessagePort port2; }; -[Exposed=(Window,Worker)] +[Exposed=(Window,Worker), Transferable] interface MessagePort : EventTarget { - void postMessage(any message, optional sequence transfer); + void postMessage(any message, optional sequence transfer = []); void start(); void close(); // event handlers - attribute EventHandler onmessage; + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; }; -// MessagePort implements Transferable; -[Constructor(DOMString channel), Exposed=(Window,Worker)] +[Constructor(DOMString name), Exposed=(Window,Worker)] interface BroadcastChannel : EventTarget { readonly attribute DOMString name; void postMessage(any message); void close(); - attribute EventHandler onmessage; + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; }; [Exposed=Worker] @@ -1906,9 +1910,13 @@ interface WorkerGlobalScope : EventTarget { }; [Global=(Worker,DedicatedWorker),Exposed=DedicatedWorker] -/*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope { - void postMessage(any message, optional sequence transfer); - attribute EventHandler onmessage; +interface DedicatedWorkerGlobalScope : WorkerGlobalScope { + void postMessage(any message, optional sequence transfer = []); + + void close(); + + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; }; [Global=(Worker,SharedWorker),Exposed=SharedWorker] diff --git a/testing/web-platform/tests/interfaces/touchevents.idl b/testing/web-platform/tests/interfaces/touchevents.idl new file mode 100644 index 000000000000..81eec0185c25 --- /dev/null +++ b/testing/web-platform/tests/interfaces/touchevents.idl @@ -0,0 +1,10 @@ +interface Touch { + readonly attribute long identifier; + readonly attribute EventTarget target; + readonly attribute long screenX; + readonly attribute long screenY; + readonly attribute long clientX; + readonly attribute long clientY; + readonly attribute long pageX; + readonly attribute long pageY; +}; diff --git a/testing/web-platform/tests/interfaces/uievents.idl b/testing/web-platform/tests/interfaces/uievents.idl new file mode 100644 index 000000000000..bac832ba436d --- /dev/null +++ b/testing/web-platform/tests/interfaces/uievents.idl @@ -0,0 +1,60 @@ +[Constructor(DOMString type, optional UIEventInit eventInitDict)] +interface UIEvent : Event { + readonly attribute WindowProxy? view; + readonly attribute long detail; +}; + +dictionary UIEventInit : EventInit { + WindowProxy? view = null; + long detail = 0; +}; + +[Constructor(DOMString typeArg, optional MouseEventInit mouseEventInitDict)] +interface MouseEvent : UIEvent { + readonly attribute long screenX; + readonly attribute long screenY; + readonly attribute long clientX; + readonly attribute long clientY; + readonly attribute boolean ctrlKey; + readonly attribute boolean shiftKey; + readonly attribute boolean altKey; + readonly attribute boolean metaKey; + readonly attribute short button; + readonly attribute EventTarget? relatedTarget; + // Introduced in DOM Level 3 + readonly attribute unsigned short buttons; + boolean getModifierState (DOMString keyArg); +}; + +dictionary MouseEventInit : EventModifierInit { + long screenX = 0; + long screenY = 0; + long clientX = 0; + long clientY = 0; + short button = 0; + unsigned short buttons = 0; + EventTarget? relatedTarget = null; +}; + +dictionary EventModifierInit : UIEventInit { + boolean ctrlKey = false; + boolean shiftKey = false; + boolean altKey = false; + boolean metaKey = false; + boolean keyModifierStateAltGraph = false; + boolean keyModifierStateCapsLock = false; + boolean keyModifierStateFn = false; + boolean keyModifierStateFnLock = false; + boolean keyModifierStateHyper = false; + boolean keyModifierStateNumLock = false; + boolean keyModifierStateOS = false; + boolean keyModifierStateScrollLock = false; + boolean keyModifierStateSuper = false; + boolean keyModifierStateSymbol = false; + boolean keyModifierStateSymbolLock = false; +}; + +partial interface MouseEvent { + // Deprecated in DOM Level 3 + void initMouseEvent (DOMString typeArg, boolean bubblesArg, boolean cancelableArg, Window? viewArg, long detailArg, long screenXArg, long screenYArg, long clientXArg, long clientYArg, boolean ctrlKeyArg, boolean altKeyArg, boolean shiftKeyArg, boolean metaKeyArg, short buttonArg, EventTarget? relatedTargetArg); +}; diff --git a/testing/web-platform/tests/interfaces/webrtc-pc.idl b/testing/web-platform/tests/interfaces/webrtc-pc.idl new file mode 100644 index 000000000000..133524a6cdf6 --- /dev/null +++ b/testing/web-platform/tests/interfaces/webrtc-pc.idl @@ -0,0 +1,657 @@ +dictionary RTCConfiguration { + sequence iceServers; + RTCIceTransportPolicy iceTransportPolicy = "all"; + RTCBundlePolicy bundlePolicy = "balanced"; + RTCRtcpMuxPolicy rtcpMuxPolicy = "require"; + DOMString peerIdentity; + sequence certificates; + [EnforceRange] + octet iceCandidatePoolSize = 0; +}; + +enum RTCIceCredentialType { + "password", + "token" +}; + +dictionary RTCIceServer { + required (DOMString or sequence) urls; + DOMString username; + DOMString credential; + RTCIceCredentialType credentialType = "password"; +}; + +enum RTCIceTransportPolicy { + "relay", + "all" +}; + +enum RTCBundlePolicy { + "balanced", + "max-compat", + "max-bundle" +}; + +enum RTCRtcpMuxPolicy { + // At risk due to lack of implementers' interest. + "negotiate", + "require" +}; + +dictionary RTCOfferAnswerOptions { + boolean voiceActivityDetection = true; +}; + +dictionary RTCOfferOptions : RTCOfferAnswerOptions { + boolean iceRestart = false; + boolean offerToReceiveAudio; + boolean offerToReceiveVideo; +}; + +dictionary RTCAnswerOptions : RTCOfferAnswerOptions { +}; + +[Constructor(optional RTCConfiguration configuration)] +interface RTCPeerConnection : EventTarget { + Promise createOffer(optional RTCOfferOptions options); + Promise createAnswer(optional RTCAnswerOptions options); + Promise setLocalDescription(RTCSessionDescriptionInit description); + readonly attribute RTCSessionDescription? localDescription; + readonly attribute RTCSessionDescription? currentLocalDescription; + readonly attribute RTCSessionDescription? pendingLocalDescription; + Promise setRemoteDescription(RTCSessionDescriptionInit description); + readonly attribute RTCSessionDescription? remoteDescription; + readonly attribute RTCSessionDescription? currentRemoteDescription; + readonly attribute RTCSessionDescription? pendingRemoteDescription; + Promise addIceCandidate((RTCIceCandidateInit or RTCIceCandidate) candidate); + readonly attribute RTCSignalingState signalingState; + readonly attribute RTCIceGatheringState iceGatheringState; + readonly attribute RTCIceConnectionState iceConnectionState; + readonly attribute RTCPeerConnectionState connectionState; + readonly attribute boolean? canTrickleIceCandidates; + static readonly attribute FrozenArray defaultIceServers; + RTCConfiguration getConfiguration(); + void setConfiguration(RTCConfiguration configuration); + void close(); + attribute EventHandler onnegotiationneeded; + attribute EventHandler onicecandidate; + attribute EventHandler onicecandidateerror; + attribute EventHandler onsignalingstatechange; + attribute EventHandler oniceconnectionstatechange; + attribute EventHandler onicegatheringstatechange; + attribute EventHandler onconnectionstatechange; + attribute EventHandler onfingerprintfailure; +}; + +partial interface RTCPeerConnection { + Promise createOffer(RTCSessionDescriptionCallback successCallback, + RTCPeerConnectionErrorCallback failureCallback, + optional RTCOfferOptions options); + Promise setLocalDescription(RTCSessionDescriptionInit description, + VoidFunction successCallback, + RTCPeerConnectionErrorCallback failureCallback); + Promise createAnswer(RTCSessionDescriptionCallback successCallback, + RTCPeerConnectionErrorCallback failureCallback); + Promise setRemoteDescription(RTCSessionDescriptionInit description, + VoidFunction successCallback, + RTCPeerConnectionErrorCallback failureCallback); + Promise addIceCandidate((RTCIceCandidateInit or RTCIceCandidate) candidate, + VoidFunction successCallback, + RTCPeerConnectionErrorCallback failureCallback); +}; + +enum RTCSignalingState { + "stable", + "have-local-offer", + "have-remote-offer", + "have-local-pranswer", + "have-remote-pranswer" +}; + +enum RTCIceGatheringState { + "new", + "gathering", + "complete" +}; + +enum RTCPeerConnectionState { + "new", + "connecting", + "connected", + "disconnected", + "failed", + "closed" +}; + +enum RTCIceConnectionState { + "new", + "checking", + "connected", + "completed", + "failed", + "disconnected", + "closed" +}; + +callback RTCPeerConnectionErrorCallback = void (DOMException error); + +callback RTCSessionDescriptionCallback = void (RTCSessionDescriptionInit description); + +callback RTCStatsCallback = void (RTCStatsReport report); + +enum RTCSdpType { + "offer", + "pranswer", + "answer", + "rollback" +}; + +[Constructor(RTCSessionDescriptionInit descriptionInitDict)] +interface RTCSessionDescription { + readonly attribute RTCSdpType type; + readonly attribute DOMString sdp; + serializer = {attribute}; +}; + +dictionary RTCSessionDescriptionInit { + required RTCSdpType type; + DOMString sdp = ""; +}; + +[Constructor(RTCIceCandidateInit candidateInitDict)] +interface RTCIceCandidate { + readonly attribute DOMString candidate; + readonly attribute DOMString? sdpMid; + readonly attribute unsigned short? sdpMLineIndex; + readonly attribute DOMString? foundation; + readonly attribute unsigned long? priority; + readonly attribute DOMString? ip; + readonly attribute RTCIceProtocol? protocol; + readonly attribute unsigned short? port; + readonly attribute RTCIceCandidateType? type; + readonly attribute RTCIceTcpCandidateType? tcpType; + readonly attribute DOMString? relatedAddress; + readonly attribute unsigned short? relatedPort; + readonly attribute DOMString? ufrag; + serializer = {candidate, sdpMid, sdpMLineIndex, ufrag}; +}; + +dictionary RTCIceCandidateInit { + DOMString candidate = ""; + DOMString? sdpMid = null; + unsigned short? sdpMLineIndex = null; + DOMString ufrag; +}; + +enum RTCIceProtocol { + "udp", + "tcp" +}; + +enum RTCIceTcpCandidateType { + "active", + "passive", + "so" +}; + +enum RTCIceCandidateType { + "host", + "srflx", + "prflx", + "relay" +}; + +[Constructor(DOMString type, optional RTCPeerConnectionIceEventInit eventInitDict)] +interface RTCPeerConnectionIceEvent : Event { + readonly attribute RTCIceCandidate? candidate; + readonly attribute DOMString? url; +}; + +dictionary RTCPeerConnectionIceEventInit : EventInit { + RTCIceCandidate? candidate; + DOMString? url; +}; + +[Constructor(DOMString type, RTCPeerConnectionIceErrorEventInit eventInitDict)] +interface RTCPeerConnectionIceErrorEvent : Event { + readonly attribute DOMString hostCandidate; + readonly attribute DOMString url; + readonly attribute unsigned short errorCode; + readonly attribute USVString errorText; +}; + +dictionary RTCPeerConnectionIceErrorEventInit : EventInit { + DOMString hostCandidate; + DOMString url; + required unsigned short errorCode; + USVString statusText; +}; + +enum RTCPriorityType { + "very-low", + "low", + "medium", + "high" +}; + +partial interface RTCPeerConnection { + static Promise generateCertificate(AlgorithmIdentifier keygenAlgorithm); +}; + +dictionary RTCCertificateExpiration { + [EnforceRange] + DOMTimeStamp expires; +}; + +interface RTCCertificate { + readonly attribute DOMTimeStamp expires; + readonly attribute FrozenArray fingerprints; + AlgorithmIdentifier getAlgorithm(); +}; + +partial interface RTCPeerConnection { + sequence getSenders(); + sequence getReceivers(); + sequence getTransceivers(); + RTCRtpSender addTrack(MediaStreamTrack track, + MediaStream... streams); + void removeTrack(RTCRtpSender sender); + RTCRtpTransceiver addTransceiver((MediaStreamTrack or DOMString) trackOrKind, + optional RTCRtpTransceiverInit init); + attribute EventHandler ontrack; +}; + +dictionary RTCRtpTransceiverInit { + RTCRtpTransceiverDirection direction = "sendrecv"; + sequence streams; + sequence sendEncodings; +}; + +enum RTCRtpTransceiverDirection { + "sendrecv", + "sendonly", + "recvonly", + "inactive" +}; + +interface RTCRtpSender { + readonly attribute MediaStreamTrack? track; + readonly attribute RTCDtlsTransport? transport; + readonly attribute RTCDtlsTransport? rtcpTransport; + static RTCRtpCapabilities getCapabilities(DOMString kind); + Promise setParameters(optional RTCRtpParameters parameters); + RTCRtpParameters getParameters(); + Promise replaceTrack(MediaStreamTrack withTrack); +}; + +dictionary RTCRtpParameters { + DOMString transactionId; + sequence encodings; + sequence headerExtensions; + RTCRtcpParameters rtcp; + sequence codecs; + RTCDegradationPreference degradationPreference = "balanced"; +}; + +dictionary RTCRtpEncodingParameters { + unsigned long ssrc; + RTCRtpRtxParameters rtx; + RTCRtpFecParameters fec; + RTCDtxStatus dtx; + boolean active; + RTCPriorityType priority; + unsigned long maxBitrate; + unsigned long maxFramerate; + DOMString rid; + double scaleResolutionDownBy = 1; +}; + +enum RTCDtxStatus { + "disabled", + "enabled" +}; + +enum RTCDegradationPreference { + "maintain-framerate", + "maintain-resolution", + "balanced" +}; + +dictionary RTCRtpRtxParameters { + unsigned long ssrc; +}; + +dictionary RTCRtpFecParameters { + unsigned long ssrc; +}; + +dictionary RTCRtcpParameters { + DOMString cname; + boolean reducedSize; +}; + +dictionary RTCRtpHeaderExtensionParameters { + DOMString uri; + unsigned short id; + boolean encrypted; +}; + +dictionary RTCRtpCodecParameters { + unsigned short payloadType; + DOMString mimeType; + unsigned long clockRate; + unsigned short channels = 1; + DOMString sdpFmtpLine; +}; + +dictionary RTCRtpCapabilities { + sequence codecs; + sequence headerExtensions; +}; + +dictionary RTCRtpCodecCapability { + DOMString mimeType; + unsigned long clockRate; + unsigned short channels = 1; + DOMString sdpFmtpLine; +}; + +dictionary RTCRtpHeaderExtensionCapability { + DOMString uri; +}; + +interface RTCRtpReceiver { + readonly attribute MediaStreamTrack track; + readonly attribute RTCDtlsTransport? transport; + readonly attribute RTCDtlsTransport? rtcpTransport; + static RTCRtpCapabilities getCapabilities(DOMString kind); + RTCRtpParameters getParameters(); + sequence getContributingSources(); +}; + +interface RTCRtpContributingSource { + readonly attribute DOMHighResTimeStamp timestamp; + readonly attribute unsigned long source; + readonly attribute byte? audioLevel; + readonly attribute boolean? voiceActivityFlag; +}; + +interface RTCRtpTransceiver { + readonly attribute DOMString? mid; + [SameObject] + readonly attribute RTCRtpSender sender; + [SameObject] + readonly attribute RTCRtpReceiver receiver; + readonly attribute boolean stopped; + readonly attribute RTCRtpTransceiverDirection direction; + readonly attribute RTCRtpTransceiverDirection? currentDirection; + void setDirection(RTCRtpTransceiverDirection direction); + void stop(); + void setCodecPreferences(sequence codecs); +}; + +interface RTCDtlsTransport { + readonly attribute RTCIceTransport transport; + readonly attribute RTCDtlsTransportState state; + sequence getRemoteCertificates(); + attribute EventHandler onstatechange; +}; + +enum RTCDtlsTransportState { + "new", + "connecting", + "connected", + "closed", + "failed" +}; + +dictionary RTCDtlsFingerprint { + DOMString algorithm; + DOMString value; +}; + +interface RTCIceTransport { + readonly attribute RTCIceRole role; + readonly attribute RTCIceComponent component; + readonly attribute RTCIceTransportState state; + readonly attribute RTCIceGathererState gatheringState; + sequence getLocalCandidates(); + sequence getRemoteCandidates(); + RTCIceCandidatePair? getSelectedCandidatePair(); + RTCIceParameters? getLocalParameters(); + RTCIceParameters? getRemoteParameters(); + attribute EventHandler onstatechange; + attribute EventHandler ongatheringstatechange; + attribute EventHandler onselectedcandidatepairchange; +}; + +dictionary RTCIceParameters { + DOMString usernameFragment; + DOMString password; +}; + +dictionary RTCIceCandidatePair { + RTCIceCandidate local; + RTCIceCandidate remote; +}; + +enum RTCIceGathererState { + "new", + "gathering", + "complete" +}; + +enum RTCIceTransportState { + "new", + "checking", + "connected", + "completed", + "failed", + "disconnected", + "closed" +}; + +enum RTCIceRole { + "controlling", + "controlled" +}; + +enum RTCIceComponent { + "rtp", + "rtcp" +}; + +[Constructor(DOMString type, RTCTrackEventInit eventInitDict)] +interface RTCTrackEvent : Event { + readonly attribute RTCRtpReceiver receiver; + readonly attribute MediaStreamTrack track; + readonly attribute FrozenArray streams; + readonly attribute RTCRtpTransceiver transceiver; +}; + +dictionary RTCTrackEventInit : EventInit { + required RTCRtpReceiver receiver; + required MediaStreamTrack track; + sequence streams = []; + required RTCRtpTransceiver transceiver; +}; + +partial interface RTCPeerConnection { + readonly attribute RTCSctpTransport? sctp; + RTCDataChannel createDataChannel([TreatNullAs=EmptyString] USVString label, + optional RTCDataChannelInit dataChannelDict); + attribute EventHandler ondatachannel; +}; + +interface RTCSctpTransport { + readonly attribute RTCDtlsTransport transport; + readonly attribute unsigned long maxMessageSize; +}; + +interface RTCDataChannel : EventTarget { + readonly attribute USVString label; + readonly attribute boolean ordered; + readonly attribute unsigned short? maxPacketLifeTime; + readonly attribute unsigned short? maxRetransmits; + readonly attribute USVString protocol; + readonly attribute boolean negotiated; + readonly attribute unsigned short? id; + readonly attribute RTCPriorityType priority; + readonly attribute RTCDataChannelState readyState; + readonly attribute unsigned long bufferedAmount; + attribute unsigned long bufferedAmountLowThreshold; + attribute EventHandler onopen; + attribute EventHandler onbufferedamountlow; + attribute EventHandler onerror; + attribute EventHandler onclose; + void close(); + attribute EventHandler onmessage; + attribute DOMString binaryType; + void send(USVString data); + void send(Blob data); + void send(ArrayBuffer data); + void send(ArrayBufferView data); +}; + +dictionary RTCDataChannelInit { + boolean ordered = true; + unsigned short maxPacketLifeTime; + unsigned short maxRetransmits; + USVString protocol = ""; + boolean negotiated = false; + [EnforceRange] + unsigned short id; + RTCPriorityType priority = "low"; +}; + +enum RTCDataChannelState { + "connecting", + "open", + "closing", + "closed" +}; + +[Constructor(DOMString type, RTCDataChannelEventInit eventInitDict)] +interface RTCDataChannelEvent : Event { + readonly attribute RTCDataChannel channel; +}; + +dictionary RTCDataChannelEventInit : EventInit { + required RTCDataChannel channel; +}; + +partial interface RTCRtpSender { + readonly attribute RTCDTMFSender? dtmf; +}; + +interface RTCDTMFSender : EventTarget { + void insertDTMF(DOMString tones, + optional unsigned long duration = 100, + optional unsigned long interToneGap = 70); + attribute EventHandler ontonechange; + readonly attribute DOMString toneBuffer; +}; + +[Constructor(DOMString type, RTCDTMFToneChangeEventInit eventInitDict)] +interface RTCDTMFToneChangeEvent : Event { + readonly attribute DOMString tone; +}; + +dictionary RTCDTMFToneChangeEventInit : EventInit { + required DOMString tone; +}; + +partial interface RTCPeerConnection { + Promise getStats(optional MediaStreamTrack? selector = null); +}; + +interface RTCStatsReport { + readonly maplike; +}; + +dictionary RTCStats { + DOMHighResTimeStamp timestamp; + RTCStatsType type; + DOMString id; +}; + +enum RTCStatsType { +}; + +[Global, + Exposed=RTCIdentityProviderGlobalScope] +interface RTCIdentityProviderGlobalScope : WorkerGlobalScope { + readonly attribute RTCIdentityProviderRegistrar rtcIdentityProvider; +}; + +[Exposed=RTCIdentityProviderGlobalScope] +interface RTCIdentityProviderRegistrar { + void register(RTCIdentityProvider idp); +}; + +dictionary RTCIdentityProvider { + required GenerateAssertionCallback generateAssertion; + required ValidateAssertionCallback validateAssertion; +}; + +callback GenerateAssertionCallback = Promise (DOMString contents, + DOMString origin, + RTCIdentityProviderOptions options); + +callback ValidateAssertionCallback = Promise (DOMString assertion, + DOMString origin); + +dictionary RTCIdentityAssertionResult { + required RTCIdentityProviderDetails idp; + required DOMString assertion; +}; + +dictionary RTCIdentityProviderDetails { + required DOMString domain; + DOMString protocol = "default"; +}; + +dictionary RTCIdentityValidationResult { + required DOMString identity; + required DOMString contents; +}; + +partial interface RTCPeerConnection { + void setIdentityProvider(DOMString provider, + optional RTCIdentityProviderOptions options); + Promise getIdentityAssertion(); + readonly attribute Promise peerIdentity; + readonly attribute DOMString? idpLoginUrl; + readonly attribute DOMString? idpErrorInfo; +}; + +dictionary RTCIdentityProviderOptions { + DOMString protocol = "default"; + DOMString usernameHint; + DOMString peerIdentity; +}; + +[Constructor(DOMString idp, DOMString name)] +interface RTCIdentityAssertion { + attribute DOMString idp; + attribute DOMString name; +}; + +partial dictionary MediaStreamConstraints { + DOMString peerIdentity; +}; + +partial interface MediaStreamTrack { + readonly attribute boolean isolated; + attribute EventHandler onisolationchange; +}; + +[Exposed=Window, + Constructor(DOMString type, RTCErrorEventInit eventInitDict)] +interface RTCErrorEvent : Event { + readonly attribute RTCError? error; +}; + +dictionary RTCErrorEventInit : EventInit { + RTCError? error = null; +}; diff --git a/testing/web-platform/tests/keyboard-lock/idlharness.https.html b/testing/web-platform/tests/keyboard-lock/idlharness.https.html new file mode 100644 index 000000000000..6fabb4117436 --- /dev/null +++ b/testing/web-platform/tests/keyboard-lock/idlharness.https.html @@ -0,0 +1,41 @@ + + + +Keyboard Lock IDL tests + + + + + + + + + + + +
+ + diff --git a/testing/web-platform/tests/keyboard-lock/navigator-cancelKeyboardLock.https.html b/testing/web-platform/tests/keyboard-lock/navigator-cancelKeyboardLock.https.html new file mode 100644 index 000000000000..10fd50d3a79e --- /dev/null +++ b/testing/web-platform/tests/keyboard-lock/navigator-cancelKeyboardLock.https.html @@ -0,0 +1,12 @@ + + + + diff --git a/testing/web-platform/tests/keyboard-lock/navigator-requestKeyboardLock-two-parallel-requests.https.html b/testing/web-platform/tests/keyboard-lock/navigator-requestKeyboardLock-two-parallel-requests.https.html new file mode 100644 index 000000000000..8e84d14d465e --- /dev/null +++ b/testing/web-platform/tests/keyboard-lock/navigator-requestKeyboardLock-two-parallel-requests.https.html @@ -0,0 +1,15 @@ + + + + diff --git a/testing/web-platform/tests/keyboard-lock/navigator-requestKeyboardLock-two-sequential-requests.https.html b/testing/web-platform/tests/keyboard-lock/navigator-requestKeyboardLock-two-sequential-requests.https.html new file mode 100644 index 000000000000..30f490544956 --- /dev/null +++ b/testing/web-platform/tests/keyboard-lock/navigator-requestKeyboardLock-two-sequential-requests.https.html @@ -0,0 +1,14 @@ + + + + diff --git a/testing/web-platform/tests/keyboard-lock/navigator-requestKeyboardLock.https.html b/testing/web-platform/tests/keyboard-lock/navigator-requestKeyboardLock.https.html new file mode 100644 index 000000000000..e6e0121e75ec --- /dev/null +++ b/testing/web-platform/tests/keyboard-lock/navigator-requestKeyboardLock.https.html @@ -0,0 +1,13 @@ + + + + diff --git a/testing/web-platform/tests/lint b/testing/web-platform/tests/lint index d2e5e18cfe06..28434bab3242 100755 --- a/testing/web-platform/tests/lint +++ b/testing/web-platform/tests/lint @@ -8,4 +8,5 @@ except ImportError: '"git submodule update --init --recursive"?') sys.exit(2) -sys.exit(0 if lint.main() == 0 else 1) +args = lint.parse_args() +sys.exit(0 if lint.main(**vars(args)) == 0 else 1) diff --git a/testing/web-platform/tests/lint.whitelist b/testing/web-platform/tests/lint.whitelist index d1514d9d4930..e26431f9a9ff 100644 --- a/testing/web-platform/tests/lint.whitelist +++ b/testing/web-platform/tests/lint.whitelist @@ -145,6 +145,7 @@ TRAILING WHITESPACE:webgl/tools/*.patch SET TIMEOUT: *-manual.* SET TIMEOUT: 2dcontext/* SET TIMEOUT: annotation-model/scripts/ajv.min.js +SET TIMEOUT: apng/animated-png-timeout.html SET TIMEOUT: cookies/resources/testharness-helpers.js SET TIMEOUT: common/reftest-wait.js SET TIMEOUT: conformance-checkers/* @@ -171,6 +172,7 @@ SET TIMEOUT: old-tests/submission/Opera/script_scheduling/* SET TIMEOUT: old-tests/webdriver/timeouts/res/implicit_waits_tests.html SET TIMEOUT: page-visibility/resources/pagevistestharness.js SET TIMEOUT: payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html +SET TIMEOUT: payment-request/payment-request-response-id.html SET TIMEOUT: pointerevents/pointerevent_support.js SET TIMEOUT: preload/single-download-preload.html SET TIMEOUT: resource-timing/resource-timing.js @@ -213,6 +215,9 @@ SET TIMEOUT: XMLHttpRequest/xmlhttprequest-timeout-reused.html SET TIMEOUT: XMLHttpRequest/resources/init.htm SET TIMEOUT: XMLHttpRequest/resources/xmlhttprequest-timeout.js +# Intentional use of setTimeout +SET TIMEOUT: html/webappapis/timers/* + # CI scripts PRINT STATEMENT:check_stability.py W3C-TEST.ORG:check_stability.py @@ -763,3 +768,12 @@ CSS-COLLIDING-SUPPORT-NAME: css/CSS2/css1/support/pattern-gg-gr.png CSS-COLLIDING-SUPPORT-NAME: css/css-display-3/support/util.js CSS-COLLIDING-SUPPORT-NAME: css/CSS2/normal-flow/support/replaced-min-max-1.png CSS-COLLIDING-SUPPORT-NAME: css/vendor-imports/mozilla/mozilla-central-reftests/ui3/support/replaced-min-max-1.png + +# TODO https://github.com/w3c/web-platform-tests/issues/5770 +MISSING-LINK: css/geometry-1/DOMMatrix-css-string.worker.js +MISSING-LINK: css/geometry-1/WebKitCSSMatrix.worker.js + +WEBIDL2.JS:.gitmodules + +# Manual test that uses console.logs for feedback +CONSOLE:payment-request/payment-request-response-id.html diff --git a/testing/web-platform/tests/magnetometer/Magnetometer.https.html b/testing/web-platform/tests/magnetometer/Magnetometer.https.html new file mode 100644 index 000000000000..bad18f1dea8e --- /dev/null +++ b/testing/web-platform/tests/magnetometer/Magnetometer.https.html @@ -0,0 +1,16 @@ + + +Magnetometer Test + + + + + +
+ + diff --git a/testing/web-platform/tests/magnetometer/Magnetometer_insecure_context.html b/testing/web-platform/tests/magnetometer/Magnetometer_insecure_context.html new file mode 100644 index 000000000000..452bfc1c6eef --- /dev/null +++ b/testing/web-platform/tests/magnetometer/Magnetometer_insecure_context.html @@ -0,0 +1,20 @@ + + +Magnetometer Test: insecure context + + + + + +
+

Precondition

+
    +
  1. + Run test in an insecure context, e.g. http://example.com/. +
  2. +
+ diff --git a/testing/web-platform/tests/magnetometer/Magnetometer_onerror-manual.https.html b/testing/web-platform/tests/magnetometer/Magnetometer_onerror-manual.https.html new file mode 100644 index 000000000000..3cd62db8a225 --- /dev/null +++ b/testing/web-platform/tests/magnetometer/Magnetometer_onerror-manual.https.html @@ -0,0 +1,20 @@ + + +Magnetometer Test: onerror + + + + + +
+

Precondition

+
    +
  1. + Disable the Magnetometer Sensor or run test on a device without Magnetometer Sensor. +
  2. +
+ diff --git a/testing/web-platform/tests/magnetometer/idlharness.https.html b/testing/web-platform/tests/magnetometer/idlharness.https.html index 00fdafee664f..55a0851e1ec6 100644 --- a/testing/web-platform/tests/magnetometer/idlharness.https.html +++ b/testing/web-platform/tests/magnetometer/idlharness.https.html @@ -2,7 +2,8 @@ Magnetometer Sensor IDL tests - + + @@ -18,24 +19,24 @@ interface Event { }; -interface EventTarget { -}; - -interface EventHandler { -}; - interface Error { }; dictionary EventInit { }; + +interface EventTarget { +}; + +interface EventHandler { +};
 [SecureContext]
 interface Sensor : EventTarget {
-  readonly attribute SensorState state;
-  readonly attribute SensorReading? reading;
+  readonly attribute boolean activated;
+  readonly attribute DOMHighResTimeStamp? timestamp;
   void start();
   void stop();
   attribute EventHandler onchange;
@@ -47,18 +48,6 @@ dictionary SensorOptions {
   double? frequency;
 };
 
-enum SensorState {
-  "idle",
-  "activating",
-  "activated",
-  "errored"
-};
-
-[SecureContext]
-interface SensorReading {
-  readonly attribute DOMHighResTimeStamp timeStamp;
-};
-
 [SecureContext, Constructor(DOMString type, SensorErrorEventInit errorEventInitDict)]
 interface SensorErrorEvent : Event {
   readonly attribute Error error;
@@ -67,42 +56,31 @@ interface SensorErrorEvent : Event {
 dictionary SensorErrorEventInit : EventInit {
   required Error error;
 };
-
 
 [Constructor(optional SensorOptions sensorOptions)]
 interface Magnetometer : Sensor {
-  readonly attribute MagnetometerReading? reading;
-};
-
-[Constructor(MagnetometerReadingInit magnetometerReadingInit)]
-interface MagnetometerReading : SensorReading {
-    readonly attribute double x;
-    readonly attribute double y;
-    readonly attribute double z;
-};
-
-dictionary MagnetometerReadingInit {
-  double x = 0;
-  double y = 0;
-  double z = 0;
+  readonly attribute unrestricted double? x;
+  readonly attribute unrestricted double? y;
+  readonly attribute unrestricted double? z;
 };
 
diff --git a/testing/web-platform/tests/magnetometer/support-iframe.html b/testing/web-platform/tests/magnetometer/support-iframe.html new file mode 100644 index 000000000000..5328f6273f0a --- /dev/null +++ b/testing/web-platform/tests/magnetometer/support-iframe.html @@ -0,0 +1,10 @@ + + + diff --git a/testing/web-platform/tests/media-capabilities/query.html b/testing/web-platform/tests/media-capabilities/decodingInfo.html similarity index 77% rename from testing/web-platform/tests/media-capabilities/query.html rename to testing/web-platform/tests/media-capabilities/decodingInfo.html index f1bd22ba1ae3..a0e0d342682b 100644 --- a/testing/web-platform/tests/media-capabilities/query.html +++ b/testing/web-platform/tests/media-capabilities/decodingInfo.html @@ -1,5 +1,5 @@ -MediaCapabilities.query() +MediaCapabilities.decodingInfo() diff --git a/testing/web-platform/tests/media-capabilities/idlharness.html b/testing/web-platform/tests/media-capabilities/idlharness.html index af0669bfd2a6..3efe5a644883 100644 --- a/testing/web-platform/tests/media-capabilities/idlharness.html +++ b/testing/web-platform/tests/media-capabilities/idlharness.html @@ -24,13 +24,19 @@ interface WorkerNavigator {
 dictionary MediaConfiguration {
-  required MediaConfigurationType type;
-
   VideoConfiguration video;
   AudioConfiguration audio;
 };
 
-enum MediaConfigurationType {
+dictionary MediaDecodingConfiguration : MediaConfiguration {
+  required MediaDecodingType type;
+};
+
+dictionary MediaEncodingConfiguration : MediaConfiguration {
+  required MediaEncodingType type;
+};
+
+enum MediaDecodingType {
   "file",
   "media-source",
 };
@@ -50,7 +56,7 @@ dictionary AudioConfiguration {
   unsigned long samplerate;
 };
 
-interface MediaDecodingAbility {
+interface MediaCapabilitiesInfo {
   readonly attribute boolean supported;
   readonly attribute boolean smooth;
   readonly attribute boolean powerEfficient;
@@ -68,7 +74,8 @@ partial interface WorkerNavigator {
 
 [Exposed=(Window, Worker)]
 interface MediaCapabilities {
-  Promise query(MediaConfiguration configuration);
+  Promise decodingInfo(MediaDecodingConfiguration configuration);
+  Promise encodingInfo(MediaEncodingConfiguration configuration);
 };
 
+ + + + + + + + + + +
+ + diff --git a/testing/web-platform/tests/mixed-content/imageset.https.sub.html b/testing/web-platform/tests/mixed-content/imageset.https.sub.html new file mode 100644 index 000000000000..dd371566161d --- /dev/null +++ b/testing/web-platform/tests/mixed-content/imageset.https.sub.html @@ -0,0 +1,31 @@ + + + + Mixed-Content: imageset tests + + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/navigation-timing/nav2_test_document_replaced.html b/testing/web-platform/tests/navigation-timing/nav2_test_document_replaced.html new file mode 100644 index 000000000000..b910f453d129 --- /dev/null +++ b/testing/web-platform/tests/navigation-timing/nav2_test_document_replaced.html @@ -0,0 +1,58 @@ + + + + + Navigation Timing 2 WPT + + + + + + + +

+ Description

+

+ This test validates that a PerformanceNavigatingTiming corresponding to a detached document can't access a different document's state.

+ + + diff --git a/testing/web-platform/tests/navigation-timing/nav2_test_frame_removed.html b/testing/web-platform/tests/navigation-timing/nav2_test_frame_removed.html new file mode 100644 index 000000000000..0bef297d4e7b --- /dev/null +++ b/testing/web-platform/tests/navigation-timing/nav2_test_frame_removed.html @@ -0,0 +1,27 @@ + + + + + Navigation Timing 2 WPT + + + + + + + +

+ Description

+

+ This test validates that PerformanceNavigationTiming::type()'s default value is navigate

+ + + diff --git a/testing/web-platform/tests/navigation-timing/resources/webperftestharness.js b/testing/web-platform/tests/navigation-timing/resources/webperftestharness.js index 750946dde20b..f9b56d986896 100644 --- a/testing/web-platform/tests/navigation-timing/resources/webperftestharness.js +++ b/testing/web-platform/tests/navigation-timing/resources/webperftestharness.js @@ -12,7 +12,6 @@ policies and contribution forms [3]. // Helper Functions for NavigationTiming W3C tests // -var performanceNamespace = window.performance; var timingAttributes = [ 'connectEnd', 'connectStart', @@ -36,32 +35,6 @@ var timingAttributes = [ 'unloadEventStart' ]; -var namespace_check = false; - -// -// All test() functions in the WebPerf test suite should use wp_test() instead. -// -// wp_test() validates the window.performance namespace exists prior to running tests and -// immediately shows a single failure if it does not. -// - -function wp_test(func, msg, properties) -{ - // only run the namespace check once - if (!namespace_check) - { - namespace_check = true; - - if (performanceNamespace === undefined || performanceNamespace == null) - { - // show a single error that window.performance is undefined - test(function() { assert_true(performanceNamespace !== undefined && performanceNamespace != null, "window.performance is defined and not null"); }, "window.performance is defined and not null.", {author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "}); - } - } - - test(func, msg, properties); -} - function test_namespace(child_name, skip_root) { if (skip_root === undefined) { @@ -129,16 +102,6 @@ function sleep_milliseconds(n) // Common helper functions // -function test_true(value, msg, properties) -{ - wp_test(function () { assert_true(value, msg); }, msg, properties); -} - -function test_equals(value, equals, msg, properties) -{ - wp_test(function () { assert_equals(value, equals, msg); }, msg, properties); -} - function test_greater_than(value, greater_than, msg, properties) { wp_test(function () { assert_true(value > greater_than, msg); }, msg, properties); diff --git a/testing/web-platform/tests/navigation-timing/test_document_open.html b/testing/web-platform/tests/navigation-timing/test_document_open.html index 078909520421..1986b3fb9862 100644 --- a/testing/web-platform/tests/navigation-timing/test_document_open.html +++ b/testing/web-platform/tests/navigation-timing/test_document_open.html @@ -7,6 +7,7 @@ + + diff --git a/testing/web-platform/tests/navigation-timing/test_navigation_attributes_exist.html b/testing/web-platform/tests/navigation-timing/test_navigation_attributes_exist.html index 465409ea413e..845523d1a2da 100644 --- a/testing/web-platform/tests/navigation-timing/test_navigation_attributes_exist.html +++ b/testing/web-platform/tests/navigation-timing/test_navigation_attributes_exist.html @@ -7,6 +7,7 @@ + diff --git a/testing/web-platform/tests/navigation-timing/test_navigation_redirectCount_none.html b/testing/web-platform/tests/navigation-timing/test_navigation_redirectCount_none.html index 2046b32cd643..eaaef4b514c7 100644 --- a/testing/web-platform/tests/navigation-timing/test_navigation_redirectCount_none.html +++ b/testing/web-platform/tests/navigation-timing/test_navigation_redirectCount_none.html @@ -7,6 +7,7 @@ + diff --git a/testing/web-platform/tests/navigation-timing/test_navigation_type_backforward.html b/testing/web-platform/tests/navigation-timing/test_navigation_type_backforward.html index b201c3adee83..b5920953cbd3 100644 --- a/testing/web-platform/tests/navigation-timing/test_navigation_type_backforward.html +++ b/testing/web-platform/tests/navigation-timing/test_navigation_type_backforward.html @@ -7,6 +7,7 @@ + + diff --git a/testing/web-platform/tests/navigation-timing/test_navigation_type_reload.html b/testing/web-platform/tests/navigation-timing/test_navigation_type_reload.html index 786d1ddca6c8..d3331b819726 100644 --- a/testing/web-platform/tests/navigation-timing/test_navigation_type_reload.html +++ b/testing/web-platform/tests/navigation-timing/test_navigation_type_reload.html @@ -7,6 +7,7 @@ + + + diff --git a/testing/web-platform/tests/navigation-timing/test_performance_attributes_exist_in_object.html b/testing/web-platform/tests/navigation-timing/test_performance_attributes_exist_in_object.html index 0464758c62b1..9035522aee99 100644 --- a/testing/web-platform/tests/navigation-timing/test_performance_attributes_exist_in_object.html +++ b/testing/web-platform/tests/navigation-timing/test_performance_attributes_exist_in_object.html @@ -7,6 +7,7 @@ + + diff --git a/testing/web-platform/tests/navigation-timing/test_timing_attributes_exist.html b/testing/web-platform/tests/navigation-timing/test_timing_attributes_exist.html index f3dea6838c40..5db07459b4e6 100644 --- a/testing/web-platform/tests/navigation-timing/test_timing_attributes_exist.html +++ b/testing/web-platform/tests/navigation-timing/test_timing_attributes_exist.html @@ -7,6 +7,7 @@ + diff --git a/testing/web-platform/tests/navigation-timing/test_timing_attributes_order.html b/testing/web-platform/tests/navigation-timing/test_timing_attributes_order.html index e3a0758f17b2..03c2619cb3e4 100644 --- a/testing/web-platform/tests/navigation-timing/test_timing_attributes_order.html +++ b/testing/web-platform/tests/navigation-timing/test_timing_attributes_order.html @@ -7,6 +7,7 @@ + + + + + + diff --git a/testing/web-platform/tests/orientation-sensor/OWNERS b/testing/web-platform/tests/orientation-sensor/OWNERS new file mode 100644 index 000000000000..cc7c3879319b --- /dev/null +++ b/testing/web-platform/tests/orientation-sensor/OWNERS @@ -0,0 +1,5 @@ +@zqzhang +@dontcallmedom +@tobie +@riju +@Honry diff --git a/testing/web-platform/tests/orientation-sensor/idlharness.https.html b/testing/web-platform/tests/orientation-sensor/idlharness.https.html new file mode 100644 index 000000000000..8f556ca31640 --- /dev/null +++ b/testing/web-platform/tests/orientation-sensor/idlharness.https.html @@ -0,0 +1,89 @@ + + +Orientation Sensor IDL tests + + + + + + + + +
+ +
+interface Event {
+};
+
+interface Error {
+};
+
+dictionary EventInit {
+};
+
+interface EventTarget {
+};
+
+interface EventHandler {
+};
+
+ +
+[SecureContext]
+interface Sensor : EventTarget {
+  readonly attribute boolean activated;
+  readonly attribute DOMHighResTimeStamp? timestamp;
+  void start();
+  void stop();
+  attribute EventHandler onchange;
+  attribute EventHandler onactivate;
+  attribute EventHandler onerror;
+};
+
+dictionary SensorOptions {
+  double? frequency;
+};
+
+[SecureContext, Constructor(DOMString type, SensorErrorEventInit errorEventInitDict)]
+interface SensorErrorEvent : Event {
+  readonly attribute Error error;
+};
+
+dictionary SensorErrorEventInit : EventInit {
+  required Error error;
+};
+
+ +
+typedef (Float32Array or Float64Array or DOMMatrix) RotationMatrixType;
+interface OrientationSensor : Sensor {
+  readonly attribute FrozenArray? quaternion;
+  void populateMatrix(RotationMatrixType targetMatrix);
+};
+
+[Constructor(optional SensorOptions sensorOptions)]
+interface AbsoluteOrientationSensor : OrientationSensor {
+};
+
+ + diff --git a/testing/web-platform/tests/page-visibility/prerender_call.html b/testing/web-platform/tests/page-visibility/prerender_call.html new file mode 100644 index 000000000000..ed9e54a1dd8e --- /dev/null +++ b/testing/web-platform/tests/page-visibility/prerender_call.html @@ -0,0 +1,22 @@ + + + + +Prerender test for Page Visibility API + + + + +

Description

+

This document validate that visibilityState of a target page was set to "prerender" when it has been prerendered.

+ + diff --git a/testing/web-platform/tests/page-visibility/resources/prerender_target.html b/testing/web-platform/tests/page-visibility/resources/prerender_target.html new file mode 100644 index 000000000000..73108e8ab9f2 --- /dev/null +++ b/testing/web-platform/tests/page-visibility/resources/prerender_target.html @@ -0,0 +1,13 @@ + + + + Document has been prerendered + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/payment-request/payment-request-id.https.html b/testing/web-platform/tests/payment-request/payment-request-id.https.html new file mode 100644 index 000000000000..8e3c34461706 --- /dev/null +++ b/testing/web-platform/tests/payment-request/payment-request-id.https.html @@ -0,0 +1,18 @@ + + + +Test for PaymentRequest identifier usage + + + + diff --git a/testing/web-platform/tests/payment-request/payment-request-response-id.html b/testing/web-platform/tests/payment-request/payment-request-response-id.html new file mode 100644 index 000000000000..a28f3b24c6f3 --- /dev/null +++ b/testing/web-platform/tests/payment-request/payment-request-response-id.html @@ -0,0 +1,140 @@ + + + + + + PaymentRequest identifier manual test + + +
+

PaymentRequest identifier manual test

+

Perform the following steps:

+
    +
  • Press 'Buy'
  • +
  • In the payment dialog make sure a payment app is selected
  • +
  • In the payment dialog press 'Pay'
  • +
  • In the launched payment app perform steps to do the payment
  • +
  • The response will be processed and below should display 'my_payment_id'
  • +
+

No payment will be processed.

+

Price: USD $55.00

+

+
+

+  
+
+
+
diff --git a/testing/web-platform/tests/pointerevents/extension/pointerevent_coalesced_events_attributes-manual.html b/testing/web-platform/tests/pointerevents/extension/pointerevent_coalesced_events_attributes-manual.html
index 4610806b3fca..89149468a5d2 100644
--- a/testing/web-platform/tests/pointerevents/extension/pointerevent_coalesced_events_attributes-manual.html
+++ b/testing/web-platform/tests/pointerevents/extension/pointerevent_coalesced_events_attributes-manual.html
@@ -77,8 +77,14 @@
                               test (function() {
                                 for (var i=0; i 0)
+                                    assert_greater_than_equal(coalescedEvents[i].timeStamp, coalescedEvents[i-1].timeStamp, 'Time stamps of coalesced events must be ascending.');
                                 }
                               }, expectedPointerType + ' pointermove coalesced events should all be marked as trusted.');
+                              test (function() {
+                                for (var i=1; i target0.getBoundingClientRect().left)&&
                             (event.clientX < target0.getBoundingClientRect().right)&&
                             (event.clientY > target0.getBoundingClientRect().top)&&
                             (event.clientY < target0.getBoundingClientRect().bottom),
                             "pointerleave should be received inside of target bounds");
                     });
-                    test_pointerEvent.done(); // complete test
+                    if (count >= 2)
+                      test_pointerEvent.done(); // complete test
                 });
             }
         
@@ -43,7 +55,7 @@
         

Pointer Event: Dispatch pointerleave (pen)

Test Description: - When a pointing device that supports hover (pen stylus) leaves the range of the digitizer while over an element, the pointerleave event must be dispatched. + When a pointing device that supports hover (pen stylus) leaves the range of the digitizer while over an element, the pointerleave event must be dispatched. In addition, all the pointer events' isPrimary should always be true when the pointing device leaves and enters the range of the digitizer again.


diff --git a/testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse-manual.html b/testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse-manual.html index 02bca85008e9..8afa04634bbd 100644 --- a/testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse-manual.html +++ b/testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse-manual.html @@ -41,8 +41,9 @@ on_event(document.getElementById("done"), "click", end_of_interaction); var target_list = ["target0", "target1"]; - var pointer_event_list = ["pointerdown"]; + var pointer_event_list = ["pointerdown" , "pointermove", "pointerup"]; var mouse_event_list = ["mousedown", "mouseup", "mousemove"]; + var last_pointer_event = null; target_list.forEach(function(targetId) { var target = document.getElementById(targetId); @@ -52,12 +53,16 @@ detected_pointertypes[event.pointerType] = true; var label = event.type + "@" + targetId; - test(function () { - assert_true(event.isPrimary); - }, "primary pointer " + label); + if (event.type == "pointerdown") { + test(function () { + assert_true(event.isPrimary); + }, "primary pointer " + label); + } if (label === "pointerdown@target0") event.preventDefault(); + + last_pointer_event = event; }); }); @@ -69,6 +74,11 @@ event_log.push(event.type + "@" + targetId); include_next_mousemove = (event.type == "mousedown"); + test(function() { + test(function () { + assert_equals(event.timeStamp, last_pointer_event.timeStamp, "The time stamp of the compat mouse event should be the same as its pointerevent"); + }); + }, event.type + "'s time stamp should be the same as " + last_pointer_event.type + "'s time stamp."); }); }); }); diff --git a/testing/web-platform/tests/preload/download-resources.html b/testing/web-platform/tests/preload/download-resources.html index 3a758cfa18d0..d4165e1c6aba 100644 --- a/testing/web-platform/tests/preload/download-resources.html +++ b/testing/web-platform/tests/preload/download-resources.html @@ -8,7 +8,7 @@ - + @@ -21,7 +21,7 @@ verifyPreloadAndRTSupport() verifyNumberOfDownloads("resources/dummy.js", 1); verifyNumberOfDownloads("resources/dummy.css", 1); - verifyNumberOfDownloads("/media/CanvasTest.ttf", 1); + verifyNumberOfDownloads("/fonts/CanvasTest.ttf", 1); verifyNumberOfDownloads("/media/white.mp4", 1); verifyNumberOfDownloads("/media/sound_5.oga", 1); verifyNumberOfDownloads("/media/foo.vtt", 1); diff --git a/testing/web-platform/tests/preload/onload-event.html b/testing/web-platform/tests/preload/onload-event.html index bd945cb42c70..684f84f9cb3f 100644 --- a/testing/web-platform/tests/preload/onload-event.html +++ b/testing/web-platform/tests/preload/onload-event.html @@ -18,7 +18,7 @@ - + diff --git a/testing/web-platform/tests/preload/preload-with-type.html b/testing/web-platform/tests/preload/preload-with-type.html index db68721f54e2..69c52c46ee36 100644 --- a/testing/web-platform/tests/preload/preload-with-type.html +++ b/testing/web-platform/tests/preload/preload-with-type.html @@ -31,7 +31,7 @@ - + diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_onconnectionavailable-manual.https.html b/testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_onconnectionavailable-manual.https.html index a24e03aba880..450cab212cab 100644 --- a/testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_onconnectionavailable-manual.https.html +++ b/testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_onconnectionavailable-manual.https.html @@ -1,6 +1,6 @@ -PresentationRequest.onconnectionavailable (manual test) +Firing a connectionavailable event at a controlling user agent @@ -17,43 +17,56 @@ // ---------- // DOM Object // ---------- - var presentBtn = document.getElementById("presentBtn"); + const presentBtn = document.getElementById('presentBtn'); // -------------------------------------------------------------------------- // Start New PresentationRequest.onconnectionavailable Test (success) - begin // -------------------------------------------------------------------------- - var startPresentation = function () { + presentBtn.onclick = () => { presentBtn.disabled = true; - promise_test(function (t) { - var connection; - t.add_cleanup(function() { - if(connection) - connection.terminate(); + + promise_test(t => { + let connection; + const request = new PresentationRequest(presentationUrls); + + t.add_cleanup(() => { + if (connection) { + connection.onconnect = () => { connection.terminate(); }; + if (connection.state === 'closed') + request.reconnect(connection.id); + else + connection.terminate(); + } }); - // Note: During starting a presentation, the connectionavailable event is fired (step 20) - // after the promise P is resolved (step 19). - return new Promise(function(resolve, reject) { - var request = new PresentationRequest(presentationUrls); - request.onconnectionavailable = function (evt) { - resolve(evt.connection); - }; - // This test fails if request.onconnectionavailable is not invoked although the presentation is started successfully - // or the presentation fails to be started - request.start().then(function(c) { - connection = c; - t.step_timeout(function() { assert_unreached('The connectionavailable event was not fired.'); }, 5000); - }, reject); - }).then(function(c) { + // Note: During starting a presentation, the connectionavailable event is fired (step 9) + // after the promise P is resolved (step 8). + return request.start().then(c => { connection = c; assert_equals(connection.state, 'connecting', 'The initial state of the presentation connection is "connecting".'); assert_true(!!connection.id, 'The connection ID is set.'); assert_true(typeof connection.id === 'string', 'The connection ID is a string.'); assert_true(connection instanceof PresentationConnection, 'The connection is an instance of PresentationConnection.'); + + const eventWatcher = new EventWatcher(t, request, 'connectionavailable'); + const timeout = new Promise((_, reject) => { + // This test fails if request.onconnectionavailable is not invoked although the presentation is started successfully + // or the presentation fails to be started. + t.step_timeout(() => { reject('The connectionavailable event was not fired (timeout).'); }, 5000);} + ); + return Promise.race([ eventWatcher.wait_for('connectionavailable'), timeout ]); + }).then(evt => { + assert_true(evt instanceof PresentationConnectionAvailableEvent, 'An event using PresentationConnectionAvailableEvent is fired.'); + assert_true(evt.isTrusted, 'The event is a trusted event.'); + assert_false(evt.bubbles, 'The event does not bubbles.'); + assert_false(evt.cancelable, 'The event is not cancelable.'); + assert_equals(evt.type, 'connectionavailable', 'The event name is "connectionavailable".'); + assert_equals(evt.target, request, 'event.target is the presentation request.'); + assert_true(evt.connection instanceof PresentationConnection, 'event.connection is a presentation connection.'); + assert_equals(evt.connection, connection, 'event.connection is set to the presentation which the promise is resolved with.'); }); - }, 'The connectionavailable event was fired successfully.'); + }); } - presentBtn.onclick = startPresentation; // ------------------------------------------------------------------------ // Start New PresentationRequest.onconnectionavailable Test (success) - end // ------------------------------------------------------------------------ diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_success.https.html b/testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_success.https.html index 4e1570e83ad2..70ea5a806e7b 100644 --- a/testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_success.https.html +++ b/testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_success.https.html @@ -1,43 +1,24 @@ -Presentation API PresentationRequest for Controlling User Agent (Success) +Constructing a PresentationRequest - + + \ No newline at end of file diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/defaultRequest.https.html b/testing/web-platform/tests/presentation-api/controlling-ua/defaultRequest.https.html new file mode 100644 index 000000000000..bc07e02748c7 --- /dev/null +++ b/testing/web-platform/tests/presentation-api/controlling-ua/defaultRequest.https.html @@ -0,0 +1,24 @@ + + +Setting a default presentation request + + + + + + diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/getAvailability.https.html b/testing/web-platform/tests/presentation-api/controlling-ua/getAvailability.https.html index 895e1dc27d1d..f8ccd7034032 100644 --- a/testing/web-platform/tests/presentation-api/controlling-ua/getAvailability.https.html +++ b/testing/web-platform/tests/presentation-api/controlling-ua/getAvailability.https.html @@ -16,33 +16,46 @@ // Presentation Availability Tests - begin // --------------------------------------- - promise_test(function(t) { - var availability; + promise_test(t => { + let availability; - var request = new PresentationRequest(presentationUrls); + const request = new PresentationRequest(presentationUrls); assert_true(request instanceof PresentationRequest, 'The request is an instance of PresentationRequest.'); - var promise = request.getAvailability(); + const promise = request.getAvailability(); assert_equals(promise, request.getAvailability(), 'If the PresentationRequest object has an unsettled Promise, getAvailability returns that Promise.'); function catchNotSupported(err) { assert_equals(err.name, 'NotSupportedError', 'getAvailability() rejects a Promise with a NotSupportedError exception, if the browser can find presentation displays only when starting a connection.') } - return promise.then(function (a) { + return promise.then(a => { availability = a; assert_true(availability instanceof PresentationAvailability, 'The promise is resolved with an instance of PresentationAvailability.'); assert_equals(typeof availability.value, 'boolean', 'The availability has an boolean value.'); - assert_true(availability.value, 'The availability value is true when any presentation display is available.'); - var newPromise = request.getAvailability(); - assert_not_equals(promise, newPromise, 'If the Promise from a previous call to getAvailability has already been settled, getAvailability returns a new Promise.'); + // The value of the presentation availability object is set to false, when the object is newly created. + const waitForChange = () => { + const eventWatcher = new EventWatcher(t, availability, 'change'); + return eventWatcher.wait_for('change'); + }; - return newPromise.then(function (newAvailability) { - assert_equals(availability, newAvailability, 'Promises from a PresentationRequest\'s getAvailability are resolved with the same PresentationAvailability object.'); + return (availability.value ? Promise.resolve() : waitForChange()).then(() => { + assert_true(availability.value, 'The availability value is true when any presentation display is available.'); + + const request2 = new PresentationRequest('https://example.com'); + return request2.getAvailability(); + }).then(a => { + assert_not_equals(availability, a, 'A presentation availability object is newly created if the presentation request has a newly added presentation URLs.'); + + const newPromise = request.getAvailability(); + assert_not_equals(promise, newPromise, 'If the Promise from a previous call to getAvailability has already been settled, getAvailability returns a new Promise.'); + + return newPromise.then(newAvailability => { + assert_equals(availability, newAvailability, 'Promises from a PresentationRequest\'s getAvailability are resolved with the same PresentationAvailability object.'); + }, catchNotSupported); }, catchNotSupported); }, catchNotSupported); }); - diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_success-manual.https.html b/testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_success-manual.https.html index c740f6d0021a..94c48d9840d1 100644 --- a/testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_success-manual.https.html +++ b/testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_success-manual.https.html @@ -7,48 +7,101 @@ +

Click the button below to start the manual test. Select a presentation device after the selection dialog is prompted. The test assumes that at least one presentation device is available. The test passes if a "PASS" result appears.

+ diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/support/iframe.html b/testing/web-platform/tests/presentation-api/controlling-ua/support/iframe.html index a37f0fcd8e0a..6c602d86a8a2 100644 --- a/testing/web-platform/tests/presentation-api/controlling-ua/support/iframe.html +++ b/testing/web-platform/tests/presentation-api/controlling-ua/support/iframe.html @@ -57,6 +57,21 @@ parent.window.postMessage(err.name, '*'); }); } + else if (ev.data.match(/^reconnect\?id=(.*)$/)) { + var presentationId = RegExp.$1; + request = new PresentationRequest(urls); + request.reconnect(presentationId) + .then(function (c) { + var result = { state: c.state, id: c.id }; + parent.window.postMessage(result, '*'); + c.onterminate = function() { + parent.window.postMessage('terminated', '*'); + }; + }) + .catch(function (err) { + parent.window.postMessage(err.name, '*'); + }); + } else if (ev.data === 'getAvailability') { request = new PresentationRequest(urls); request.getAvailability() diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnectionList_onconnectionavailable-manual.https.html b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnectionList_onconnectionavailable-manual.https.html new file mode 100644 index 000000000000..84971cbdf63b --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnectionList_onconnectionavailable-manual.https.html @@ -0,0 +1,78 @@ + + +Monitoring incoming presentation connections + + + + + + + +

Click the button below and select the available presentation display, to start the manual test.

+ + + + \ No newline at end of file diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_onclose-manual.https.html b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_onclose-manual.https.html new file mode 100644 index 000000000000..d6baad1c285d --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_onclose-manual.https.html @@ -0,0 +1,85 @@ + + +Closing a PresentationConnection + + + + + + + +

Click the button below and select the available presentation display, to start the manual test.

+ + + + \ No newline at end of file diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_onmessage-manual.https.html b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_onmessage-manual.https.html new file mode 100644 index 000000000000..4b05cdc9e895 --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_onmessage-manual.https.html @@ -0,0 +1,65 @@ + + +Receiving a message through PresentationConnection + + + + + + +

Click the button below and select the available presentation display, to start the manual test.

+ + + diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_send-manual.https.html b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_send-manual.https.html new file mode 100644 index 000000000000..f600a7fba236 --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_send-manual.https.html @@ -0,0 +1,97 @@ + + +Sending a message through PresentationConnection + + + + + + + +

Click the button below and select the available presentation display, to start the manual test.

+ + + diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_terminate-manual.https.html b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_terminate-manual.https.html new file mode 100644 index 000000000000..6484e97c5ab6 --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationConnection_terminate-manual.https.html @@ -0,0 +1,71 @@ + + +Terminating a presentation in a receiving browsing context + + + + + + + + +

Click the button below and select the available presentation display, to start the manual test.

+ + + + diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html index e0445562fc4a..67b8c43d5a1a 100644 --- a/testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html +++ b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html @@ -48,16 +48,9 @@ indexedDB.deleteDatabase(dbName); if (connection) { - if (connection.state === 'connecting') { - connection.onconnect = () => { - connection.terminate(); - } - } - else if (connection.state === 'closed') { - request.reconnect(connection.id).then(c => { - c.terminate(); - }); - } + connection.onconnect = () => { connection.terminate(); }; + if (connection.state === 'closed') + request.reconnect(connection.id); else connection.terminate(); } diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/idlharness-manual.https.html b/testing/web-platform/tests/presentation-api/receiving-ua/idlharness-manual.https.html index 8258211e3068..079bb094acff 100644 --- a/testing/web-platform/tests/presentation-api/receiving-ua/idlharness-manual.https.html +++ b/testing/web-platform/tests/presentation-api/receiving-ua/idlharness-manual.https.html @@ -35,16 +35,9 @@ log.innerHTML = json.log; document.body.appendChild(log); - if (connection.state === 'connecting') { - connection.onconnect = () => { - connection.terminate(); - } - } - else if (connection.state === 'closed') { - request.reconnect(connection.id).then(c => { - c.terminate(); - }); - } + connection.onconnect = () => { connection.terminate(); }; + if (connection.state === 'closed') + request.reconnect(connection.id); else connection.terminate(); }); diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnectionList_onconnectionavailable_receiving-ua.html b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnectionList_onconnectionavailable_receiving-ua.html new file mode 100644 index 000000000000..f6994504309a --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnectionList_onconnectionavailable_receiving-ua.html @@ -0,0 +1,82 @@ + + + +Monitoring incoming presentation connections + + + + + + + + diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_onclose_receiving-ua.html b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_onclose_receiving-ua.html new file mode 100644 index 000000000000..a7a633fd037e --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_onclose_receiving-ua.html @@ -0,0 +1,79 @@ + + + +Closing a PresentationConnection + + + + + + + + diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_onmessage_receiving-ua.html b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_onmessage_receiving-ua.html new file mode 100644 index 000000000000..93f0dca04ed1 --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_onmessage_receiving-ua.html @@ -0,0 +1,98 @@ + + +Receiving a message through PresentationConnection + + + + + + + + diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_send_receiving-ua.html b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_send_receiving-ua.html new file mode 100644 index 000000000000..bc482e9dfd2c --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_send_receiving-ua.html @@ -0,0 +1,45 @@ + + + +Sending a message through PresentationConnection + + + + + + diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_terminate_receiving-ua.html b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_terminate_receiving-ua.html new file mode 100644 index 000000000000..3a234aaa8339 --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationConnection_terminate_receiving-ua.html @@ -0,0 +1,23 @@ + + + +Terminating a presentation in a receiving browsing context + + + + + + diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html index a7be89722647..8edb88e1d780 100644 --- a/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html +++ b/testing/web-platform/tests/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html @@ -194,7 +194,7 @@ child.addEventListener('load', () => { resolve(); }); }) : Promise.resolve()).then(getClientUrls).then(urls => { - assert_true(urls.every(url => { return url !== new Request('../PresentationReceiver_create-manual.html').url }), + assert_true(urls.every(url => { return url !== new Request('../PresentationReceiver_create-manual.https.html').url }), 'A window client in a controlling user agent is not accessible to a service worker on a receiving user agent.'); }); }; diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/support/idlharness_receiving-ua.https.html b/testing/web-platform/tests/presentation-api/receiving-ua/support/idlharness_receiving-ua.html similarity index 100% rename from testing/web-platform/tests/presentation-api/receiving-ua/support/idlharness_receiving-ua.https.html rename to testing/web-platform/tests/presentation-api/receiving-ua/support/idlharness_receiving-ua.html diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/support/iframe.html b/testing/web-platform/tests/presentation-api/receiving-ua/support/iframe.html new file mode 100644 index 000000000000..61f18b8912d3 --- /dev/null +++ b/testing/web-platform/tests/presentation-api/receiving-ua/support/iframe.html @@ -0,0 +1,22 @@ + + +Helper functions invoked by a nested browsing context + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/support/stash.js b/testing/web-platform/tests/presentation-api/receiving-ua/support/stash.js index 616907d4f2c9..eb63bb862377 100644 --- a/testing/web-platform/tests/presentation-api/receiving-ua/support/stash.js +++ b/testing/web-platform/tests/presentation-api/receiving-ua/support/stash.js @@ -1,5 +1,5 @@ var Stash = function(inbound, outbound) { - this.stashPath = '/presentation-api/controlling-ua/support/stash.py?id='; + this.stashPath = '/presentation-api/receiving-ua/support/stash.py?id='; this.inbound = inbound; this.outbound = outbound; } @@ -28,6 +28,21 @@ Stash.prototype.send = function(result) { }) }; +// upload a test result to a stash on wptserve via navigator.sendBeacon +Stash.prototype.sendBeacon = function(result) { + if ('sendBeacon' in navigator) { + navigator.sendBeacon(this.stashPath + this.outbound, JSON.stringify({ type: 'data', data: result })); + } + // Note: The following could be discarded, since XHR in synchronous mode is now being deprecated. + else { + return new Promise(resolve, reject => { + const xhr = new XMLHttpRequest(); + xhr.open('POST', this.stashPath + this.outbound, false); + xhr.send(JSON.stringify({ type: 'data', data: result })); + }); + } +}; + // wait until a test result is uploaded to a stash on wptserve Stash.prototype.receive = function() { return new Promise((resolve, reject) => { diff --git a/testing/web-platform/tests/resource-timing/resource_TAO_match_origin.htm b/testing/web-platform/tests/resource-timing/resource_TAO_match_origin.htm new file mode 100644 index 000000000000..3ab239e90bbf --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_TAO_match_origin.htm @@ -0,0 +1,55 @@ + + + + +Resource Timing TAO tests + + + + + + + + + +

Description

+

This test validates that for a cross origin resource, the timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a case-sensitive match for the value of the origin of the current document.

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_TAO_match_wildcard.htm b/testing/web-platform/tests/resource-timing/resource_TAO_match_wildcard.htm new file mode 100644 index 000000000000..8b07b46672e6 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_TAO_match_wildcard.htm @@ -0,0 +1,55 @@ + + + + +Resource Timing TAO tests + + + + + + + + + +

Description

+

This test validates that for a cross origin resource, the timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a wildcard ("*").

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_TAO_multi.htm b/testing/web-platform/tests/resource-timing/resource_TAO_multi.htm new file mode 100644 index 000000000000..3b6c2e6b267b --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_TAO_multi.htm @@ -0,0 +1,55 @@ + + + + +Resource Timing TAO tests + + + + + + + + + +

Description

+

This test validates that for a cross origin resource, the timing allow check algorithm will pass when the HTTP response has multiple Timing-Allow-Origin header fields and the subsequent field value is separated by a comma.

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_TAO_null.htm b/testing/web-platform/tests/resource-timing/resource_TAO_null.htm new file mode 100644 index 000000000000..419de693e1f9 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_TAO_null.htm @@ -0,0 +1,55 @@ + + + + +Resource Timing TAO tests + + + + + + + + + +

Description

+

This test validates that for a cross origin resource, the timing allow check algorithm will fail when the value of Timing-Allow-Origin is null.

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_TAO_origin.htm b/testing/web-platform/tests/resource-timing/resource_TAO_origin.htm new file mode 100644 index 000000000000..dc5efa43ee2b --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_TAO_origin.htm @@ -0,0 +1,55 @@ + + + + +Resource Timing TAO tests + + + + + + + + + +

Description

+

This test validates that for a cross origin resource, the timing allow check algorithm will pass when the value of Timing-Allow-Origin is a case-sensitive match for the value of the origin of the current document.

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_TAO_origin_uppercase.htm b/testing/web-platform/tests/resource-timing/resource_TAO_origin_uppercase.htm new file mode 100644 index 000000000000..0b42166c0ee8 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_TAO_origin_uppercase.htm @@ -0,0 +1,55 @@ + + + + +Resource Timing TAO tests + + + + + + + + + +

Description

+

This test validates that for a cross origin resource, the timing allow check algorithm will fail when the value of Timing-Allow-Origin is NOT a case-sensitive match for the value of the origin of the current document.

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_TAO_space.htm b/testing/web-platform/tests/resource-timing/resource_TAO_space.htm new file mode 100644 index 000000000000..f3cbdc62c016 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_TAO_space.htm @@ -0,0 +1,55 @@ + + + + +Resource Timing TAO tests + + + + + + + + + +

Description

+

This test validates that for a cross origin resource, the timing allow check algorithm will fail if the Timing-Allow-Origin header value list contains [origin|*]{2,}, separated by space.

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_TAO_wildcard.htm b/testing/web-platform/tests/resource-timing/resource_TAO_wildcard.htm new file mode 100644 index 000000000000..407c642d9d46 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_TAO_wildcard.htm @@ -0,0 +1,55 @@ + + + + +Resource Timing TAO tests + + + + + + + + + +

Description

+

This test validates that for a cross origin resource, the timing allow check algorithm will pass when the Timing-Allow-Origin header value is a wildcard ("*").

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_TAO_zero.htm b/testing/web-platform/tests/resource-timing/resource_TAO_zero.htm new file mode 100644 index 000000000000..0fe16c082a03 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_TAO_zero.htm @@ -0,0 +1,55 @@ + + + + +Resource Timing TAO tests + + + + + + + + + +

Description

+

This test validates that for a cross origin resource, the timing allow check algorithm will fail when the HTTP response includes zero Timing-Allow-Origin header value.

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resources/TAOResponse.py b/testing/web-platform/tests/resource-timing/resources/TAOResponse.py new file mode 100644 index 000000000000..cc8fa5f0f93f --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/TAOResponse.py @@ -0,0 +1,38 @@ +def main(request, response): + origin = request.headers['origin'] + response.headers.set('Access-Control-Allow-Origin', origin) + + tao = request.GET.first('tao') + + if tao == 'zero': + # zero TAO value, fail + pass + elif tao == 'wildcard': + # wildcard, pass + response.headers.set('Timing-Allow-Origin', '*') + elif tao == 'null': + # null, fail + response.headers.set('Timing-Allow-Origin', 'null') + elif tao == 'origin': + # case-sensitive match for origin, pass + response.headers.set('Timing-Allow-Origin', origin) + elif tao == 'space': + # space seperated list of origin and wildcard, fail + response.headers.set('Timing-Allow-Origin', (origin + ' *')) + elif tao == 'multi': + # more than one TAO values, seperated by common, pass + response.headers.set('Timing-Allow-Origin', origin) + response.headers.append('Timing-Allow-Origin', '*') + elif tao == 'match_origin': + # contains a match of origin, seperated by common, pass + response.headers.set('Timing-Allow-Origin', origin) + response.headers.append('Timing-Allow-Origin', "fake") + elif tao == 'match_wildcard': + # contains a wildcard, seperated by common, pass + response.headers.set('Timing-Allow-Origin', "fake") + response.headers.append('Timing-Allow-Origin', '*') + elif tao == 'uppercase': + # non-case-sensitive match for origin, fail + response.headers.set('Timing-Allow-Origin', origin.upper()) + else: + pass \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_origin.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_origin.html new file mode 100644 index 000000000000..cf68aade7954 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_origin.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_wildcard.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_wildcard.html new file mode 100644 index 000000000000..a6a03e0680e9 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_wildcard.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_multi.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_multi.html new file mode 100644 index 000000000000..0696dbe3e502 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_multi.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_null.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_null.html new file mode 100644 index 000000000000..7d47a2076f87 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_null.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_origin.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_origin.html new file mode 100644 index 000000000000..c75b0752406d --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_origin.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_origin_uppercase.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_origin_uppercase.html new file mode 100644 index 000000000000..7404035d1ab2 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_origin_uppercase.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_space.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_space.html new file mode 100644 index 000000000000..2a484ed5140b --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_space.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_wildcard.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_wildcard.html new file mode 100644 index 000000000000..3b5be4cdab98 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_wildcard.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_zero.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_zero.html new file mode 100644 index 000000000000..76c5938689a4 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_zero.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resources/.gitmodules b/testing/web-platform/tests/resources/.gitmodules deleted file mode 100644 index 89035729d514..000000000000 --- a/testing/web-platform/tests/resources/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "webidl2"] - path = webidl2 - url = https://github.com/darobin/webidl2.js.git diff --git a/testing/web-platform/tests/resources/examples/apisample18.html b/testing/web-platform/tests/resources/examples/apisample18.html new file mode 100644 index 000000000000..c97cba395808 --- /dev/null +++ b/testing/web-platform/tests/resources/examples/apisample18.html @@ -0,0 +1,26 @@ + + + +Example with iframe that consolidates errors via fetch_tests_from_window + + + + + +

Fetching Tests From a Child Context

+

This test demonstrates the use of fetch_tests_from_window to pull +tests from an iframe into the primary document.

+

The test suite is expected to fail due to an unhandled exception in the +child context.

+
+ + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resources/examples/apisample19.html b/testing/web-platform/tests/resources/examples/apisample19.html new file mode 100644 index 000000000000..84b9e122aba2 --- /dev/null +++ b/testing/web-platform/tests/resources/examples/apisample19.html @@ -0,0 +1,26 @@ + + + +Example with iframe that consolidates tests via fetch_tests_from_window + + + + + +

Fetching Tests From a Child Context

+

This test demonstrates the use of fetch_tests_from_window to pull +tests from an iframe into the primary document.

+

The test suite will not complete until tests in the child context have finished +executing

+
+ + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resources/idlharness.js b/testing/web-platform/tests/resources/idlharness.js index 5fca23e56acd..f661d238cbf5 100644 --- a/testing/web-platform/tests/resources/idlharness.js +++ b/testing/web-platform/tests/resources/idlharness.js @@ -437,6 +437,31 @@ IdlArray.prototype.test = function() IdlArray.prototype.assert_type_is = function(value, type) //@{ { + if (type.idlType in this.members + && this.members[type.idlType] instanceof IdlTypedef) { + this.assert_type_is(value, this.members[type.idlType].idlType); + return; + } + if (type.union) { + for (var i = 0; i < type.idlType.length; i++) { + try { + this.assert_type_is(value, type.idlType[i]); + // No AssertionError, so we match one type in the union + return; + } catch(e) { + if (e instanceof AssertionError) { + // We didn't match this type, let's try some others + continue; + } + throw e; + } + } + // TODO: Is there a nice way to list the union's types in the message? + assert_true(false, "Attribute has value " + format_value(value) + + " which doesn't match any of the types in the union"); + + } + /** * Helper function that tests that value is an instance of type according * to the rules of WebIDL. value is any JavaScript value, and type is an @@ -624,10 +649,6 @@ IdlArray.prototype.assert_type_is = function(value, type) { // TODO: Test when we actually have something to test this on } - else if (this.members[type] instanceof IdlTypedef) - { - // TODO: Test when we actually have something to test this on - } else { throw "Type " + type + " isn't an interface or dictionary"; @@ -1048,13 +1069,19 @@ IdlInterface.prototype.test_self = function() // "The class string of an interface prototype object is the // concatenation of the interface’s identifier and the string // “Prototype”." - assert_class_string(self[this.name].prototype, this.name + "Prototype", - "class string of " + this.name + ".prototype"); + + // Skip these tests for now due to a specification issue about + // prototype name. + // https://www.w3.org/Bugs/Public/show_bug.cgi?id=28244 + + // assert_class_string(self[this.name].prototype, this.name + "Prototype", + // "class string of " + this.name + ".prototype"); + // String() should end up calling {}.toString if nothing defines a // stringifier. if (!this.has_stringifier()) { - assert_equals(String(self[this.name].prototype), "[object " + this.name + "Prototype]", - "String(" + this.name + ".prototype)"); + // assert_equals(String(self[this.name].prototype), "[object " + this.name + "Prototype]", + // "String(" + this.name + ".prototype)"); } }.bind(this), this.name + " interface: existence and properties of interface prototype object"); @@ -2003,8 +2030,8 @@ function IdlTypedef(obj) /** Self-explanatory. */ this.name = obj.name; - /** An array of values produced by the "typedef" production. */ - this.values = obj.values; + /** The idlType that we are supposed to be typedeffing to. */ + this.idlType = obj.idlType; } //@} diff --git a/testing/web-platform/tests/resources/readme.md b/testing/web-platform/tests/resources/readme.md index eed909064239..8583d5f8d5b4 100644 --- a/testing/web-platform/tests/resources/readme.md +++ b/testing/web-platform/tests/resources/readme.md @@ -16,8 +16,7 @@ To use testharness.js you must include two scripts, in the order given: ## Full documentation ## -Full user documentation for the API is in the -[docs/api.md](https://github.com/w3c/testharness.js/blob/master/docs/api.md) file. +Full user documentation for the API is at [http://web-platform-tests.org/writing-tests/testharness-api.html](http://web-platform-tests.org/writing-tests/testharness-api.html). You can also read a tutorial on [Using testharness.js](http://darobin.github.com/test-harness-tutorial/docs/using-testharness.html). diff --git a/testing/web-platform/tests/resources/testharness.js b/testing/web-platform/tests/resources/testharness.js index ee842e42832c..2ee9a146a83a 100644 --- a/testing/web-platform/tests/resources/testharness.js +++ b/testing/web-platform/tests/resources/testharness.js @@ -66,6 +66,7 @@ policies and contribution forms [3]. this.all_loaded = false; var this_obj = this; this.message_events = []; + this.dispatched_messages = []; this.message_functions = { start: [add_start_callback, remove_start_callback, @@ -102,9 +103,23 @@ policies and contribution forms [3]. on_event(window, 'load', function() { this_obj.all_loaded = true; }); + + on_event(window, 'message', function(event) { + if (event.data && event.data.type === "getmessages" && event.source) { + // A window can post "getmessages" to receive a duplicate of every + // message posted by this environment so far. This allows subscribers + // from fetch_tests_from_window to 'catch up' to the current state of + // this environment. + for (var i = 0; i < this_obj.dispatched_messages.length; ++i) + { + event.source.postMessage(this_obj.dispatched_messages[i], "*"); + } + } + }); } WindowTestEnvironment.prototype._dispatch = function(selector, callback_args, message_arg) { + this.dispatched_messages.push(message_arg); this._forEach_windows( function(w, same_origin) { if (same_origin) { @@ -142,33 +157,14 @@ policies and contribution forms [3]. var w = self; var i = 0; var so; - var origins = location.ancestorOrigins; while (w != w.parent) { w = w.parent; - // In WebKit, calls to parent windows' properties that aren't on the same - // origin cause an error message to be displayed in the error console but - // don't throw an exception. This is a deviation from the current HTML5 - // spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504 - // The problem with WebKit's behavior is that it pollutes the error console - // with error messages that can't be caught. - // - // This issue can be mitigated by relying on the (for now) proprietary - // `location.ancestorOrigins` property which returns an ordered list of - // the origins of enclosing windows. See: - // http://trac.webkit.org/changeset/113945. - if (origins) { - so = (location.origin == origins[i]); - } else { - so = is_same_origin(w); - } + so = is_same_origin(w); cache.push([w, so]); i++; } w = window.opener; if (w) { - // window.opener isn't included in the `location.ancestorOrigins` prop. - // We'll just have to deal with a simple check and an error msg on WebKit - // browsers in this case. cache.push([w, is_same_origin(w)]); } this.window_cache = cache; @@ -414,7 +410,7 @@ policies and contribution forms [3]. var this_obj = this; self.addEventListener("message", function(event) { - if (event.data.type && event.data.type === "connect") { + if (event.data && event.data.type && event.data.type === "connect") { if (event.ports && event.ports[0]) { // If a MessageChannel was passed, then use it to // send results back to the main window. This @@ -1575,73 +1571,56 @@ policies and contribution forms [3]. } /* - * A RemoteWorker listens for test events from a worker. These events are - * then used to construct and maintain RemoteTest objects that mirror the - * tests running on the remote worker. + * A RemoteContext listens for test events from a remote test context, such + * as another window or a worker. These events are then used to construct + * and maintain RemoteTest objects that mirror the tests running in the + * remote context. + * + * An optional third parameter can be used as a predicate to filter incoming + * MessageEvents. */ - function RemoteWorker(worker) { + function RemoteContext(remote, message_target, message_filter) { this.running = true; this.tests = new Array(); var this_obj = this; - worker.onerror = function(error) { this_obj.worker_error(error); }; + remote.onerror = function(error) { this_obj.remote_error(error); }; - var message_port; - - if (is_service_worker(worker)) { - if (window.MessageChannel) { - // The ServiceWorker's implicit MessagePort is currently not - // reliably accessible from the ServiceWorkerGlobalScope due to - // Blink setting MessageEvent.source to null for messages sent - // via ServiceWorker.postMessage(). Until that's resolved, - // create an explicit MessageChannel and pass one end to the - // worker. - var message_channel = new MessageChannel(); - message_port = message_channel.port1; - message_port.start(); - worker.postMessage({type: "connect"}, [message_channel.port2]); - } else { - // If MessageChannel is not available, then try the - // ServiceWorker.postMessage() approach using MessageEvent.source - // on the other end. - message_port = navigator.serviceWorker; - worker.postMessage({type: "connect"}); + // Keeping a reference to the remote object and the message handler until + // remote_done() is seen prevents the remote object and its message channel + // from going away before all the messages are dispatched. + this.remote = remote; + this.message_target = message_target; + this.message_handler = function(message) { + var passesFilter = !message_filter || message_filter(message); + if (this_obj.running && message.data && passesFilter && + (message.data.type in this_obj.message_handlers)) { + this_obj.message_handlers[message.data.type].call(this_obj, message.data); } - } else if (is_shared_worker(worker)) { - message_port = worker.port; - } else { - message_port = worker; - } + }; - // Keeping a reference to the worker until worker_done() is seen - // prevents the Worker object and its MessageChannel from going away - // before all the messages are dispatched. - this.worker = worker; - - message_port.onmessage = - function(message) { - if (this_obj.running && (message.data.type in this_obj.message_handlers)) { - this_obj.message_handlers[message.data.type].call(this_obj, message.data); - } - }; + this.message_target.addEventListener("message", this.message_handler); } - RemoteWorker.prototype.worker_error = function(error) { + RemoteContext.prototype.remote_error = function(error) { var message = error.message || String(error); var filename = (error.filename ? " " + error.filename: ""); - // FIXME: Display worker error states separately from main document + // FIXME: Display remote error states separately from main document // error state. - this.worker_done({ + this.remote_done({ status: { status: tests.status.ERROR, - message: "Error in worker" + filename + ": " + message, + message: "Error in remote" + filename + ": " + message, stack: error.stack } }); - error.preventDefault(); + + if (error.preventDefault) { + error.preventDefault(); + } }; - RemoteWorker.prototype.test_state = function(data) { + RemoteContext.prototype.test_state = function(data) { var remote_test = this.tests[data.test.index]; if (!remote_test) { remote_test = new RemoteTest(data.test); @@ -1651,31 +1630,33 @@ policies and contribution forms [3]. tests.notify_test_state(remote_test); }; - RemoteWorker.prototype.test_done = function(data) { + RemoteContext.prototype.test_done = function(data) { var remote_test = this.tests[data.test.index]; remote_test.update_state_from(data.test); remote_test.done(); tests.result(remote_test); }; - RemoteWorker.prototype.worker_done = function(data) { + RemoteContext.prototype.remote_done = function(data) { if (tests.status.status === null && data.status.status !== data.status.OK) { tests.status.status = data.status.status; tests.status.message = data.status.message; tests.status.stack = data.status.stack; } + this.message_target.removeEventListener("message", this.message_handler); this.running = false; - this.worker = null; + this.remote = null; + this.message_target = null; if (tests.all_done()) { tests.complete(); } }; - RemoteWorker.prototype.message_handlers = { - test_state: RemoteWorker.prototype.test_state, - result: RemoteWorker.prototype.test_done, - complete: RemoteWorker.prototype.worker_done + RemoteContext.prototype.message_handlers = { + test_state: RemoteContext.prototype.test_state, + result: RemoteContext.prototype.test_done, + complete: RemoteContext.prototype.remote_done }; /* @@ -1743,7 +1724,7 @@ policies and contribution forms [3]. this.test_done_callbacks = []; this.all_done_callbacks = []; - this.pending_workers = []; + this.pending_remotes = []; this.status = new TestsStatus(); @@ -1858,7 +1839,7 @@ policies and contribution forms [3]. return (this.tests.length > 0 && test_environment.all_loaded && this.num_pending === 0 && !this.wait_for_finish && !this.processing_callbacks && - !this.pending_workers.some(function(w) { return w.running; })); + !this.pending_remotes.some(function(w) { return w.running; })); }; Tests.prototype.start = function() { @@ -1967,12 +1948,65 @@ policies and contribution forms [3]. }); }; + /* + * Constructs a RemoteContext that tracks tests from a specific worker. + */ + Tests.prototype.create_remote_worker = function(worker) { + var message_port; + + if (is_service_worker(worker)) { + // Microsoft Edge's implementation of ServiceWorker doesn't support MessagePort yet. + // Feature detection isn't a straightforward option here; it's only possible in the + // worker's script context. + var isMicrosoftEdgeBrowser = navigator.userAgent.includes("Edge"); + if (window.MessageChannel && !isMicrosoftEdgeBrowser) { + // The ServiceWorker's implicit MessagePort is currently not + // reliably accessible from the ServiceWorkerGlobalScope due to + // Blink setting MessageEvent.source to null for messages sent + // via ServiceWorker.postMessage(). Until that's resolved, + // create an explicit MessageChannel and pass one end to the + // worker. + var message_channel = new MessageChannel(); + message_port = message_channel.port1; + message_port.start(); + worker.postMessage({type: "connect"}, [message_channel.port2]); + } else { + // If MessageChannel is not available, then try the + // ServiceWorker.postMessage() approach using MessageEvent.source + // on the other end. + message_port = navigator.serviceWorker; + worker.postMessage({type: "connect"}); + } + } else if (is_shared_worker(worker)) { + message_port = worker.port; + message_port.start(); + } else { + message_port = worker; + } + + return new RemoteContext(worker, message_port); + }; + + /* + * Constructs a RemoteContext that tracks tests from a specific window. + */ + Tests.prototype.create_remote_window = function(remote) { + remote.postMessage({type: "getmessages"}, "*"); + return new RemoteContext( + remote, + window, + function(msg) { + return msg.source === remote; + } + ); + }; + Tests.prototype.fetch_tests_from_worker = function(worker) { if (this.phase >= this.phases.COMPLETE) { return; } - this.pending_workers.push(new RemoteWorker(worker)); + this.pending_remotes.push(this.create_remote_worker(worker)); }; function fetch_tests_from_worker(port) { @@ -1980,6 +2014,19 @@ policies and contribution forms [3]. } expose(fetch_tests_from_worker, 'fetch_tests_from_worker'); + Tests.prototype.fetch_tests_from_window = function(remote) { + if (this.phase >= this.phases.COMPLETE) { + return; + } + + this.pending_remotes.push(this.create_remote_window(remote)); + }; + + function fetch_tests_from_window(window) { + tests.fetch_tests_from_window(window); + } + expose(fetch_tests_from_window, 'fetch_tests_from_window'); + function timeout() { if (tests.timeout_length === null) { tests.timeout(); @@ -2139,7 +2186,7 @@ policies and contribution forms [3]. } var harness_url = get_harness_url(); - if (harness_url !== null) { + if (harness_url !== undefined) { var stylesheet = output_document.createElementNS(xhtml_ns, "link"); stylesheet.setAttribute("rel", "stylesheet"); stylesheet.setAttribute("href", harness_url + "testharness.css"); @@ -2493,6 +2540,7 @@ policies and contribution forms [3]. this.message = message; this.stack = this.get_stack(); } + expose(AssertionError, "AssertionError"); AssertionError.prototype = Object.create(Error.prototype); diff --git a/testing/web-platform/tests/resources/webidl2/README.md b/testing/web-platform/tests/resources/webidl2/README.md index f7d03fcdef30..5d128ed27ca8 100644 --- a/testing/web-platform/tests/resources/webidl2/README.md +++ b/testing/web-platform/tests/resources/webidl2/README.md @@ -3,16 +3,15 @@ [![NPM version](https://badge.fury.io/js/webidl2.png)](http://badge.fury.io/js/webidl2) -Purpose -======= +## Purpose This is a parser for the [WebIDL](http://dev.w3.org/2006/webapi/WebIDL/) language. If you don't know what that is, then you probably don't need it. It is meant to be used both in Node and in the browser (the parser likely works in other JS environments, but not the test suite). -What of v1? ------------ +### What of v1? + There was a previous incarnation of this project. I had written it in the most quick and dirty manner that was handy because I required it as a dependency in an experiment. As these things tend to happen, some people started using that, which then had to be @@ -20,65 +19,72 @@ maintained. But since it was not built on solid foundations, it was painful to k up to date with the specification, which is a bit of a moving target. So I started from scratch. Compared to the previous version (which used a parser generator) -this one is about 6x less code (which translates to 4x smaller minified or 2x smaller +this one is about 6x less code (which translates to 4x smaller minified or 2x smaller minizipped) and 4x faster. The test suite is reasonably complete (95% coverage), much more than previously. This version is up to date with WebIDL, rather than a couple years' behind. It also has *far* better error reporting. -The AST you get from parsing is very similar to the one you got in v1, but some adjustments -have been made in order to be more systematic, and to map better to what's actually in the spec +The AST you get from parsing is very similar to the one you got in v1, but some adjustments +have been made in order to be more systematic, and to map better to what's actually in the spec now. If you used v1, you will need to tweak your code but the result ought to be simpler and -you ought to be able to be a fair bit less defensive against irregularities in the way +you ought to be able to be a fair bit less defensive against irregularities in the way information is represented. -Installation -============ +## Installation Just the usual. For Node: - npm install webidl2 - +```Bash +npm install webidl2 +``` + In the browser: - +```HTML + +``` + +## Documentation -Documentation -============= The API to WebIDL2 is trivial: you parse a string of WebIDL and it returns a syntax tree. -Parsing -------- +### Parsing + In Node, that happens with: - var WebIDL2 = require("webidl2"); - var tree = WebIDL2.parse("string of WebIDL"); +```JS +var WebIDL2 = require("webidl2"); +var tree = WebIDL2.parse("string of WebIDL"); +``` In the browser: +```HTML + + +``` - - - -Advanced Parsing ----------------- +### Advanced Parsing `parse()` can optionally accept a second parameter, an options object, which can be used to modify parsing behavior. The following options are recognized: -```javascript +```JS { - allowNestedTypedefs: false # + allowNestedTypedefs: false } ``` + And their meanings are as follows: -* `allowNestedTypedefs`: Boolean indicating whether the parser should accept `typedef`s as valid members of `interface`s. This is non-standard syntax and therefore the default is `false`. +* `allowNestedTypedefs`: Boolean indicating whether the parser should accept `typedef`s as valid members of `interface`s. +This is non-standard syntax and therefore the default is `false`. + +### Errors -Errors ------- When there is a syntax error in the WebIDL, it throws an exception object with the following properties: @@ -91,8 +97,8 @@ properties: The exception also has a `toString()` method that hopefully should produce a decent error message. -AST (Abstract Syntax Tree) --------------------------- +### AST (Abstract Syntax Tree) + The `parse()` method returns a tree object representing the parse tree of the IDL. Comment and white space are not represented in the AST. @@ -106,35 +112,34 @@ This structure is used in many other places (operation return types, argument ty It captures a WebIDL type with a number of options. Types look like this and are typically attached to a field called `idlType`: - { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "void" - } +```JS +{ + "array": false, + "generic": null, + "idlType": "void", + "nullable": false, + "union": false, +} +``` Where the fields are as follows: -* `sequence`: Boolean indicating whether this is a sequence or not. Deprecated. Use - `generic` instead. -* `generic`: String indicating the generic type (e.g. "Promise", "sequence"). `null` - otherwise. -* `nullable`: Boolean indicating whether this is nullable or not. * `array`: Either `false` to indicate that it is not an array, or a number for the level of array nesting. -* `union`: Boolean indicating whether this is a union type or not. +* `generic`: String indicating the generic type (e.g. "Promise", "sequence"). `null` + otherwise. * `idlType`: Can be different things depending on context. In most cases, this will just be a string with the type name. But the reason this field isn't called "typeName" is because it can take more complex values. If the type is a union, then this contains an array of the types it unites. If it is a generic type, it contains the IDL type description for the type in the sequence, the eventual value of the promise, etc. +* `nullable`: Boolean indicating whether this is nullable or not. +* `union`: Boolean indicating whether this is a union type or not. #### Interactions between `nullable` and `array` A more complex data model for our AST would likely represent `Foo[][][]` as a series of -nested types four levels deep with three anonymous array types eventually containing a +nested types four levels deep with three anonymous array types eventually containing a `Foo` type. But experience shows that such structures are cumbersome to use, and so we have a simpler model in which the depth of the array is specified with the `array` field. @@ -167,22 +172,23 @@ a `?` at the end. ### Interface Interfaces look like this: - { - "type": "interface", - "name": "Animal", - "partial": false, - "members": [...], - "inheritance": null, - "extAttrs": [...] - }, - { - "type": "interface", - "name": "Human", - "partial": false, - "members": [...], - "inheritance": "Animal", - "extAttrs": [...] - } +```JS +{ + "type": "interface", + "name": "Animal", + "partial": false, + "members": [...], + "inheritance": null, + "extAttrs": [...] +}, { + "type": "interface", + "name": "Human", + "partial": false, + "members": [...], + "inheritance": "Animal", + "extAttrs": [...] +} +``` The fields are as follows: @@ -204,20 +210,22 @@ their `type` field is "callback interface". A callback looks like this: - { - "type": "callback", - "name": "AsyncOperationCallback", - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "void" - }, - "arguments": [...], - "extAttrs": [] - } +```JS +{ + "type": "callback", + "name": "AsyncOperationCallback", + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "void" + }, + "arguments": [...], + "extAttrs": [] +} +``` The fields are as follows: @@ -231,33 +239,33 @@ The fields are as follows: A dictionary looks like this: - { - "type": "dictionary", - "name": "PaintOptions", - "partial": false, - "members": [ - { - "type": "field", - "name": "fillPattern", - "required": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": true, - "array": false, - "union": false, - "idlType": "DOMString" - }, - "extAttrs": [], - "default": { - "type": "string", - "value": "black" - } - } - ], - "inheritance": null, - "extAttrs": [] +```JS +{ + "type": "dictionary", + "name": "PaintOptions", + "partial": false, + "members": [{ + "type": "field", + "name": "fillPattern", + "required": false, + "idlType": { + "sequence": false, + "generic": null, + "nullable": true, + "array": false, + "union": false, + "idlType": "DOMString" + }, + "extAttrs": [], + "default": { + "type": "string", + "value": "black" } + }], + "inheritance": null, + "extAttrs": [] +} +``` The fields are as follows: @@ -281,27 +289,27 @@ All the members are fields as follows: An exception looks like this: - { - "type": "exception", - "name": "HierarchyRequestError", - "members": [ - { - "type": "field", - "name": "code", - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "unsigned short" - }, - "extAttrs": [] - } - ], - "inheritance": "DOMException", - "extAttrs": [] - } +```JS +{ + "type": "exception", + "name": "HierarchyRequestError", + "members": [{ + "type": "field", + "name": "code", + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "unsigned short" + }, + "extAttrs": [] + }], + "inheritance": "DOMException", + "extAttrs": [] +} +``` The fields are as follows: @@ -322,16 +330,18 @@ Members that aren't [constants](#constants) have the following fields: An enum looks like this: - { - "type": "enum", - "name": "MealType", - "values": [ - "rice", - "noodles", - "other" - ], - "extAttrs": [] - } +```JS +{ + "type": "enum", + "name": "MealType", + "values": [ + "rice", + "noodles", + "other" + ], + "extAttrs": [] +} +``` The fields are as follows: @@ -344,27 +354,30 @@ The fields are as follows: A typedef looks like this: - { - "type": "typedef", - "typeExtAttrs": [], - "idlType": { - "sequence": true, - "generic": "sequence", - "nullable": false, - "array": false, - "union": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Point" - } - }, - "name": "PointSequence", - "extAttrs": [] +```JS +{ + "type": "typedef", + "typeExtAttrs": [], + "idlType": { + "sequence": true, + "generic": "sequence", + "nullable": false, + "array": false, + "union": false, + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "Point" } + }, + "name": "PointSequence", + "extAttrs": [] +} +``` + The fields are as follows: @@ -379,12 +392,14 @@ type rather than to the typedef as a whole. An implements definition looks like this: - { - "type": "implements", - "target": "Node", - "implements": "EventTarget", - "extAttrs": [] - } +```JS +{ + "type": "implements", + "target": "Node", + "implements": "EventTarget", + "extAttrs": [] +} +``` The fields are as follows: @@ -396,43 +411,42 @@ The fields are as follows: ### Operation Member An operation looks like this: - - { - "type": "operation", - "getter": false, - "setter": false, - "creator": false, - "deleter": false, - "legacycaller": false, - "static": false, - "stringifier": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "void" - }, - "name": "intersection", - "arguments": [ - { - "optional": false, - "variadic": true, - "extAttrs": [], - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "long" - }, - "name": "ints" - } - ], - "extAttrs": [] - } +```JS +{ + "type": "operation", + "getter": false, + "setter": false, + "creator": false, + "deleter": false, + "legacycaller": false, + "static": false, + "stringifier": false, + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "void" + }, + "name": "intersection", + "arguments": [{ + "optional": false, + "variadic": true, + "extAttrs": [], + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "long" + }, + "name": "ints" + }], + "extAttrs": [] +} +``` The fields are as follows: @@ -453,24 +467,26 @@ The fields are as follows: An attribute member looks like this: - { - "type": "attribute", - "static": false, - "stringifier": false, - "inherit": false, - "readonly": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "RegExp" - }, - "name": "regexp", - "extAttrs": [] - } - +```JS +{ + "type": "attribute", + "static": false, + "stringifier": false, + "inherit": false, + "readonly": false, + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "RegExp" + }, + "name": "regexp", + "extAttrs": [] +} +``` + The fields are as follows: * `type`: Always "attribute". @@ -486,17 +502,19 @@ The fields are as follows: A constant member looks like this: - { - "type": "const", - "nullable": false, - "idlType": "boolean", - "name": "DEBUG", - "value": { - "type": "boolean", - "value": false - }, - "extAttrs": [] - } +```JS +{ + "type": "const", + "nullable": false, + "idlType": "boolean", + "name": "DEBUG", + "value": { + "type": "boolean", + "value": false + }, + "extAttrs": [] +} +``` The fields are as follows: @@ -512,60 +530,63 @@ The fields are as follows: Serializers come in many shapes, which are best understood by looking at the examples below that map the IDL to the produced AST. - // serializer; - { - "type": "serializer", - "extAttrs": [] - } +```JS +// serializer; +{ + "type": "serializer", + "extAttrs": [] +} - // serializer DOMString serialize(); - { - "type": "serializer", - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "DOMString" - }, - "operation": { - "name": "serialize", - "arguments": [] - }, - "extAttrs": [] - } +// serializer DOMString serialize(); +{ + "type": "serializer", + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "DOMString" + }, + "operation": { + "name": "serialize", + "arguments": [] + }, + "extAttrs": [] +} - // serializer = { from, to, amount, description }; - { - "type": "serializer", - "patternMap": true, - "names": [ - "from", - "to", - "amount", - "description" - ], - "extAttrs": [] - } +// serializer = { from, to, amount, description }; +{ + "type": "serializer", + "patternMap": true, + "names": [ + "from", + "to", + "amount", + "description" + ], + "extAttrs": [] +} - // serializer = number; - { - "type": "serializer", - "name": "number", - "extAttrs": [] - } +// serializer = number; +{ + "type": "serializer", + "name": "number", + "extAttrs": [] +} - // serializer = [ name, number ]; - { - "type": "serializer", - "patternList": true, - "names": [ - "name", - "number" - ], - "extAttrs": [] - } +// serializer = [ name, number ]; +{ + "type": "serializer", + "patternList": true, + "names": [ + "name", + "number" + ], + "extAttrs": [] +} + +``` The common fields are as follows: @@ -598,26 +619,28 @@ Finally, if the serializer is a named serializer: Iterator members look like this - { - "type": "iterator", - "getter": false, - "setter": false, - "creator": false, - "deleter": false, - "legacycaller": false, - "static": false, - "stringifier": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Session2" - }, - "iteratorObject": "SessionIterator", - "extAttrs": [] - } +```JS +{ + "type": "iterator", + "getter": false, + "setter": false, + "creator": false, + "deleter": false, + "legacycaller": false, + "static": false, + "stringifier": false, + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "Session2" + }, + "iteratorObject": "SessionIterator", + "extAttrs": [] +} +``` * `type`: Always "iterator". * `iteratorObject`: The string on the right-hand side; absent if there isn't one. @@ -627,22 +650,24 @@ Iterator members look like this The arguments (e.g. for an operation) look like this: - "arguments": [ - { - "optional": false, - "variadic": true, - "extAttrs": [], - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "long" - }, - "name": "ints" - } - ] +```JS +{ + "arguments": [{ + "optional": false, + "variadic": true, + "extAttrs": [], + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "long" + }, + "name": "ints" + }] +} +``` The fields are as follows: @@ -656,16 +681,18 @@ The fields are as follows: Extended attributes are arrays of items that look like this: - "extAttrs": [ - { - "name": "TreatNullAs", - "arguments": null, - "rhs": { - "type": "identifier", - "value": "EmptyString" - } - } - ] +```JS +{ + "extAttrs": [{ + "name": "TreatNullAs", + "arguments": null, + "rhs": { + "type": "identifier", + "value": "EmptyString" + } + }] +} +``` The fields are as follows: @@ -700,12 +727,14 @@ For Infinity: These appear as members of interfaces that look like this: - { - "type": "maplike", // or "legacyiterable" / "iterable" / "setlike" - "idlType": /* One or two types */, - "readonly": false, // only for maplike and setlike - "extAttrs": [] - } +```JS +{ + "type": "maplike", // or "legacyiterable" / "iterable" / "setlike" + "idlType": /* One or two types */ , + "readonly": false, // only for maplike and setlike + "extAttrs": [] +} +``` The fields are as follows: @@ -715,46 +744,51 @@ The fields are as follows: * `extAttrs`: A list of [extended attributes](#extended-attributes). -Testing -======= +## Testing In order to run the tests you need to ensure that the widlproc submodule inside `test` is -initialised and up to date: +initialized and up to date: - git submodule init - git submodule update +```Bash +git submodule init +git submodule update +``` + +### Running -Running -------- The test runs with mocha and expect.js. Normally, running mocha in the root directory should be enough once you're set up. -Coverage --------- +### Coverage + Current test coverage, as documented in `coverage.html`, is 95%. You can run your own coverage analysis with: - jscoverage lib lib-cov - +```Bash +jscoverage lib lib-cov +``` + That will create the lib-cov directory with instrumented code; the test suite knows to use that if needed. You can then run the tests with: - JSCOV=1 mocha --reporter html-cov > coverage.html +```Bash +JSCOV=1 mocha --reporter html-cov > coverage.html +``` Note that I've been getting weirdly overescaped results from the html-cov reporter, so you might wish to try this instead: - JSCOV=1 mocha --reporter html-cov | sed "s/<//g" | sed "s/"/\"/g" > coverage.html +```Bash +JSCOV=1 mocha --reporter html-cov | sed "s/<//g" | sed "s/"/\"/g" > coverage.html +``` +### Browser tests -Browser tests -------------- In order to test in the browser, get inside `test/web` and run `make-web-tests.js`. This will generate a `browser-tests.html` file that you can open in a browser. As of this writing tests pass in the latest Firefox, Chrome, Opera, and Safari. Testing on IE and older versions will happen progressively. -TODO -==== +## TODO * add some tests to address coverage limitations * add a push API for processors that need to process things like comments diff --git a/testing/web-platform/tests/resources/webidl2/lib/webidl2.js b/testing/web-platform/tests/resources/webidl2/lib/webidl2.js index 9e504fc6e1fd..0e76174a0836 100644 --- a/testing/web-platform/tests/resources/webidl2/lib/webidl2.js +++ b/testing/web-platform/tests/resources/webidl2/lib/webidl2.js @@ -1,1012 +1,1084 @@ +(function() { + var tokenise = function(str) { + var tokens = [], + re = { + "float": /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/, + "integer": /^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/, + "identifier": /^[A-Z_a-z][0-9A-Z_a-z-]*/, + "string": /^"[^"]*"/, + "whitespace": /^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/, + "other": /^[^\t\n\r 0-9A-Z_a-z]/ + }, + types = ["float", "integer", "identifier", "string", "whitespace", "other"]; + while (str.length > 0) { + var matched = false; + for (var i = 0, n = types.length; i < n; i++) { + var type = types[i]; + str = str.replace(re[type], function(tok) { + tokens.push({ type: type, value: tok }); + matched = true; + return ""; + }); + if (matched) break; + } + if (matched) continue; + throw new Error("Token stream not progressing"); + } + return tokens; + }; + function WebIDLParseError(str, line, input, tokens) { + this.message = str; + this.line = line; + this.input = input; + this.tokens = tokens; + }; -(function () { - var tokenise = function (str) { - var tokens = [] - , re = { - "float": /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/ - , "integer": /^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/ - , "identifier": /^[A-Z_a-z][0-9A-Z_a-z]*/ - , "string": /^"[^"]*"/ - , "whitespace": /^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/ - , "other": /^[^\t\n\r 0-9A-Z_a-z]/ - } - , types = [] - ; - for (var k in re) types.push(k); - while (str.length > 0) { + WebIDLParseError.prototype.toString = function() { + return this.message + ", line " + this.line + " (tokens: '" + this.input + "')\n" + + JSON.stringify(this.tokens, null, 4); + }; + + var parse = function(tokens, opt) { + var line = 1; + tokens = tokens.slice(); + + var FLOAT = "float", + INT = "integer", + ID = "identifier", + STR = "string", + OTHER = "other"; + + var error = function(str) { + var tok = ""; + var numTokens = 0; + var maxTokens = 5; + while (numTokens < maxTokens && tokens.length > numTokens) { + tok += tokens[numTokens].value; + numTokens++; + } + throw new WebIDLParseError(str, line, tok, tokens.slice(0, 5)); + }; + + var last_token = null; + + var consume = function(type, value) { + if (!tokens.length || tokens[0].type !== type) return; + if (typeof value === "undefined" || tokens[0].value === value) { + last_token = tokens.shift(); + if (type === ID) last_token.value = last_token.value.replace(/^_/, ""); + return last_token; + } + }; + + var ws = function() { + if (!tokens.length) return; + if (tokens[0].type === "whitespace") { + var t = tokens.shift(); + t.value.replace(/\n/g, function(m) { line++; + return m; }); + return t; + } + }; + + var all_ws = function(store, pea) { // pea == post extended attribute, tpea = same for types + var t = { type: "whitespace", value: "" }; + while (true) { + var w = ws(); + if (!w) break; + t.value += w.value; + } + if (t.value.length > 0) { + if (store) { + var w = t.value, + re = { + "ws": /^([\t\n\r ]+)/, + "line-comment": /^\/\/(.*)\n?/m, + "multiline-comment": /^\/\*((?:.|\n|\r)*?)\*\// + }, + wsTypes = []; + for (var k in re) wsTypes.push(k); + while (w.length) { var matched = false; - for (var i = 0, n = types.length; i < n; i++) { - var type = types[i]; - str = str.replace(re[type], function (tok) { - tokens.push({ type: type, value: tok }); - matched = true; - return ""; - }); - if (matched) break; + for (var i = 0, n = wsTypes.length; i < n; i++) { + var type = wsTypes[i]; + w = w.replace(re[type], function(tok, m1) { + store.push({ type: type + (pea ? ("-" + pea) : ""), value: m1 }); + matched = true; + return ""; + }); + if (matched) break; } if (matched) continue; - throw new Error("Token stream not progressing"); + throw new Error("Surprising white space construct."); // this shouldn't happen + } } - return tokens; + return t; + } }; + + var integer_type = function() { + var ret = ""; + all_ws(); + if (consume(ID, "unsigned")) ret = "unsigned "; + all_ws(); + if (consume(ID, "short")) return ret + "short"; + if (consume(ID, "long")) { + ret += "long"; + all_ws(); + if (consume(ID, "long")) return ret + " long"; + return ret; + } + if (ret) error("Failed to parse integer type"); + }; + + var float_type = function() { + var ret = ""; + all_ws(); + if (consume(ID, "unrestricted")) ret = "unrestricted "; + all_ws(); + if (consume(ID, "float")) return ret + "float"; + if (consume(ID, "double")) return ret + "double"; + if (ret) error("Failed to parse float type"); + }; + + var primitive_type = function() { + var num_type = integer_type() || float_type(); + if (num_type) return num_type; + all_ws(); + if (consume(ID, "boolean")) return "boolean"; + if (consume(ID, "byte")) return "byte"; + if (consume(ID, "octet")) return "octet"; + }; + + var const_value = function() { + if (consume(ID, "true")) return { type: "boolean", value: true }; + if (consume(ID, "false")) return { type: "boolean", value: false }; + if (consume(ID, "null")) return { type: "null" }; + if (consume(ID, "Infinity")) return { type: "Infinity", negative: false }; + if (consume(ID, "NaN")) return { type: "NaN" }; + var ret = consume(FLOAT) || consume(INT); + if (ret) return { type: "number", value: 1 * ret.value }; + var tok = consume(OTHER, "-"); + if (tok) { + if (consume(ID, "Infinity")) return { type: "Infinity", negative: true }; + else tokens.unshift(tok); + } + }; + + var type_suffix = function(obj) { + while (true) { + all_ws(); + if (consume(OTHER, "?")) { + if (obj.nullable) error("Can't nullable more than once"); + obj.nullable = true; + } else if (consume(OTHER, "[")) { + all_ws(); + consume(OTHER, "]") || error("Unterminated array type"); + if (!obj.array) { + obj.array = 1; + obj.nullableArray = [obj.nullable]; + } else { + obj.array++; + obj.nullableArray.push(obj.nullable); + } + obj.nullable = false; + } else return; + } + }; + + var single_type = function() { + var prim = primitive_type(), + ret = { sequence: false, generic: null, nullable: false, array: false, union: false }, + name, value; + if (prim) { + ret.idlType = prim; + } else if (name = consume(ID)) { + value = name.value; + all_ws(); + // Generic types + if (consume(OTHER, "<")) { + // backwards compat + if (value === "sequence") { + ret.sequence = true; + } + ret.generic = value; + var types = []; + do { + all_ws(); + types.push(type() || error("Error parsing generic type " + value)); + all_ws(); + } + while (consume(OTHER, ",")); + if (value === "sequence") { + if (types.length !== 1) error("A sequence must have exactly one subtype"); + } else if (value === "record") { + if (types.length !== 2) error("A record must have exactly two subtypes"); + if (!/^(DOMString|USVString|ByteString)$/.test(types[0].idlType)) { + error("Record key must be DOMString, USVString, or ByteString"); + } + } + ret.idlType = types.length === 1 ? types[0] : types; + all_ws(); + if (!consume(OTHER, ">")) error("Unterminated generic type " + value); + type_suffix(ret); + return ret; + } else { + ret.idlType = value; + } + } else { + return; + } + type_suffix(ret); + if (ret.nullable && !ret.array && ret.idlType === "any") error("Type any cannot be made nullable"); + return ret; + }; + + var union_type = function() { + all_ws(); + if (!consume(OTHER, "(")) return; + var ret = { sequence: false, generic: null, nullable: false, array: false, union: true, idlType: [] }; + var fst = type_with_extended_attributes() || error("Union type with no content"); + ret.idlType.push(fst); + while (true) { + all_ws(); + if (!consume(ID, "or")) break; + var typ = type_with_extended_attributes() || error("No type after 'or' in union type"); + ret.idlType.push(typ); + } + if (!consume(OTHER, ")")) error("Unterminated union type"); + type_suffix(ret); + return ret; + }; + + var type = function() { + return single_type() || union_type(); + }; + + var type_with_extended_attributes = function() { + var extAttrs = extended_attrs(); + var ret = single_type() || union_type(); + if (extAttrs.length && ret) ret.extAttrs = extAttrs; + return ret; + }; + + var argument = function(store) { + var ret = { optional: false, variadic: false }; + ret.extAttrs = extended_attrs(store); + all_ws(store, "pea"); + var opt_token = consume(ID, "optional"); + if (opt_token) { + ret.optional = true; + all_ws(); + } + ret.idlType = type_with_extended_attributes(); + if (!ret.idlType) { + if (opt_token) tokens.unshift(opt_token); + return; + } + var type_token = last_token; + if (!ret.optional) { + all_ws(); + if (tokens.length >= 3 && + tokens[0].type === "other" && tokens[0].value === "." && + tokens[1].type === "other" && tokens[1].value === "." && + tokens[2].type === "other" && tokens[2].value === "." + ) { + tokens.shift(); + tokens.shift(); + tokens.shift(); + ret.variadic = true; + } + } + all_ws(); + var name = consume(ID); + if (!name) { + if (opt_token) tokens.unshift(opt_token); + tokens.unshift(type_token); + return; + } + ret.name = name.value; + if (ret.optional) { + all_ws(); + var dflt = default_(); + if (typeof dflt !== "undefined") { + ret["default"] = dflt; + } + } + return ret; + }; + + var argument_list = function(store) { + var ret = [], + arg = argument(store ? ret : null); + if (!arg) return; + ret.push(arg); + while (true) { + all_ws(store ? ret : null); + if (!consume(OTHER, ",")) return ret; + var nxt = argument(store ? ret : null) || error("Trailing comma in arguments list"); + ret.push(nxt); + } + }; + + var simple_extended_attr = function(store) { + all_ws(); + var name = consume(ID); + if (!name) return; + var ret = { + name: name.value, + "arguments": null + }; + all_ws(); + var eq = consume(OTHER, "="); + if (eq) { + var rhs; + all_ws(); + if (rhs = consume(ID)) { + ret.rhs = rhs; + } else if (rhs = consume(FLOAT)) { + ret.rhs = rhs; + } else if (rhs = consume(INT)) { + ret.rhs = rhs; + } else if (rhs = consume(STR)) { + ret.rhs = rhs; + } else if (consume(OTHER, "(")) { + // [Exposed=(Window,Worker)] + rhs = []; + var id = consume(ID); + if (id) { + rhs = [id.value]; + } + identifiers(rhs); + consume(OTHER, ")") || error("Unexpected token in extended attribute argument list or type pair"); + ret.rhs = { + type: "identifier-list", + value: rhs + }; + } + if (!ret.rhs) return error("No right hand side to extended attribute assignment"); + } + all_ws(); + if (consume(OTHER, "(")) { + var args, pair; + // [Constructor(DOMString str)] + if (args = argument_list(store)) { + ret["arguments"] = args; + } + // [Constructor()] + else { + ret["arguments"] = []; + } + all_ws(); + consume(OTHER, ")") || error("Unexpected token in extended attribute argument list"); + } + return ret; + }; + + // Note: we parse something simpler than the official syntax. It's all that ever + // seems to be used + var extended_attrs = function(store) { + var eas = []; + all_ws(store); + if (!consume(OTHER, "[")) return eas; + eas[0] = simple_extended_attr(store) || error("Extended attribute with not content"); + all_ws(); + while (consume(OTHER, ",")) { + if (eas.length) { + eas.push(simple_extended_attr(store)); + } else { + eas.push(simple_extended_attr(store) || error("Trailing comma in extended attribute")); + } + } + consume(OTHER, "]") || error("No end of extended attribute"); + return eas; + }; + + var default_ = function() { + all_ws(); + if (consume(OTHER, "=")) { + all_ws(); + var def = const_value(); + if (def) { + return def; + } else if (consume(OTHER, "[")) { + if (!consume(OTHER, "]")) error("Default sequence value must be empty"); + return { type: "sequence", value: [] }; + } else { + var str = consume(STR) || error("No value for default"); + str.value = str.value.replace(/^"/, "").replace(/"$/, ""); + return str; + } + } + }; + + var const_ = function(store) { + all_ws(store, "pea"); + if (!consume(ID, "const")) return; + var ret = { type: "const", nullable: false }; + all_ws(); + var typ = primitive_type(); + if (!typ) { + typ = consume(ID) || error("No type for const"); + typ = typ.value; + } + ret.idlType = typ; + all_ws(); + if (consume(OTHER, "?")) { + ret.nullable = true; + all_ws(); + } + var name = consume(ID) || error("No name for const"); + ret.name = name.value; + all_ws(); + consume(OTHER, "=") || error("No value assignment for const"); + all_ws(); + var cnt = const_value(); + if (cnt) ret.value = cnt; + else error("No value for const"); + all_ws(); + consume(OTHER, ";") || error("Unterminated const"); + return ret; + }; + + var inheritance = function() { + all_ws(); + if (consume(OTHER, ":")) { + all_ws(); + var inh = consume(ID) || error("No type in inheritance"); + return inh.value; + } + }; + + var operation_rest = function(ret, store) { + all_ws(); + if (!ret) ret = {}; + var name = consume(ID); + ret.name = name ? name.value : null; + all_ws(); + consume(OTHER, "(") || error("Invalid operation"); + ret["arguments"] = argument_list(store) || []; + all_ws(); + consume(OTHER, ")") || error("Unterminated operation"); + all_ws(); + consume(OTHER, ";") || error("Unterminated operation"); + return ret; + }; + + var callback = function(store) { + all_ws(store, "pea"); + var ret; + if (!consume(ID, "callback")) return; + all_ws(); + var tok = consume(ID, "interface"); + if (tok) { + tokens.unshift(tok); + ret = interface_(); + ret.type = "callback interface"; + return ret; + } + var name = consume(ID) || error("No name for callback"); + ret = { type: "callback", name: name.value }; + all_ws(); + consume(OTHER, "=") || error("No assignment in callback"); + all_ws(); + ret.idlType = return_type(); + all_ws(); + consume(OTHER, "(") || error("No arguments in callback"); + ret["arguments"] = argument_list(store) || []; + all_ws(); + consume(OTHER, ")") || error("Unterminated callback"); + all_ws(); + consume(OTHER, ";") || error("Unterminated callback"); + return ret; + }; + + var attribute = function(store) { + all_ws(store, "pea"); + var grabbed = [], + ret = { + type: "attribute", + "static": false, + stringifier: false, + inherit: false, + readonly: false + }; + if (consume(ID, "static")) { + ret["static"] = true; + grabbed.push(last_token); + } else if (consume(ID, "stringifier")) { + ret.stringifier = true; + grabbed.push(last_token); + } + var w = all_ws(); + if (w) grabbed.push(w); + if (consume(ID, "inherit")) { + if (ret["static"] || ret.stringifier) error("Cannot have a static or stringifier inherit"); + ret.inherit = true; + grabbed.push(last_token); + var w = all_ws(); + if (w) grabbed.push(w); + } + if (consume(ID, "readonly")) { + ret.readonly = true; + grabbed.push(last_token); + var w = all_ws(); + if (w) grabbed.push(w); + } + var rest = attribute_rest(ret); + if (!rest) { + tokens = grabbed.concat(tokens); + } + return rest; + }; + + var attribute_rest = function(ret) { + if (!consume(ID, "attribute")) { + return; + } + all_ws(); + ret.idlType = type_with_extended_attributes() || error("No type in attribute"); + if (ret.idlType.sequence) error("Attributes cannot accept sequence types"); + if (ret.idlType.generic === "record") error("Attributes cannot accept record types"); + all_ws(); + var name = consume(ID) || error("No name in attribute"); + ret.name = name.value; + all_ws(); + consume(OTHER, ";") || error("Unterminated attribute"); + return ret; + }; + + var return_type = function() { + var typ = type(); + if (!typ) { + if (consume(ID, "void")) { + return "void"; + } else error("No return type"); + } + return typ; + }; + + var operation = function(store) { + all_ws(store, "pea"); + var ret = { + type: "operation", + getter: false, + setter: false, + creator: false, + deleter: false, + legacycaller: false, + "static": false, + stringifier: false + }; + while (true) { + all_ws(); + if (consume(ID, "getter")) ret.getter = true; + else if (consume(ID, "setter")) ret.setter = true; + else if (consume(ID, "creator")) ret.creator = true; + else if (consume(ID, "deleter")) ret.deleter = true; + else if (consume(ID, "legacycaller")) ret.legacycaller = true; + else break; + } + if (ret.getter || ret.setter || ret.creator || ret.deleter || ret.legacycaller) { + all_ws(); + ret.idlType = return_type(); + operation_rest(ret, store); + return ret; + } + if (consume(ID, "static")) { + ret["static"] = true; + ret.idlType = return_type(); + operation_rest(ret, store); + return ret; + } else if (consume(ID, "stringifier")) { + ret.stringifier = true; - + all_ws(); + if (consume(OTHER, ";")) return ret; + ret.idlType = return_type(); + operation_rest(ret, store); + return ret; + } + ret.idlType = return_type(); + all_ws(); + if (consume(ID, "iterator")) { + all_ws(); + ret.type = "iterator"; + if (consume(ID, "object")) { + ret.iteratorObject = "object"; + } else if (consume(OTHER, "=")) { + all_ws(); + var name = consume(ID) || error("No right hand side in iterator"); + ret.iteratorObject = name.value; + } + all_ws(); + consume(OTHER, ";") || error("Unterminated iterator"); + return ret; + } else { + operation_rest(ret, store); + return ret; + } + }; + + var identifiers = function(arr) { + while (true) { + all_ws(); + if (consume(OTHER, ",")) { + all_ws(); + var name = consume(ID) || error("Trailing comma in identifiers list"); + arr.push(name.value); + } else break; + } + }; + + var serialiser = function(store) { + all_ws(store, "pea"); + if (!consume(ID, "serializer")) return; + var ret = { type: "serializer" }; + all_ws(); + if (consume(OTHER, "=")) { + all_ws(); + if (consume(OTHER, "{")) { + ret.patternMap = true; + all_ws(); + var id = consume(ID); + if (id && id.value === "getter") { + ret.names = ["getter"]; + } else if (id && id.value === "inherit") { + ret.names = ["inherit"]; + identifiers(ret.names); + } else if (id) { + ret.names = [id.value]; + identifiers(ret.names); + } else { + ret.names = []; + } + all_ws(); + consume(OTHER, "}") || error("Unterminated serializer pattern map"); + } else if (consume(OTHER, "[")) { + ret.patternList = true; + all_ws(); + var id = consume(ID); + if (id && id.value === "getter") { + ret.names = ["getter"]; + } else if (id) { + ret.names = [id.value]; + identifiers(ret.names); + } else { + ret.names = []; + } + all_ws(); + consume(OTHER, "]") || error("Unterminated serializer pattern list"); + } else { + var name = consume(ID) || error("Invalid serializer"); + ret.name = name.value; + } + all_ws(); + consume(OTHER, ";") || error("Unterminated serializer"); + return ret; + } else if (consume(OTHER, ";")) { + // noop, just parsing + } else { + ret.idlType = return_type(); + all_ws(); + ret.operation = operation_rest(null, store); + } + return ret; + }; + + var iterable_type = function() { + if (consume(ID, "iterable")) return "iterable"; + else if (consume(ID, "legacyiterable")) return "legacyiterable"; + else if (consume(ID, "maplike")) return "maplike"; + else if (consume(ID, "setlike")) return "setlike"; + else return; + }; + + var readonly_iterable_type = function() { + if (consume(ID, "maplike")) return "maplike"; + else if (consume(ID, "setlike")) return "setlike"; + else return; + }; + + var iterable = function(store) { + all_ws(store, "pea"); + var grabbed = [], + ret = { type: null, idlType: null, readonly: false }; + if (consume(ID, "readonly")) { + ret.readonly = true; + grabbed.push(last_token); + var w = all_ws(); + if (w) grabbed.push(w); + } + var consumeItType = ret.readonly ? readonly_iterable_type : iterable_type; + + var ittype = consumeItType(); + if (!ittype) { + tokens = grabbed.concat(tokens); + return; + } + + var secondTypeRequired = ittype === "maplike"; + var secondTypeAllowed = secondTypeRequired || ittype === "iterable"; + ret.type = ittype; + if (ret.type !== 'maplike' && ret.type !== 'setlike') + delete ret.readonly; + all_ws(); + if (consume(OTHER, "<")) { + ret.idlType = type_with_extended_attributes() || error("Error parsing " + ittype + " declaration"); + all_ws(); + if (secondTypeAllowed) { + var type2 = null; + if (consume(OTHER, ",")) { + all_ws(); + type2 = type_with_extended_attributes(); + all_ws(); + } + if (type2) + ret.idlType = [ret.idlType, type2]; + else if (secondTypeRequired) + error("Missing second type argument in " + ittype + " declaration"); + } + if (!consume(OTHER, ">")) error("Unterminated " + ittype + " declaration"); + all_ws(); + if (!consume(OTHER, ";")) error("Missing semicolon after " + ittype + " declaration"); + } else + error("Error parsing " + ittype + " declaration"); + + return ret; + }; + + var interface_ = function(isPartial, store) { + all_ws(isPartial ? null : store, "pea"); + if (!consume(ID, "interface")) return; + all_ws(); + var name = consume(ID) || error("No name for interface"); + var mems = [], + ret = { + type: "interface", + name: name.value, + partial: false, + members: mems + }; + if (!isPartial) ret.inheritance = inheritance() || null; + all_ws(); + consume(OTHER, "{") || error("Bodyless interface"); + while (true) { + all_ws(store ? mems : null); + if (consume(OTHER, "}")) { + all_ws(); + consume(OTHER, ";") || error("Missing semicolon after interface"); + return ret; + } + var ea = extended_attrs(store ? mems : null); + all_ws(); + var cnt = const_(store ? mems : null); + if (cnt) { + cnt.extAttrs = ea; + ret.members.push(cnt); + continue; + } + var mem = (opt.allowNestedTypedefs && typedef(store ? mems : null)) || + iterable(store ? mems : null) || + serialiser(store ? mems : null) || + attribute(store ? mems : null) || + operation(store ? mems : null) || + error("Unknown member"); + mem.extAttrs = ea; + ret.members.push(mem); + } + }; + + var namespace = function(isPartial, store) { + all_ws(isPartial ? null : store, "pea"); + if (!consume(ID, "namespace")) return; + all_ws(); + var name = consume(ID) || error("No name for namespace"); + var mems = [], + ret = { + type: "namespace", + name: name.value, + partial: isPartial, + members: mems + }; + all_ws(); + consume(OTHER, "{") || error("Bodyless namespace"); + while (true) { + all_ws(store ? mems : null); + if (consume(OTHER, "}")) { + all_ws(); + consume(OTHER, ";") || error("Missing semicolon after namespace"); + return ret; + } + var ea = extended_attrs(store ? mems : null); + all_ws(); + var mem = noninherited_attribute(store ? mems : null) || + nonspecial_operation(store ? mems : null) || + error("Unknown member"); + mem.extAttrs = ea; + ret.members.push(mem); + } + } + + var noninherited_attribute = function(store) { + var w = all_ws(store, "pea"), + grabbed = [], + ret = { + type: "attribute", + "static": false, + stringifier: false, + inherit: false, + readonly: false + }; + if (w) grabbed.push(w); + if (consume(ID, "readonly")) { + ret.readonly = true; + grabbed.push(last_token); + var w = all_ws(); + if (w) grabbed.push(w); + } + var rest = attribute_rest(ret); + if (!rest) { + tokens = grabbed.concat(tokens); + } + return rest; + } - var parse = function (tokens, opt) { - var line = 1; - tokens = tokens.slice(); - - var FLOAT = "float" - , INT = "integer" - , ID = "identifier" - , STR = "string" - , OTHER = "other" - ; - - var WebIDLParseError = function (str, line, input, tokens) { - this.message = str; - this.line = line; - this.input = input; - this.tokens = tokens; - }; - WebIDLParseError.prototype.toString = function () { - return this.message + ", line " + this.line + " (tokens: '" + this.input + "')\n" + - JSON.stringify(this.tokens, null, 4); - }; - - var error = function (str) { - var tok = "", numTokens = 0, maxTokens = 5; - while (numTokens < maxTokens && tokens.length > numTokens) { - tok += tokens[numTokens].value; - numTokens++; - } - throw new WebIDLParseError(str, line, tok, tokens.slice(0, 5)); - }; - - var last_token = null; - - var consume = function (type, value) { - if (!tokens.length || tokens[0].type !== type) return; - if (typeof value === "undefined" || tokens[0].value === value) { - last_token = tokens.shift(); - if (type === ID) last_token.value = last_token.value.replace(/^_/, ""); - return last_token; - } - }; - - var ws = function () { - if (!tokens.length) return; - if (tokens[0].type === "whitespace") { - var t = tokens.shift(); - t.value.replace(/\n/g, function (m) { line++; return m; }); - return t; - } - }; - - var all_ws = function (store, pea) { // pea == post extended attribute, tpea = same for types - var t = { type: "whitespace", value: "" }; - while (true) { - var w = ws(); - if (!w) break; - t.value += w.value; - } - if (t.value.length > 0) { - if (store) { - var w = t.value - , re = { - "ws": /^([\t\n\r ]+)/ - , "line-comment": /^\/\/(.*)\n?/m - , "multiline-comment": /^\/\*((?:.|\n|\r)*?)\*\// - } - , wsTypes = [] - ; - for (var k in re) wsTypes.push(k); - while (w.length) { - var matched = false; - for (var i = 0, n = wsTypes.length; i < n; i++) { - var type = wsTypes[i]; - w = w.replace(re[type], function (tok, m1) { - store.push({ type: type + (pea ? ("-" + pea) : ""), value: m1 }); - matched = true; - return ""; - }); - if (matched) break; - } - if (matched) continue; - throw new Error("Surprising white space construct."); // this shouldn't happen - } - } - return t; - } - }; - - var integer_type = function () { - var ret = ""; - all_ws(); - if (consume(ID, "unsigned")) ret = "unsigned "; - all_ws(); - if (consume(ID, "short")) return ret + "short"; - if (consume(ID, "long")) { - ret += "long"; - all_ws(); - if (consume(ID, "long")) return ret + " long"; - return ret; - } - if (ret) error("Failed to parse integer type"); - }; - - var float_type = function () { - var ret = ""; - all_ws(); - if (consume(ID, "unrestricted")) ret = "unrestricted "; - all_ws(); - if (consume(ID, "float")) return ret + "float"; - if (consume(ID, "double")) return ret + "double"; - if (ret) error("Failed to parse float type"); - }; - - var primitive_type = function () { - var num_type = integer_type() || float_type(); - if (num_type) return num_type; - all_ws(); - if (consume(ID, "boolean")) return "boolean"; - if (consume(ID, "byte")) return "byte"; - if (consume(ID, "octet")) return "octet"; - }; - - var const_value = function () { - if (consume(ID, "true")) return { type: "boolean", value: true }; - if (consume(ID, "false")) return { type: "boolean", value: false }; - if (consume(ID, "null")) return { type: "null" }; - if (consume(ID, "Infinity")) return { type: "Infinity", negative: false }; - if (consume(ID, "NaN")) return { type: "NaN" }; - var ret = consume(FLOAT) || consume(INT); - if (ret) return { type: "number", value: 1 * ret.value }; - var tok = consume(OTHER, "-"); - if (tok) { - if (consume(ID, "Infinity")) return { type: "Infinity", negative: true }; - else tokens.unshift(tok); - } - }; - - var type_suffix = function (obj) { - while (true) { - all_ws(); - if (consume(OTHER, "?")) { - if (obj.nullable) error("Can't nullable more than once"); - obj.nullable = true; - } - else if (consume(OTHER, "[")) { - all_ws(); - consume(OTHER, "]") || error("Unterminated array type"); - if (!obj.array) { - obj.array = 1; - obj.nullableArray = [obj.nullable]; - } - else { - obj.array++; - obj.nullableArray.push(obj.nullable); - } - obj.nullable = false; - } - else return; - } - }; - - var single_type = function () { - var prim = primitive_type() - , ret = { sequence: false, generic: null, nullable: false, array: false, union: false } - , name - , value - ; - if (prim) { - ret.idlType = prim; - } - else if (name = consume(ID)) { - value = name.value; - all_ws(); - // Generic types - if (consume(OTHER, "<")) { - // backwards compat - if (value === "sequence") { - ret.sequence = true; - } - ret.generic = value; - ret.idlType = type() || error("Error parsing generic type " + value); - all_ws(); - if (!consume(OTHER, ">")) error("Unterminated generic type " + value); - type_suffix(ret); - return ret; - } - else { - ret.idlType = value; - } - } - else { - return; - } - type_suffix(ret); - if (ret.nullable && !ret.array && ret.idlType === "any") error("Type any cannot be made nullable"); - return ret; - }; - - var union_type = function () { - all_ws(); - if (!consume(OTHER, "(")) return; - var ret = { sequence: false, generic: null, nullable: false, array: false, union: true, idlType: [] }; - var fst = type() || error("Union type with no content"); - ret.idlType.push(fst); - while (true) { - all_ws(); - if (!consume(ID, "or")) break; - var typ = type() || error("No type after 'or' in union type"); - ret.idlType.push(typ); - } - if (!consume(OTHER, ")")) error("Unterminated union type"); - type_suffix(ret); - return ret; - }; - - var type = function () { - return single_type() || union_type(); - }; - - var argument = function (store) { - var ret = { optional: false, variadic: false }; - ret.extAttrs = extended_attrs(store); - all_ws(store, "pea"); - var opt_token = consume(ID, "optional"); - if (opt_token) { - ret.optional = true; - all_ws(); - } - ret.idlType = type(); - if (!ret.idlType) { - if (opt_token) tokens.unshift(opt_token); - return; - } - var type_token = last_token; - if (!ret.optional) { - all_ws(); - if (tokens.length >= 3 && - tokens[0].type === "other" && tokens[0].value === "." && - tokens[1].type === "other" && tokens[1].value === "." && - tokens[2].type === "other" && tokens[2].value === "." - ) { - tokens.shift(); - tokens.shift(); - tokens.shift(); - ret.variadic = true; - } - } - all_ws(); - var name = consume(ID); - if (!name) { - if (opt_token) tokens.unshift(opt_token); - tokens.unshift(type_token); - return; - } - ret.name = name.value; - if (ret.optional) { - all_ws(); - ret["default"] = default_(); - } - return ret; - }; - - var argument_list = function (store) { - var ret = [] - , arg = argument(store ? ret : null) - ; - if (!arg) return; - ret.push(arg); - while (true) { - all_ws(store ? ret : null); - if (!consume(OTHER, ",")) return ret; - var nxt = argument(store ? ret : null) || error("Trailing comma in arguments list"); - ret.push(nxt); - } - }; - - var type_pair = function () { - all_ws(); - var k = type(); - if (!k) return; - all_ws() - if (!consume(OTHER, ",")) return; - all_ws(); - var v = type(); - if (!v) return; - return [k, v]; - }; - - var simple_extended_attr = function (store) { - all_ws(); - var name = consume(ID); - if (!name) return; - var ret = { - name: name.value - , "arguments": null - }; - all_ws(); - var eq = consume(OTHER, "="); - if (eq) { - var rhs; - all_ws(); - if (rhs = consume(ID)) { - ret.rhs = rhs - } - else if (consume(OTHER, "(")) { - // [Exposed=(Window,Worker)] - rhs = []; - var id = consume(ID); - if (id) { - rhs = [id.value]; - } - identifiers(rhs); - consume(OTHER, ")") || error("Unexpected token in extended attribute argument list or type pair"); - ret.rhs = { - type: "identifier-list", - value: rhs - }; - } - if (!ret.rhs) return error("No right hand side to extended attribute assignment"); - } - all_ws(); - if (consume(OTHER, "(")) { - var args, pair; - // [Constructor(DOMString str)] - if (args = argument_list(store)) { - ret["arguments"] = args; - } - // [MapClass(DOMString, DOMString)] - else if (pair = type_pair()) { - ret.typePair = pair; - } - // [Constructor()] - else { - ret["arguments"] = []; - } - all_ws(); - consume(OTHER, ")") || error("Unexpected token in extended attribute argument list or type pair"); - } - return ret; - }; - - // Note: we parse something simpler than the official syntax. It's all that ever - // seems to be used - var extended_attrs = function (store) { - var eas = []; - all_ws(store); - if (!consume(OTHER, "[")) return eas; - eas[0] = simple_extended_attr(store) || error("Extended attribute with not content"); - all_ws(); - while (consume(OTHER, ",")) { - eas.push(simple_extended_attr(store) || error("Trailing comma in extended attribute")); - all_ws(); - } - consume(OTHER, "]") || error("No end of extended attribute"); - return eas; - }; - - var default_ = function () { - all_ws(); - if (consume(OTHER, "=")) { - all_ws(); - var def = const_value(); - if (def) { - return def; - } - else if (consume(OTHER, "[")) { - if (!consume(OTHER, "]")) error("Default sequence value must be empty"); - return { type: "sequence", value: [] }; - } - else { - var str = consume(STR) || error("No value for default"); - str.value = str.value.replace(/^"/, "").replace(/"$/, ""); - return str; - } - } - }; - - var const_ = function (store) { - all_ws(store, "pea"); - if (!consume(ID, "const")) return; - var ret = { type: "const", nullable: false }; - all_ws(); - var typ = primitive_type(); - if (!typ) { - typ = consume(ID) || error("No type for const"); - typ = typ.value; - } - ret.idlType = typ; - all_ws(); - if (consume(OTHER, "?")) { - ret.nullable = true; - all_ws(); - } - var name = consume(ID) || error("No name for const"); - ret.name = name.value; - all_ws(); - consume(OTHER, "=") || error("No value assignment for const"); - all_ws(); - var cnt = const_value(); - if (cnt) ret.value = cnt; - else error("No value for const"); - all_ws(); - consume(OTHER, ";") || error("Unterminated const"); - return ret; - }; - - var inheritance = function () { - all_ws(); - if (consume(OTHER, ":")) { - all_ws(); - var inh = consume(ID) || error ("No type in inheritance"); - return inh.value; - } - }; - - var operation_rest = function (ret, store) { - all_ws(); - if (!ret) ret = {}; - var name = consume(ID); - ret.name = name ? name.value : null; - all_ws(); - consume(OTHER, "(") || error("Invalid operation"); - ret["arguments"] = argument_list(store) || []; - all_ws(); - consume(OTHER, ")") || error("Unterminated operation"); - all_ws(); - consume(OTHER, ";") || error("Unterminated operation"); - return ret; - }; - - var callback = function (store) { - all_ws(store, "pea"); - var ret; - if (!consume(ID, "callback")) return; - all_ws(); - var tok = consume(ID, "interface"); - if (tok) { - tokens.unshift(tok); - ret = interface_(); - ret.type = "callback interface"; - return ret; - } - var name = consume(ID) || error("No name for callback"); - ret = { type: "callback", name: name.value }; - all_ws(); - consume(OTHER, "=") || error("No assignment in callback"); - all_ws(); - ret.idlType = return_type(); - all_ws(); - consume(OTHER, "(") || error("No arguments in callback"); - ret["arguments"] = argument_list(store) || []; - all_ws(); - consume(OTHER, ")") || error("Unterminated callback"); - all_ws(); - consume(OTHER, ";") || error("Unterminated callback"); - return ret; - }; + var nonspecial_operation = function(store) { + all_ws(store, "pea"); + var ret = { + type: "operation", + getter: false, + setter: false, + creator: false, + deleter: false, + legacycaller: false, + "static": false, + stringifier: false + }; + ret.idlType = return_type(); + return operation_rest(ret, store); + } - var attribute = function (store) { - all_ws(store, "pea"); - var grabbed = [] - , ret = { - type: "attribute" - , "static": false - , stringifier: false - , inherit: false - , readonly: false - }; - if (consume(ID, "static")) { - ret["static"] = true; - grabbed.push(last_token); - } - else if (consume(ID, "stringifier")) { - ret.stringifier = true; - grabbed.push(last_token); - } - var w = all_ws(); - if (w) grabbed.push(w); - if (consume(ID, "inherit")) { - if (ret["static"] || ret.stringifier) error("Cannot have a static or stringifier inherit"); - ret.inherit = true; - grabbed.push(last_token); - var w = all_ws(); - if (w) grabbed.push(w); - } - if (consume(ID, "readonly")) { - ret.readonly = true; - grabbed.push(last_token); - var w = all_ws(); - if (w) grabbed.push(w); - } - if (!consume(ID, "attribute")) { - tokens = grabbed.concat(tokens); - return; - } - all_ws(); - ret.idlType = type() || error("No type in attribute"); - if (ret.idlType.sequence) error("Attributes cannot accept sequence types"); - all_ws(); - var name = consume(ID) || error("No name in attribute"); - ret.name = name.value; - all_ws(); - consume(OTHER, ";") || error("Unterminated attribute"); - return ret; - }; - - var return_type = function () { - var typ = type(); - if (!typ) { - if (consume(ID, "void")) { - return "void"; - } - else error("No return type"); - } - return typ; - }; - - var operation = function (store) { - all_ws(store, "pea"); - var ret = { - type: "operation" - , getter: false - , setter: false - , creator: false - , deleter: false - , legacycaller: false - , "static": false - , stringifier: false - }; - while (true) { - all_ws(); - if (consume(ID, "getter")) ret.getter = true; - else if (consume(ID, "setter")) ret.setter = true; - else if (consume(ID, "creator")) ret.creator = true; - else if (consume(ID, "deleter")) ret.deleter = true; - else if (consume(ID, "legacycaller")) ret.legacycaller = true; - else break; - } - if (ret.getter || ret.setter || ret.creator || ret.deleter || ret.legacycaller) { - all_ws(); - ret.idlType = return_type(); - operation_rest(ret, store); - return ret; - } - if (consume(ID, "static")) { - ret["static"] = true; - ret.idlType = return_type(); - operation_rest(ret, store); - return ret; - } - else if (consume(ID, "stringifier")) { - ret.stringifier = true;- - all_ws(); - if (consume(OTHER, ";")) return ret; - ret.idlType = return_type(); - operation_rest(ret, store); - return ret; - } - ret.idlType = return_type(); - all_ws(); - if (consume(ID, "iterator")) { - all_ws(); - ret.type = "iterator"; - if (consume(ID, "object")) { - ret.iteratorObject = "object"; - } - else if (consume(OTHER, "=")) { - all_ws(); - var name = consume(ID) || error("No right hand side in iterator"); - ret.iteratorObject = name.value; - } - all_ws(); - consume(OTHER, ";") || error("Unterminated iterator"); - return ret; - } - else { - operation_rest(ret, store); - return ret; - } - }; - - var identifiers = function (arr) { - while (true) { - all_ws(); - if (consume(OTHER, ",")) { - all_ws(); - var name = consume(ID) || error("Trailing comma in identifiers list"); - arr.push(name.value); - } - else break; - } - }; - - var serialiser = function (store) { - all_ws(store, "pea"); - if (!consume(ID, "serializer")) return; - var ret = { type: "serializer" }; - all_ws(); - if (consume(OTHER, "=")) { - all_ws(); - if (consume(OTHER, "{")) { - ret.patternMap = true; - all_ws(); - var id = consume(ID); - if (id && id.value === "getter") { - ret.names = ["getter"]; - } - else if (id && id.value === "inherit") { - ret.names = ["inherit"]; - identifiers(ret.names); - } - else if (id) { - ret.names = [id.value]; - identifiers(ret.names); - } - else { - ret.names = []; - } - all_ws(); - consume(OTHER, "}") || error("Unterminated serializer pattern map"); - } - else if (consume(OTHER, "[")) { - ret.patternList = true; - all_ws(); - var id = consume(ID); - if (id && id.value === "getter") { - ret.names = ["getter"]; - } - else if (id) { - ret.names = [id.value]; - identifiers(ret.names); - } - else { - ret.names = []; - } - all_ws(); - consume(OTHER, "]") || error("Unterminated serializer pattern list"); - } - else { - var name = consume(ID) || error("Invalid serializer"); - ret.name = name.value; - } - all_ws(); - consume(OTHER, ";") || error("Unterminated serializer"); - return ret; - } - else if (consume(OTHER, ";")) { - // noop, just parsing - } - else { - ret.idlType = return_type(); - all_ws(); - ret.operation = operation_rest(null, store); - } - return ret; - }; - - var iterable_type = function() { - if (consume(ID, "iterable")) return "iterable"; - else if (consume(ID, "legacyiterable")) return "legacyiterable"; - else if (consume(ID, "maplike")) return "maplike"; - else if (consume(ID, "setlike")) return "setlike"; - else return; - } - - var readonly_iterable_type = function() { - if (consume(ID, "maplike")) return "maplike"; - else if (consume(ID, "setlike")) return "setlike"; - else return; - } - - var iterable = function (store) { - all_ws(store, "pea"); - var grabbed = [], - ret = {type: null, idlType: null, readonly: false}; - if (consume(ID, "readonly")) { - ret.readonly = true; - grabbed.push(last_token); - var w = all_ws(); - if (w) grabbed.push(w); - } - var consumeItType = ret.readonly ? readonly_iterable_type : iterable_type; - - var ittype = consumeItType(); - if (!ittype) { - tokens = grabbed.concat(tokens); - return; - } - - var secondTypeRequired = ittype === "maplike"; - var secondTypeAllowed = secondTypeRequired || ittype === "iterable"; - ret.type = ittype; - if (ret.type !== 'maplike' && ret.type !== 'setlike') - delete ret.readonly; - all_ws(); - if (consume(OTHER, "<")) { - ret.idlType = type() || error("Error parsing " + ittype + " declaration"); - all_ws(); - if (secondTypeAllowed) { - var type2 = null; - if (consume(OTHER, ",")) { - all_ws(); - type2 = type(); - all_ws(); - } - if (type2) - ret.idlType = [ret.idlType, type2]; - else if (secondTypeRequired) - error("Missing second type argument in " + ittype + " declaration"); - } - if (!consume(OTHER, ">")) error("Unterminated " + ittype + " declaration"); - all_ws(); - if (!consume(OTHER, ";")) error("Missing semicolon after " + ittype + " declaration"); - } - else - error("Error parsing " + ittype + " declaration"); - - return ret; - } - - var interface_ = function (isPartial, store) { - all_ws(isPartial ? null : store, "pea"); - if (!consume(ID, "interface")) return; - all_ws(); - var name = consume(ID) || error("No name for interface"); - var mems = [] - , ret = { - type: "interface" - , name: name.value - , partial: false - , members: mems - }; - if (!isPartial) ret.inheritance = inheritance() || null; - all_ws(); - consume(OTHER, "{") || error("Bodyless interface"); - while (true) { - all_ws(store ? mems : null); - if (consume(OTHER, "}")) { - all_ws(); - consume(OTHER, ";") || error("Missing semicolon after interface"); - return ret; - } - var ea = extended_attrs(store ? mems : null); - all_ws(); - var cnt = const_(store ? mems : null); - if (cnt) { - cnt.extAttrs = ea; - ret.members.push(cnt); - continue; - } - var mem = (opt.allowNestedTypedefs && typedef(store ? mems : null)) || - iterable(store ? mems : null) || - serialiser(store ? mems : null) || - attribute(store ? mems : null) || - operation(store ? mems : null) || - error("Unknown member"); - mem.extAttrs = ea; - ret.members.push(mem); - } - }; - - var partial = function (store) { - all_ws(store, "pea"); - if (!consume(ID, "partial")) return; - var thing = dictionary(true, store) || - interface_(true, store) || - error("Partial doesn't apply to anything"); - thing.partial = true; - return thing; - }; - - var dictionary = function (isPartial, store) { - all_ws(isPartial ? null : store, "pea"); - if (!consume(ID, "dictionary")) return; - all_ws(); - var name = consume(ID) || error("No name for dictionary"); - var mems = [] - , ret = { - type: "dictionary" - , name: name.value - , partial: false - , members: mems - }; - if (!isPartial) ret.inheritance = inheritance() || null; - all_ws(); - consume(OTHER, "{") || error("Bodyless dictionary"); - while (true) { - all_ws(store ? mems : null); - if (consume(OTHER, "}")) { - all_ws(); - consume(OTHER, ";") || error("Missing semicolon after dictionary"); - return ret; - } - var ea = extended_attrs(store ? mems : null); - all_ws(store ? mems : null, "pea"); - var required = consume(ID, "required"); - var typ = type() || error("No type for dictionary member"); - all_ws(); - var name = consume(ID) || error("No name for dictionary member"); - var dflt = default_(); - if (required && dflt) error("Required member must not have a default"); - ret.members.push({ - type: "field" - , name: name.value - , required: !!required - , idlType: typ - , extAttrs: ea - , "default": dflt - }); - all_ws(); - consume(OTHER, ";") || error("Unterminated dictionary member"); - } - }; - - var exception = function (store) { - all_ws(store, "pea"); - if (!consume(ID, "exception")) return; - all_ws(); - var name = consume(ID) || error("No name for exception"); - var mems = [] - , ret = { - type: "exception" - , name: name.value - , members: mems - }; - ret.inheritance = inheritance() || null; - all_ws(); - consume(OTHER, "{") || error("Bodyless exception"); - while (true) { - all_ws(store ? mems : null); - if (consume(OTHER, "}")) { - all_ws(); - consume(OTHER, ";") || error("Missing semicolon after exception"); - return ret; - } - var ea = extended_attrs(store ? mems : null); - all_ws(store ? mems : null, "pea"); - var cnt = const_(); - if (cnt) { - cnt.extAttrs = ea; - ret.members.push(cnt); - } - else { - var typ = type(); - all_ws(); - var name = consume(ID); - all_ws(); - if (!typ || !name || !consume(OTHER, ";")) error("Unknown member in exception body"); - ret.members.push({ - type: "field" - , name: name.value - , idlType: typ - , extAttrs: ea - }); - } - } - }; - - var enum_ = function (store) { - all_ws(store, "pea"); - if (!consume(ID, "enum")) return; - all_ws(); - var name = consume(ID) || error("No name for enum"); - var vals = [] - , ret = { - type: "enum" - , name: name.value - , values: vals - }; - all_ws(); - consume(OTHER, "{") || error("No curly for enum"); - var saw_comma = false; - while (true) { - all_ws(store ? vals : null); - if (consume(OTHER, "}")) { - all_ws(); - consume(OTHER, ";") || error("No semicolon after enum"); - return ret; - } - var val = consume(STR) || error("Unexpected value in enum"); - ret.values.push(val.value.replace(/"/g, "")); - all_ws(store ? vals : null); - if (consume(OTHER, ",")) { - if (store) vals.push({ type: "," }); - all_ws(store ? vals : null); - saw_comma = true; - } - else { - saw_comma = false; - } - } - }; - - var typedef = function (store) { - all_ws(store, "pea"); - if (!consume(ID, "typedef")) return; - var ret = { - type: "typedef" - }; - all_ws(); - ret.typeExtAttrs = extended_attrs(); - all_ws(store, "tpea"); - ret.idlType = type() || error("No type in typedef"); - all_ws(); - var name = consume(ID) || error("No name in typedef"); - ret.name = name.value; - all_ws(); - consume(OTHER, ";") || error("Unterminated typedef"); - return ret; - }; - - var implements_ = function (store) { - all_ws(store, "pea"); - var target = consume(ID); - if (!target) return; - var w = all_ws(); - if (consume(ID, "implements")) { - var ret = { - type: "implements" - , target: target.value - }; - all_ws(); - var imp = consume(ID) || error("Incomplete implements statement"); - ret["implements"] = imp.value; - all_ws(); - consume(OTHER, ";") || error("No terminating ; for implements statement"); - return ret; - } - else { - // rollback - tokens.unshift(w); - tokens.unshift(target); - } - }; - - var definition = function (store) { - return callback(store) || - interface_(false, store) || - partial(store) || - dictionary(false, store) || - exception(store) || - enum_(store) || - typedef(store) || - implements_(store) - ; - }; - - var definitions = function (store) { - if (!tokens.length) return []; - var defs = []; - while (true) { - var ea = extended_attrs(store ? defs : null) - , def = definition(store ? defs : null); - if (!def) { - if (ea.length) error("Stray extended attributes"); - break; - } - def.extAttrs = ea; - defs.push(def); - } - return defs; - }; - var res = definitions(opt.ws); - if (tokens.length) error("Unrecognised tokens"); - return res; + var partial = function(store) { + all_ws(store, "pea"); + if (!consume(ID, "partial")) return; + var thing = dictionary(true, store) || + interface_(true, store) || + namespace(true, store) || + error("Partial doesn't apply to anything"); + thing.partial = true; + return thing; }; - var inNode = typeof module !== "undefined" && module.exports - , obj = { - parse: function (str, opt) { - if (!opt) opt = {}; - var tokens = tokenise(str); - return parse(tokens, opt); - } + var dictionary = function(isPartial, store) { + all_ws(isPartial ? null : store, "pea"); + if (!consume(ID, "dictionary")) return; + all_ws(); + var name = consume(ID) || error("No name for dictionary"); + var mems = [], + ret = { + type: "dictionary", + name: name.value, + partial: false, + members: mems + }; + if (!isPartial) ret.inheritance = inheritance() || null; + all_ws(); + consume(OTHER, "{") || error("Bodyless dictionary"); + while (true) { + all_ws(store ? mems : null); + if (consume(OTHER, "}")) { + all_ws(); + consume(OTHER, ";") || error("Missing semicolon after dictionary"); + return ret; + } + var ea = extended_attrs(store ? mems : null); + all_ws(store ? mems : null, "pea"); + var required = consume(ID, "required"); + var typ = type_with_extended_attributes() || error("No type for dictionary member"); + all_ws(); + var name = consume(ID) || error("No name for dictionary member"); + var dflt = default_(); + if (required && dflt) error("Required member must not have a default"); + var member = { + type: "field", + name: name.value, + required: !!required, + idlType: typ, + extAttrs: ea + }; + if (typeof dflt !== "undefined") { + member["default"] = dflt; + } + ret.members.push(member); + all_ws(); + consume(OTHER, ";") || error("Unterminated dictionary member"); + } }; - if (inNode) module.exports = obj; - else self.WebIDL2 = obj; + var exception = function(store) { + all_ws(store, "pea"); + if (!consume(ID, "exception")) return; + all_ws(); + var name = consume(ID) || error("No name for exception"); + var mems = [], + ret = { + type: "exception", + name: name.value, + members: mems + }; + ret.inheritance = inheritance() || null; + all_ws(); + consume(OTHER, "{") || error("Bodyless exception"); + while (true) { + all_ws(store ? mems : null); + if (consume(OTHER, "}")) { + all_ws(); + consume(OTHER, ";") || error("Missing semicolon after exception"); + return ret; + } + var ea = extended_attrs(store ? mems : null); + all_ws(store ? mems : null, "pea"); + var cnt = const_(); + if (cnt) { + cnt.extAttrs = ea; + ret.members.push(cnt); + } else { + var typ = type(); + all_ws(); + var name = consume(ID); + all_ws(); + if (!typ || !name || !consume(OTHER, ";")) error("Unknown member in exception body"); + ret.members.push({ + type: "field", + name: name.value, + idlType: typ, + extAttrs: ea + }); + } + } + }; + + var enum_ = function(store) { + all_ws(store, "pea"); + if (!consume(ID, "enum")) return; + all_ws(); + var name = consume(ID) || error("No name for enum"); + var vals = [], + ret = { + type: "enum", + name: name.value, + values: vals + }; + all_ws(); + consume(OTHER, "{") || error("No curly for enum"); + var saw_comma = false; + while (true) { + all_ws(store ? vals : null); + if (consume(OTHER, "}")) { + all_ws(); + consume(OTHER, ";") || error("No semicolon after enum"); + return ret; + } + var val = consume(STR) || error("Unexpected value in enum"); + ret.values.push(val.value.replace(/"/g, "")); + all_ws(store ? vals : null); + if (consume(OTHER, ",")) { + if (store) vals.push({ type: "," }); + all_ws(store ? vals : null); + saw_comma = true; + } else { + saw_comma = false; + } + } + }; + + var typedef = function(store) { + all_ws(store, "pea"); + if (!consume(ID, "typedef")) return; + var ret = { + type: "typedef" + }; + all_ws(); + ret.idlType = type_with_extended_attributes() || error("No type in typedef"); + all_ws(); + var name = consume(ID) || error("No name in typedef"); + ret.name = name.value; + all_ws(); + consume(OTHER, ";") || error("Unterminated typedef"); + return ret; + }; + + var implements_ = function(store) { + all_ws(store, "pea"); + var target = consume(ID); + if (!target) return; + var w = all_ws(); + if (consume(ID, "implements")) { + var ret = { + type: "implements", + target: target.value + }; + all_ws(); + var imp = consume(ID) || error("Incomplete implements statement"); + ret["implements"] = imp.value; + all_ws(); + consume(OTHER, ";") || error("No terminating ; for implements statement"); + return ret; + } else { + // rollback + tokens.unshift(w); + tokens.unshift(target); + } + }; + + var definition = function(store) { + return callback(store) || + interface_(false, store) || + partial(store) || + dictionary(false, store) || + exception(store) || + enum_(store) || + typedef(store) || + implements_(store) || + namespace(false, store); + }; + + var definitions = function(store) { + if (!tokens.length) return []; + var defs = []; + while (true) { + var ea = extended_attrs(store ? defs : null), + def = definition(store ? defs : null); + if (!def) { + if (ea.length) error("Stray extended attributes"); + break; + } + def.extAttrs = ea; + defs.push(def); + } + return defs; + }; + var res = definitions(opt.ws); + if (tokens.length) error("Unrecognised tokens"); + return res; + }; + + var obj = { + parse: function(str, opt) { + if (!opt) opt = {}; + var tokens = tokenise(str); + return parse(tokens, opt); + } + }; + + if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = obj; + } else if (typeof define === 'function' && define.amd) { + define([], function() { + return obj; + }); + } else { + (self || window).WebIDL2 = obj; + } }()); diff --git a/testing/web-platform/tests/resources/webidl2/lib/writer.js b/testing/web-platform/tests/resources/webidl2/lib/writer.js index ba8363738235..f7c79f828935 100644 --- a/testing/web-platform/tests/resources/webidl2/lib/writer.js +++ b/testing/web-platform/tests/resources/webidl2/lib/writer.js @@ -1,236 +1,280 @@ +(function() { -(function () { + var write = function(ast, opt) { + var curPea = "", + curTPea = "", + opt = opt || {}, + noop = function(str) { + return str; }, + optNames = "type".split(" "), + context = []; + for (var i = 0, n = optNames.length; i < n; i++) { + var o = optNames[i]; + if (!opt[o]) opt[o] = noop; + } - var write = function (ast, opt) { - var curPea = "" - , curTPea = "" - , opt = opt || {} - , noop = function (str) { return str; } - , optNames = "type".split(" ") - , context = [] - ; - for (var i = 0, n = optNames.length; i < n; i++) { - var o = optNames[i]; - if (!opt[o]) opt[o] = noop; + var literal = function(it) { + return it.value; + }; + var wsPea = function(it) { + curPea += it.value; + return ""; + }; + var wsTPea = function(it) { + curTPea += it.value; + return ""; + }; + var lineComment = function(it) { + return "//" + it.value + "\n"; + }; + var multilineComment = function(it) { + return "/*" + it.value + "*/"; + }; + var type = function(it) { + if (typeof it === "string") return opt.type(it); // XXX should maintain some context + if (it.union) return "(" + it.idlType.map(type).join(" or ") + ")"; + var ret = ""; + if (it.generic) ret += it.generic + "<"; + else if (it.sequence) ret += "sequence<"; + if (Array.isArray(it.idlType)) ret += it.idlType.map(type).join(", "); + else ret += type(it.idlType); + if (it.array || it.generic === 'Array') { + for (var i = 0, n = it.nullableArray.length; i < n; i++) { + var val = it.nullableArray[i]; + if (val) ret += "?"; + ret += "[]"; } - - var literal = function (it) { - return it.value; - }; - var wsPea = function (it) { - curPea += it.value; - return ""; - }; - var wsTPea = function (it) { - curTPea += it.value; - return ""; - }; - var lineComment = function (it) { - return "//" + it.value + "\n"; - }; - var multilineComment = function (it) { - return "/*" + it.value + "*/"; - }; - var type = function (it) { - if (typeof it === "string") return opt.type(it); // XXX should maintain some context - if (it.union) return "(" + it.idlType.map(type).join(" or ") + ")"; - var ret = ""; - if (it.sequence) ret += "sequence<"; - ret += type(it.idlType); - if (it.array) { - for (var i = 0, n = it.nullableArray.length; i < n; i++) { - var val = it.nullableArray[i]; - if (val) ret += "?"; - ret += "[]"; - } - } - if (it.sequence) ret += ">"; - if (it.nullable) ret += "?"; + } + if (it.generic || it.sequence) ret += ">"; + if (it.nullable) ret += "?"; - return ret; - }; - var const_value = function (it) { - var tp = it. type; - if (tp === "boolean") return it.value ? "true" : "false"; - else if (tp === "null") return "null"; - else if (tp === "Infinity") return (it.negative ? "-" : "") + "Infinity"; - else if (tp === "NaN") return "NaN"; - else if (tp === "number") return it.value; - else return '"' + it.value + '"'; - }; - var argument = function (arg, pea) { - var ret = extended_attributes(arg.extAttrs, pea); - if (arg.optional) ret += "optional "; - ret += type(arg.idlType); - if (arg.variadic) ret += "..."; - ret += " " + arg.name; - if (arg["default"]) ret += " = " + const_value(arg["default"]); - return ret; - }; - var args = function (its) { - var res = "" - , pea = "" - ; - for (var i = 0, n = its.length; i < n; i++) { - var arg = its[i]; - if (arg.type === "ws") res += arg.value; - else if (arg.type === "ws-pea") pea += arg.value; - else { - res += argument(arg, pea); - if (i < n - 1) res += ","; - pea = ""; - } - } - return res; - }; - var make_ext_at = function (it) { - if (it["arguments"] === null) return it.name; - context.unshift(it); - var ret = it.name + "(" + (it["arguments"].length ? args(it["arguments"]) : "") + ")"; - context.shift(); // XXX need to add more contexts, but not more than needed for ReSpec - return ret; - }; - var extended_attributes = function (eats, pea) { - if (!eats || !eats.length) return ""; - return "[" + eats.map(make_ext_at).join(", ") + "]" + pea; - }; - - var modifiers = "getter setter creator deleter legacycaller stringifier static".split(" "); - var operation = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - if (it.stringifier && !it.idlType) return "stringifier;"; - for (var i = 0, n = modifiers.length; i < n; i++) { - var mod = modifiers[i]; - if (it[mod]) ret += mod + " "; - } - ret += type(it.idlType) + " "; - if (it.name) ret += it.name; - ret += "(" + args(it["arguments"]) + ");"; - return ret; - }; - - var attribute = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - if (it["static"]) ret += "static "; - if (it.stringifier) ret += "stringifier "; - if (it.readonly) ret += "readonly "; - if (it.inherit) ret += "inherit "; - ret += "attribute " + type(it.idlType) + " " + it.name + ";"; - return ret; - }; - - var interface_ = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - if (it.partial) ret += "partial "; - ret += "interface " + it.name + " "; - if (it.inheritance) ret += ": " + it.inheritance + " "; - ret += "{" + iterate(it.members) + "};"; - return ret; - }; - - var dictionary = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - if (it.partial) ret += "partial "; - ret += "dictionary " + it.name + " "; - ret += "{" + iterate(it.members) + "};"; - return ret; - }; - var field = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - ret += type(it.idlType) + " " + it.name; - if (it["default"]) ret += " = " + const_value(it["default"]); - ret += ";"; - return ret; - }; - var exception = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - ret += "exception " + it.name + " "; - if (it.inheritance) ret += ": " + it.inheritance + " "; - ret += "{" + iterate(it.members) + "};"; - return ret; - }; - var const_ = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - return ret + "const " + type(it.idlType) + " " + it.name + " = " + const_value(it.value) + ";"; - }; - var typedef = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - ret += "typedef " + extended_attributes(it.typeExtAttrs, curTPea); - curTPea = ""; - return ret + type(it.idlType) + " " + it.name + ";"; - }; - var implements_ = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - return ret + it.target + " implements " + it["implements"] + ";"; - }; - var callback = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - return ret + "callback " + it.name + " = " + type(it.idlType) + - "(" + args(it["arguments"]) + ");"; - }; - var enum_ = function (it) { - var ret = extended_attributes(it.extAttrs, curPea); - curPea = ""; - ret += "enum " + it.name + " {"; - for (var i = 0, n = it.values.length; i < n; i++) { - var v = it.values[i]; - if (typeof v === "string") ret += '"' + v + '"'; - else if (v.type === "ws") ret += v.value; - else if (v.type === ",") ret += ","; - } - return ret + "};"; - }; - - var table = { - ws: literal - , "ws-pea": wsPea - , "ws-tpea": wsTPea - , "line-comment": lineComment - , "multiline-comment": multilineComment - , "interface": interface_ - , operation: operation - , attribute: attribute - , dictionary: dictionary - , field: field - , exception: exception - , "const": const_ - , typedef: typedef - , "implements": implements_ - , callback: callback - , "enum": enum_ - }; - var dispatch = function (it) { - return table[it.type](it); - }; - var iterate = function (things) { - if (!things) return; - var ret = ""; - for (var i = 0, n = things.length; i < n; i++) ret += dispatch(things[i]); - return ret; - }; - return iterate(ast); + return ret; + }; + var const_value = function(it) { + var tp = it.type; + if (tp === "boolean") return it.value ? "true" : "false"; + else if (tp === "null") return "null"; + else if (tp === "Infinity") return (it.negative ? "-" : "") + "Infinity"; + else if (tp === "NaN") return "NaN"; + else if (tp === "number") return it.value; + else return '"' + it.value + '"'; + }; + var argument = function(arg, pea) { + var ret = extended_attributes(arg.extAttrs, pea); + if (arg.optional) ret += "optional "; + ret += type(arg.idlType); + if (arg.variadic) ret += "..."; + ret += " " + arg.name; + if (arg["default"]) ret += " = " + const_value(arg["default"]); + return ret; + }; + var args = function(its) { + var res = "", + pea = ""; + for (var i = 0, n = its.length; i < n; i++) { + var arg = its[i]; + if (arg.type === "ws") res += arg.value; + else if (arg.type === "ws-pea") pea += arg.value; + else { + res += argument(arg, pea); + if (i < n - 1) res += ","; + pea = ""; + } + } + return res; + }; + var make_ext_at = function(it) { + if (it["arguments"] === null) return it.name; + context.unshift(it); + var ret = it.name + "(" + (it["arguments"].length ? args(it["arguments"]) : "") + ")"; + context.shift(); // XXX need to add more contexts, but not more than needed for ReSpec + return ret; + }; + var extended_attributes = function(eats, pea) { + if (!eats || !eats.length) return ""; + return "[" + eats.map(make_ext_at).join(", ") + "]" + pea; }; - - var inNode = typeof module !== "undefined" && module.exports - , obj = { - write: function (ast, opt) { - if (!opt) opt = {}; - return write(ast, opt); - } + var modifiers = "getter setter creator deleter legacycaller stringifier static".split(" "); + var operation = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + if (it.stringifier && !it.idlType) return "stringifier;"; + for (var i = 0, n = modifiers.length; i < n; i++) { + var mod = modifiers[i]; + if (it[mod]) ret += mod + " "; + } + ret += type(it.idlType) + " "; + if (it.name) ret += it.name; + ret += "(" + args(it["arguments"]) + ");"; + return ret; }; - if (inNode) module.exports = obj; - else window.WebIDL2Writer = obj; - + var attribute = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + if (it["static"]) ret += "static "; + if (it.stringifier) ret += "stringifier "; + if (it.readonly) ret += "readonly "; + if (it.inherit) ret += "inherit "; + ret += "attribute " + type(it.idlType) + " " + it.name + ";"; + return ret; + }; + + var interface_ = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + if (it.partial) ret += "partial "; + ret += "interface " + it.name + " "; + if (it.inheritance) ret += ": " + it.inheritance + " "; + ret += "{" + iterate(it.members) + "};"; + return ret; + }; + + var dictionary = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + if (it.partial) ret += "partial "; + ret += "dictionary " + it.name + " "; + ret += "{" + iterate(it.members) + "};"; + return ret; + }; + var field = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + if (it.required) ret += "required "; + ret += type(it.idlType) + " " + it.name; + if (it["default"]) ret += " = " + const_value(it["default"]); + ret += ";"; + return ret; + }; + var exception = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + ret += "exception " + it.name + " "; + if (it.inheritance) ret += ": " + it.inheritance + " "; + ret += "{" + iterate(it.members) + "};"; + return ret; + }; + var const_ = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + return ret + "const " + type(it.idlType) + " " + it.name + " = " + const_value(it.value) + ";"; + }; + var typedef = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + ret += "typedef " + extended_attributes(it.typeExtAttrs, curTPea); + curTPea = ""; + return ret + type(it.idlType) + " " + it.name + ";"; + }; + var implements_ = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + return ret + it.target + " implements " + it["implements"] + ";"; + }; + var callback = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + return ret + "callback " + it.name + " = " + type(it.idlType) + + "(" + args(it["arguments"]) + ");"; + }; + var enum_ = function(it) { + var ret = extended_attributes(it.extAttrs, curPea); + curPea = ""; + ret += "enum " + it.name + " {"; + for (var i = 0, n = it.values.length; i < n; i++) { + var v = it.values[i]; + if (typeof v === "string") ret += '"' + v + '"'; + else if (v.type === "ws") ret += v.value; + else if (v.type === ",") ret += ","; + } + return ret + "};"; + }; + var serializer = function(it) { + var ret = "serializer"; + if (it.name) { + ret += " = " + it.name + ";"; + } else if (it.patternList) { + ret += " = [ " + it.names.join(", ") + " ];"; + } else if (it.patternMap) { + ret += " = { " + it.names.join(", ") + " };"; + } else if (it.operation) { + ret += " " + operation(it); + } else { + ret += ";"; + } + return ret; + }; + var iterable = function(it) { + return "iterable<" + (it.idlType instanceof Array ? it.idlType.map(type).join(", ") : type(it.idlType)) + ">;"; + }; + var legacyiterable = function(it) { + return "legacyiterable<" + (it.idlType instanceof Array ? it.idlType.map(type).join(", ") : type(it.idlType)) + ">;"; + }; + var maplike = function(it) { + return (it.readonly ? "readonly " : "") + "maplike<" + + it.idlType.map(type).join(", ") + ">;"; + }; + var setlike = function(it) { + return (it.readonly ? "readonly " : "") + "setlike<" + + type(it.idlType) + ">;"; + }; + var callbackInterface = function(it) { + return 'callback ' + interface_(it); + }; + + var table = { + ws: literal, + "ws-pea": wsPea, + "ws-tpea": wsTPea, + "line-comment": lineComment, + "multiline-comment": multilineComment, + "interface": interface_, + operation: operation, + attribute: attribute, + dictionary: dictionary, + field: field, + exception: exception, + "const": const_, + typedef: typedef, + "implements": implements_, + callback: callback, + "enum": enum_, + serializer: serializer, + iterable: iterable, + legacyiterable: legacyiterable, + maplike: maplike, + setlike: setlike, + "callback interface": callbackInterface + }; + var dispatch = function(it) { + return table[it.type](it); + }; + var iterate = function(things) { + if (!things) return; + var ret = ""; + for (var i = 0, n = things.length; i < n; i++) ret += dispatch(things[i]); + return ret; + }; + return iterate(ast); + }; + + + var obj = { + write: function(ast, opt) { + if (!opt) opt = {}; + return write(ast, opt); + } + }; + + if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = obj; + } else if (typeof define === 'function' && define.amd) { + define([], function() { + return obj; + }); + } else { + (self || window).WebIDL2Writer = obj; + } }()); diff --git a/testing/web-platform/tests/resources/webidl2/package.json b/testing/web-platform/tests/resources/webidl2/package.json index c5ae7da2d593..02b2a9d9b164 100644 --- a/testing/web-platform/tests/resources/webidl2/package.json +++ b/testing/web-platform/tests/resources/webidl2/package.json @@ -1,17 +1,17 @@ { "name": "webidl2", "description": "A WebIDL Parser", - "version": "2.0.11", + "version": "2.4.0", "author": "Robin Berjon ", "license": "MIT", "dependencies": {}, "devDependencies": { - "mocha": "2.2.5", - "expect.js": "0.3.1", + "mocha": "3.2.0", + "expect": "1.20.2", "underscore": "1.8.3", - "jsondiffpatch": "0.1.31", + "jsondiffpatch": "0.2.4", "benchmark": "*", - "microtime": "1.4.2" + "microtime": "2.1.3" }, "scripts": { "test": "mocha" diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid.js b/testing/web-platform/tests/resources/webidl2/test/invalid.js index c98218037264..b8ab3a1866de 100644 --- a/testing/web-platform/tests/resources/webidl2/test/invalid.js +++ b/testing/web-platform/tests/resources/webidl2/test/invalid.js @@ -4,7 +4,7 @@ // are fully correct interpretations of the IDLs var wp = process.env.JSCOV ? require("../lib-cov/webidl2") : require("../lib/webidl2") -, expect = require("expect.js") +, expect = require("expect") , pth = require("path") , fs = require("fs") ; @@ -16,7 +16,7 @@ describe("Parses all of the invalid IDLs to check that they blow up correctly", .map(function (it) { return pth.join(dir, it); }) , errors = idls.map(function (it) { return pth.join(__dirname, "invalid", "json", pth.basename(it).replace(/\.w?idl/, ".json")); }) ; - + for (var i = 0, n = idls.length; i < n; i++) { var idl = idls[i], error = JSON.parse(fs.readFileSync(errors[i], "utf8")); var func = (function (idl, err) { @@ -30,11 +30,11 @@ describe("Parses all of the invalid IDLs to check that they blow up correctly", error = e; } finally { - expect(error).to.be.ok(); - expect(error.message).to.equal(err.message); - expect(error.line).to.equal(err.line); + expect(error).toExist(); + expect(error.message).toEqual(err.message); + expect(error.line).toEqual(err.line); } - + }; }(idl, error)); it("should produce the right error for " + idl, func); diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/record-key.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/record-key.widl new file mode 100644 index 000000000000..39dc386182f8 --- /dev/null +++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/record-key.widl @@ -0,0 +1,3 @@ +interface Foo { + void foo(record param); +}; diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/record-key.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/record-key.json new file mode 100644 index 000000000000..3b929b926a30 --- /dev/null +++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/record-key.json @@ -0,0 +1,4 @@ +{ + "message": "Record key must be DOMString, USVString, or ByteString", + "line": 2 +} diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax.js b/testing/web-platform/tests/resources/webidl2/test/syntax.js index 712542a6be8e..3b343e4229d5 100644 --- a/testing/web-platform/tests/resources/webidl2/test/syntax.js +++ b/testing/web-platform/tests/resources/webidl2/test/syntax.js @@ -1,6 +1,6 @@ var wp = process.env.JSCOV ? require("../lib-cov/webidl2") : require("../lib/webidl2") -, expect = require("expect.js") +, expect = require("expect") , pth = require("path") , fs = require("fs") , jdp = require("jsondiffpatch") @@ -14,7 +14,7 @@ describe("Parses all of the IDLs to produce the correct ASTs", function () { .map(function (it) { return pth.join(dir, it); }) , jsons = idls.map(function (it) { return pth.join(__dirname, "syntax/json", pth.basename(it).replace(".widl", ".json")); }) ; - + for (var i = 0, n = idls.length; i < n; i++) { var idl = idls[i], json = jsons[i]; @@ -28,7 +28,7 @@ describe("Parses all of the IDLs to produce the correct ASTs", function () { var diff = jdp.diff(JSON.parse(fs.readFileSync(json, "utf8")), wp.parse(fs.readFileSync(idl, "utf8"), opt)); if (diff && debug) console.log(JSON.stringify(diff, null, 4)); - expect(diff).to.be(undefined); + expect(diff).toBe(undefined); } catch (e) { console.log(e.toString()); diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/extended-attributes.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/extended-attributes.widl index f769c2559cc7..c1df79e142d5 100644 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/extended-attributes.widl +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/extended-attributes.widl @@ -3,4 +3,9 @@ [Global=(Worker,ServiceWorker), Exposed=ServiceWorker] interface ServiceWorkerGlobalScope : WorkerGlobalScope { -}; \ No newline at end of file +}; + +// Conformance with ExtendedAttributeList grammar in http://www.w3.org/TR/WebIDL/#idl-extended-attributes +// Section 3.11 +[IntAttr=0, FloatAttr=3.14, StringAttr="abc"] +interface IdInterface {}; diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/map.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/map.widl deleted file mode 100644 index 19b54f80a61a..000000000000 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/map.widl +++ /dev/null @@ -1,5 +0,0 @@ -// Extracted from https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ on 2014-05-06 - -[MapClass(DOMString, DOMString)] -interface HeaderMap { -}; diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/namespace.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/namespace.widl new file mode 100644 index 000000000000..d9610555e17a --- /dev/null +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/namespace.widl @@ -0,0 +1,10 @@ +// Extracted from Web IDL editors draft March 27 2017 +namespace VectorUtils { + readonly attribute Vector unit; + double dotProduct(Vector x, Vector y); + Vector crossProduct(Vector x, Vector y); +}; + +partial namespace SomeNamespace { + /* namespace_members... */ +}; \ No newline at end of file diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/record.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/record.widl new file mode 100644 index 000000000000..6cdedb219bec --- /dev/null +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/record.widl @@ -0,0 +1,8 @@ +[Constructor(record init)] +interface Foo { + void foo(sequence> param); + record bar(); + + // Make sure record can still be registered as a type. + record baz(); +}; diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-nested.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-nested.widl deleted file mode 100644 index 106f30b8f72e..000000000000 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-nested.widl +++ /dev/null @@ -1,22 +0,0 @@ - - interface Point { - attribute float x; - attribute float y; - }; - - - interface Rect { - attribute Point topleft; - attribute Point bottomright; - }; - - interface Widget { - typedef sequence PointSequence; - - readonly attribute Rect bounds; - - boolean pointWithinBounds(Point p); - boolean allPointsWithinBounds(PointSequence ps); - }; - - typedef [Clamp] octet value; \ No newline at end of file diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-union.idl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-union.idl new file mode 100644 index 000000000000..3048703e0c55 --- /dev/null +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-union.idl @@ -0,0 +1,4 @@ + typedef (ImageData or + HTMLImageElement or + HTMLCanvasElement or + HTMLVideoElement) TexImageSource; diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/uniontype.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/uniontype.widl index 4d99f0196308..0d5fe9be4286 100644 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/uniontype.widl +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/uniontype.widl @@ -1,3 +1,4 @@ interface Union { attribute (float or (Date or Event) or (Node or DOMString)?) test; + attribute ([EnforceRange] long or Date) test2; }; \ No newline at end of file diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/extended-attributes.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/extended-attributes.json index 228c4b824be3..3b5a3b2e22b3 100644 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/extended-attributes.json +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/extended-attributes.json @@ -26,5 +26,38 @@ } } ] + }, + { + "type": "interface", + "name": "IdInterface", + "partial": false, + "members": [], + "inheritance": null, + "extAttrs": [ + { + "name": "IntAttr", + "arguments": null, + "rhs": { + "type": "integer", + "value": "0" + } + }, + { + "name": "FloatAttr", + "arguments": null, + "rhs": { + "type": "float", + "value": "3.14" + } + }, + { + "name": "StringAttr", + "arguments": null, + "rhs": { + "type": "string", + "value": "\"abc\"" + } + } + ] } -] \ No newline at end of file +] diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json index a91f8c8eb53e..d87ea3b5f369 100644 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json @@ -1,7 +1,6 @@ [ { "type": "typedef", - "typeExtAttrs": [], "idlType": { "sequence": false, "generic": null, @@ -214,4 +213,4 @@ "inheritance": null, "extAttrs": [] } -] \ No newline at end of file +] diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/map.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/map.json deleted file mode 100644 index 03ce9412ed08..000000000000 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/map.json +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "type": "interface", - "name": "HeaderMap", - "partial": false, - "members": [], - "inheritance": null, - "extAttrs": [{ - "name": "MapClass", - "arguments": null, - "typePair": [{ - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "DOMString" - }, - { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "DOMString" - }] - }] - } -] diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/namespace.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/namespace.json new file mode 100644 index 000000000000..7c7ba771e1bf --- /dev/null +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/namespace.json @@ -0,0 +1,134 @@ +[ + { + "type": "namespace", + "name": "VectorUtils", + "partial": false, + "members": [ + { + "type": "attribute", + "static": false, + "stringifier": false, + "inherit": false, + "readonly": true, + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "Vector" + }, + "name": "unit", + "extAttrs": [] + }, + { + "type": "operation", + "getter": false, + "setter": false, + "creator": false, + "deleter": false, + "legacycaller": false, + "static": false, + "stringifier": false, + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "double" + }, + "name": "dotProduct", + "arguments": [ + { + "optional": false, + "variadic": false, + "extAttrs": [], + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "Vector" + }, + "name": "x" + }, + { + "optional": false, + "variadic": false, + "extAttrs": [], + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "Vector" + }, + "name": "y" + } + ], + "extAttrs": [] + }, + { + "type": "operation", + "getter": false, + "setter": false, + "creator": false, + "deleter": false, + "legacycaller": false, + "static": false, + "stringifier": false, + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "Vector" + }, + "name": "crossProduct", + "arguments": [ + { + "optional": false, + "variadic": false, + "extAttrs": [], + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "Vector" + }, + "name": "x" + }, + { + "optional": false, + "variadic": false, + "extAttrs": [], + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "Vector" + }, + "name": "y" + } + ], + "extAttrs": [] + } + ], + "extAttrs": [] + }, + { + "type": "namespace", + "name": "SomeNamespace", + "partial": true, + "members": [], + "extAttrs": [] + } +] \ No newline at end of file diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/record.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/record.json new file mode 100644 index 000000000000..d2a21a4acd99 --- /dev/null +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/record.json @@ -0,0 +1,184 @@ +[ + { + "type": "interface", + "name": "Foo", + "partial": false, + "members": [ + { + "type": "operation", + "getter": false, + "setter": false, + "creator": false, + "deleter": false, + "legacycaller": false, + "static": false, + "stringifier": false, + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "void" + }, + "name": "foo", + "arguments": [ + { + "optional": false, + "variadic": false, + "extAttrs": [], + "idlType": { + "sequence": true, + "generic": "sequence", + "nullable": false, + "array": false, + "union": false, + "idlType": { + "sequence": false, + "generic": "record", + "nullable": false, + "array": false, + "union": false, + "idlType": [ + { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "ByteString" + }, + { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "any" + } + ] + } + }, + "name": "param" + } + ], + "extAttrs": [] + }, + { + "type": "operation", + "getter": false, + "setter": false, + "creator": false, + "deleter": false, + "legacycaller": false, + "static": false, + "stringifier": false, + "idlType": { + "sequence": false, + "generic": "record", + "nullable": false, + "array": false, + "union": false, + "idlType": [ + { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "DOMString" + }, + { + "sequence": false, + "generic": null, + "nullable": true, + "array": false, + "union": true, + "idlType": [ + { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "float" + }, + { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "DOMString" + } + ] + } + ] + }, + "name": "bar", + "arguments": [], + "extAttrs": [] + }, + { + "type": "operation", + "getter": false, + "setter": false, + "creator": false, + "deleter": false, + "legacycaller": false, + "static": false, + "stringifier": false, + "idlType": { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "record" + }, + "name": "baz", + "arguments": [], + "extAttrs": [] + } + ], + "inheritance": null, + "extAttrs": [ + { + "name": "Constructor", + "arguments": [ + { + "optional": false, + "variadic": false, + "extAttrs": [], + "idlType": { + "sequence": false, + "generic": "record", + "nullable": false, + "array": false, + "union": false, + "idlType": [ + { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "USVString" + }, + { + "sequence": false, + "generic": null, + "nullable": false, + "array": false, + "union": false, + "idlType": "USVString" + } + ] + }, + "name": "init" + } + ] + } + ] + } +] diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-nested.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-nested.json deleted file mode 100644 index 76d138408ddf..000000000000 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-nested.json +++ /dev/null @@ -1,226 +0,0 @@ -[ - { - "type": "interface", - "name": "Point", - "partial": false, - "members": [ - { - "type": "attribute", - "static": false, - "stringifier": false, - "inherit": false, - "readonly": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "float" - }, - "name": "x", - "extAttrs": [] - }, - { - "type": "attribute", - "static": false, - "stringifier": false, - "inherit": false, - "readonly": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "float" - }, - "name": "y", - "extAttrs": [] - } - ], - "inheritance": null, - "extAttrs": [] - }, - { - "type": "interface", - "name": "Rect", - "partial": false, - "members": [ - { - "type": "attribute", - "static": false, - "stringifier": false, - "inherit": false, - "readonly": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Point" - }, - "name": "topleft", - "extAttrs": [] - }, - { - "type": "attribute", - "static": false, - "stringifier": false, - "inherit": false, - "readonly": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Point" - }, - "name": "bottomright", - "extAttrs": [] - } - ], - "inheritance": null, - "extAttrs": [] - }, - { - "type": "interface", - "name": "Widget", - "partial": false, - "members": [ - { - "type": "typedef", - "typeExtAttrs": [], - "idlType": { - "sequence": true, - "generic": "sequence", - "nullable": false, - "array": false, - "union": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Point" - } - }, - "name": "PointSequence", - "extAttrs": [] - }, - { - "type": "attribute", - "static": false, - "stringifier": false, - "inherit": false, - "readonly": true, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Rect" - }, - "name": "bounds", - "extAttrs": [] - }, - { - "type": "operation", - "getter": false, - "setter": false, - "creator": false, - "deleter": false, - "legacycaller": false, - "static": false, - "stringifier": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "boolean" - }, - "name": "pointWithinBounds", - "arguments": [ - { - "optional": false, - "variadic": false, - "extAttrs": [], - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Point" - }, - "name": "p" - } - ], - "extAttrs": [] - }, - { - "type": "operation", - "getter": false, - "setter": false, - "creator": false, - "deleter": false, - "legacycaller": false, - "static": false, - "stringifier": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "boolean" - }, - "name": "allPointsWithinBounds", - "arguments": [ - { - "optional": false, - "variadic": false, - "extAttrs": [], - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "PointSequence" - }, - "name": "ps" - } - ], - "extAttrs": [] - } - ], - "inheritance": null, - "extAttrs": [] - }, - { - "type": "typedef", - "typeExtAttrs": [ - { - "name": "Clamp", - "arguments": null - } - ], - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "octet" - }, - "name": "value", - "extAttrs": [] - } -] \ No newline at end of file diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-union.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-union.json new file mode 100644 index 000000000000..9c87672c8aeb --- /dev/null +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-union.json @@ -0,0 +1,49 @@ +[ + { + "type" : "typedef", + "idlType" : { + "nullable" : false, + "generic" : null, + "union" : true, + "idlType" : [ + { + "union" : false, + "generic" : null, + "nullable" : false, + "array" : false, + "sequence" : false, + "idlType" : "ImageData" + }, + { + "generic" : null, + "union" : false, + "nullable" : false, + "array" : false, + "idlType" : "HTMLImageElement", + "sequence" : false + }, + { + "array" : false, + "sequence" : false, + "idlType" : "HTMLCanvasElement", + "generic" : null, + "union" : false, + "nullable" : false + }, + { + "union" : false, + "generic" : null, + "nullable" : false, + "array" : false, + "sequence" : false, + "idlType" : "HTMLVideoElement" + } + ], + "sequence" : false, + "array" : false + }, + "name" : "TexImageSource", + "extAttrs" : [], + "typeExtAttrs" : [] + } +] diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json index ffdeea945d7f..d0854fa3d262 100644 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json @@ -44,7 +44,6 @@ }, { "type": "typedef", - "typeExtAttrs": [], "idlType": { "sequence": true, "generic": "sequence", @@ -206,21 +205,21 @@ }, { "type": "typedef", - "typeExtAttrs": [ - { - "name": "Clamp", - "arguments": null - } - ], "idlType": { "sequence": false, "generic": null, "nullable": false, "array": false, "union": false, - "idlType": "octet" + "idlType": "octet", + "extAttrs": [ + { + "name": "Clamp", + "arguments": null + } + ] }, "name": "value", "extAttrs": [] } -] \ No newline at end of file +] diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json index 43e25fd6bfb8..9da5e79f3625 100644 --- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json +++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json @@ -1,87 +1,127 @@ [ - { - "type": "interface", - "name": "Union", - "partial": false, - "members": [ - { - "type": "attribute", - "static": false, - "stringifier": false, - "inherit": false, - "readonly": false, - "idlType": { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": true, - "idlType": [ + { + "partial": false, + "members": [ + { + "idlType": { + "idlType": [ + { + "array": false, + "union": false, + "sequence": false, + "generic": null, + "idlType": "float", + "nullable": false + }, + { + "idlType": [ { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "float" + "nullable": false, + "idlType": "Date", + "sequence": false, + "generic": null, + "union": false, + "array": false }, { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": true, - "idlType": [ - { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Date" - }, - { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Event" - } - ] - }, - { - "sequence": false, - "generic": null, - "nullable": true, - "array": false, - "union": true, - "idlType": [ - { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "Node" - }, - { - "sequence": false, - "generic": null, - "nullable": false, - "array": false, - "union": false, - "idlType": "DOMString" - } - ] + "nullable": false, + "idlType": "Event", + "generic": null, + "sequence": false, + "array": false, + "union": false } - ] - }, - "name": "test", - "extAttrs": [] - } - ], - "inheritance": null, - "extAttrs": [] - } -] \ No newline at end of file + ], + "nullable": false, + "sequence": false, + "generic": null, + "array": false, + "union": true + }, + { + "generic": null, + "sequence": false, + "idlType": [ + { + "array": false, + "union": false, + "sequence": false, + "generic": null, + "nullable": false, + "idlType": "Node" + }, + { + "nullable": false, + "idlType": "DOMString", + "sequence": false, + "generic": null, + "array": false, + "union": false + } + ], + "nullable": true, + "union": true, + "array": false + } + ], + "nullable": false, + "generic": null, + "sequence": false, + "union": true, + "array": false + }, + "name": "test", + "inherit": false, + "type": "attribute", + "extAttrs": [], + "readonly": false, + "stringifier": false, + "static": false + }, + { + "readonly": false, + "extAttrs": [], + "stringifier": false, + "static": false, + "name": "test2", + "idlType": { + "nullable": false, + "idlType": [ + { + "extAttrs": [ + { + "name": "EnforceRange", + "arguments": null + } + ], + "nullable": false, + "idlType": "long", + "generic": null, + "sequence": false, + "array": false, + "union": false + }, + { + "array": false, + "union": false, + "sequence": false, + "generic": null, + "idlType": "Date", + "nullable": false + } + ], + "generic": null, + "sequence": false, + "union": true, + "array": false + }, + "inherit": false, + "type": "attribute" + } + ], + "inheritance": null, + "name": "Union", + "extAttrs": [], + "type": "interface" + } +] diff --git a/testing/web-platform/tests/resources/webidl2/test/web/make-web-tests.js b/testing/web-platform/tests/resources/webidl2/test/web/make-web-tests.js index 34c5a5c2b46d..1774806994e0 100644 --- a/testing/web-platform/tests/resources/webidl2/test/web/make-web-tests.js +++ b/testing/web-platform/tests/resources/webidl2/test/web/make-web-tests.js @@ -36,9 +36,10 @@ var pth = require("path") , " " , "
" , " " - , " " + , " " + , " " , " " - , " " + , " " , " " , " " , " " diff --git a/testing/web-platform/tests/resources/webidl2/test/web/run-tests.js b/testing/web-platform/tests/resources/webidl2/test/web/run-tests.js index a72800b8bdb8..452f799b2a6f 100644 --- a/testing/web-platform/tests/resources/webidl2/test/web/run-tests.js +++ b/testing/web-platform/tests/resources/webidl2/test/web/run-tests.js @@ -10,7 +10,7 @@ describe("Parses all of the IDLs to produce the correct ASTs", function () { // so we compare based on that var diff = jsondiffpatch.diff(json, WebIDL2.parse(idl)); if (diff && debug) console.log(JSON.stringify(diff, null, 4)); - expect(diff).to.be(undefined); + expect(diff).toBe(undefined); } catch (e) { console.log(e.toString()); @@ -36,11 +36,11 @@ describe("Parses all of the invalid IDLs to check that they blow up correctly", error = e; } finally { - expect(error).to.be.ok(); - expect(error.message).to.equal(err.message); - expect(error.line).to.equal(err.line); + expect(error).toExist(); + expect(error.message).toEqual(err.message); + expect(error.line).toEqual(err.line); } - + }; }(idl, error)); it("should produce the right error for " + i, func); diff --git a/testing/web-platform/tests/selection/collapse-00.html b/testing/web-platform/tests/selection/collapse-00.html index cc1eb7e6e1ef..6adaca4002dc 100644 --- a/testing/web-platform/tests/selection/collapse-00.html +++ b/testing/web-platform/tests/selection/collapse-00.html @@ -1,5 +1,5 @@ -Selection.collapse() tests +Selection.collapse()/setPosition() tests
@@ -9,6 +9,6 @@ diff --git a/testing/web-platform/tests/selection/collapse-15.html b/testing/web-platform/tests/selection/collapse-15.html new file mode 100644 index 000000000000..377e5044343c --- /dev/null +++ b/testing/web-platform/tests/selection/collapse-15.html @@ -0,0 +1,14 @@ + +Selection.collapse()/setPosition() tests + +
+ + + + + diff --git a/testing/web-platform/tests/selection/collapse-30.html b/testing/web-platform/tests/selection/collapse-30.html index 204586206b29..376633d9103e 100644 --- a/testing/web-platform/tests/selection/collapse-30.html +++ b/testing/web-platform/tests/selection/collapse-30.html @@ -1,5 +1,5 @@ -Selection.collapse() tests +Selection.collapse()/setPosition() tests
diff --git a/testing/web-platform/tests/selection/collapse-45.html b/testing/web-platform/tests/selection/collapse-45.html new file mode 100644 index 000000000000..28eee4eb7978 --- /dev/null +++ b/testing/web-platform/tests/selection/collapse-45.html @@ -0,0 +1,14 @@ + +Selection.collapse()/setPosition() tests + +
+ + + + + diff --git a/testing/web-platform/tests/selection/collapse.js b/testing/web-platform/tests/selection/collapse.js index 7c97e2725d6e..7d03f00c8c7b 100644 --- a/testing/web-platform/tests/selection/collapse.js +++ b/testing/web-platform/tests/selection/collapse.js @@ -1,6 +1,6 @@ "use strict"; -function testCollapse(range, point) { +function testCollapse(range, point, method) { selection.removeAllRanges(); var addedRange; if (range) { @@ -10,46 +10,46 @@ function testCollapse(range, point) { if (point[0].nodeType == Node.DOCUMENT_TYPE_NODE) { assert_throws("INVALID_NODE_TYPE_ERR", function() { - selection.collapse(point[0], point[1]); - }, "Must throw INVALID_NODE_TYPE_ERR when collapse()ing if the node is a DocumentType"); + selection[method](point[0], point[1]); + }, "Must throw INVALID_NODE_TYPE_ERR when " + method + "()ing if the node is a DocumentType"); return; } if (point[1] < 0 || point[1] > getNodeLength(point[0])) { assert_throws("INDEX_SIZE_ERR", function() { - selection.collapse(point[0], point[1]); - }, "Must throw INDEX_SIZE_ERR when collapse()ing if the offset is negative or greater than the node's length"); + selection[method](point[0], point[1]); + }, "Must throw INDEX_SIZE_ERR when " + method + "()ing if the offset is negative or greater than the node's length"); return; } if (!document.contains(point[0])) { assertSelectionNoChange(function() { - selection.collapse(point[0], point[1]); + selection[method](point[0], point[1]); }); return; } - selection.collapse(point[0], point[1]); + selection[method](point[0], point[1]); assert_equals(selection.rangeCount, 1, - "selection.rangeCount must equal 1 after collapse()"); + "selection.rangeCount must equal 1 after " + method + "()"); assert_equals(selection.focusNode, point[0], - "focusNode must equal the node we collapse()d to"); + "focusNode must equal the node we " + method + "()d to"); assert_equals(selection.focusOffset, point[1], - "focusOffset must equal the offset we collapse()d to"); + "focusOffset must equal the offset we " + method + "()d to"); assert_equals(selection.focusNode, selection.anchorNode, - "focusNode and anchorNode must be equal after collapse()"); + "focusNode and anchorNode must be equal after " + method + "()"); assert_equals(selection.focusOffset, selection.anchorOffset, - "focusOffset and anchorOffset must be equal after collapse()"); + "focusOffset and anchorOffset must be equal after " + method + "()"); if (range) { assert_equals(addedRange.startContainer, range.startContainer, - "collapse() must not change the startContainer of a preexisting Range"); + method + "() must not change the startContainer of a preexisting Range"); assert_equals(addedRange.endContainer, range.endContainer, - "collapse() must not change the endContainer of a preexisting Range"); + method + "() must not change the endContainer of a preexisting Range"); assert_equals(addedRange.startOffset, range.startOffset, - "collapse() must not change the startOffset of a preexisting Range"); + method + "() must not change the startOffset of a preexisting Range"); assert_equals(addedRange.endOffset, range.endOffset, - "collapse() must not change the endOffset of a preexisting Range"); + method + "() must not change the endOffset of a preexisting Range"); } } @@ -91,7 +91,10 @@ function testCollapseSubSet(startIndex, optionalEndIndex) { } }, "Set up range " + i + " " + testRanges[i]); for (var j = 0; j < testPoints.length; j++) { - tests.push(["Range " + i + " " + testRanges[i] + ", point " + j + " " + testPoints[j], range, testPointsCached[j]]); + tests.push(["collapse() on " + testRanges[i] + " to " + testPoints[j], + range, testPointsCached[j], "collapse"]); + tests.push(["setPosition() on " + testRanges[i] + " to " + testPoints[j], + range, testPointsCached[j], "setPosition"]); } } diff --git a/testing/web-platform/tests/selection/removeAllRanges.html b/testing/web-platform/tests/selection/removeAllRanges.html index cc6b69256084..286876f8bda1 100644 --- a/testing/web-platform/tests/selection/removeAllRanges.html +++ b/testing/web-platform/tests/selection/removeAllRanges.html @@ -1,5 +1,5 @@ -Selection.removeAllRanges() tests +Selection.removeAllRanges()/empty() tests
@@ -12,33 +12,38 @@ testRanges.unshift("[]"); var range = rangeFromEndpoints([paras[0].firstChild, 0, paras[0].firstChild, 1]); -for (var i = 0; i < testRanges.length; i++) { +function testRange(rangeDesc, method) { test(function() { - setSelectionForwards(eval(testRanges[i])); - selection.removeAllRanges(); + setSelectionForwards(eval(rangeDesc)); + selection[method](); assert_equals(selection.rangeCount, 0, - "After removeAllRanges(), rangeCount must be 0"); + "After " + method + "(), rangeCount must be 0"); // Test that it's forwards selection.addRange(range); assert_equals(selection.anchorOffset, selection.getRangeAt(0).startOffset, - "After removeAllRanges(), addRange() must be forwards, so anchorOffset must equal startOffset rather than endOffset"); + "After " + method + "(), addRange() must be forwards, so anchorOffset must equal startOffset rather than endOffset"); assert_equals(selection.focusOffset, selection.getRangeAt(0).endOffset, - "After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset"); - }, "Range " + i + " " + testRanges[i] + " forwards"); + "After " + method + "(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset"); + }, method + " on " + rangeDesc + " forwards"); // Copy-pasted from above test(function() { - setSelectionBackwards(eval(testRanges[i])); - selection.removeAllRanges(); + setSelectionBackwards(eval(rangeDesc)); + selection[method](); assert_equals(selection.rangeCount, 0, - "After removeAllRanges(), rangeCount must be 0"); + "After " + method + "(), rangeCount must be 0"); // Test that it's forwards selection.addRange(range); assert_equals(selection.anchorOffset, selection.getRangeAt(0).startOffset, - "After removeAllRanges(), addRange() must be forwards, so anchorOffset must equal startOffset rather than endOffset"); + "After " + method + "(), addRange() must be forwards, so anchorOffset must equal startOffset rather than endOffset"); assert_equals(selection.focusOffset, selection.getRangeAt(0).endOffset, - "After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset"); - }, "Range " + i + " " + testRanges[i] + " backwards"); + "After " + method + "(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset"); + }, method + " on " + rangeDesc + " backwards"); +} + +for (var i = 0; i < testRanges.length; i++) { + testRange(testRanges[i], "removeAllRanges"); + testRange(testRanges[i], "empty"); } testDiv.style.display = "none"; diff --git a/testing/web-platform/tests/selection/type.html b/testing/web-platform/tests/selection/type.html new file mode 100644 index 000000000000..7be8ba61bc20 --- /dev/null +++ b/testing/web-platform/tests/selection/type.html @@ -0,0 +1,31 @@ + +Selection.type tests +
+ + + + diff --git a/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html b/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html deleted file mode 100644 index 95237a6fd975..000000000000 --- a/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html +++ /dev/null @@ -1,89 +0,0 @@ - - -Selectors-API Level 2 Test Suite: HTML with Selectors Level 3 - - - - - - - - -
This test requires JavaScript.
- - diff --git a/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.js b/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.js deleted file mode 100644 index 5fd5d6941ac1..000000000000 --- a/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.js +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Check that the query and queryAll methods exist on the given Node - */ -function interfaceCheckQuery(type, obj) { - test(function() { - var q = typeof obj.query === "function"; - assert_true(q, type + " supports query."); - }, type + " supports query") - - test(function() { - var qa = typeof obj.queryAll === "function"; - assert_true( qa, type + " supports queryAll."); - }, type + " supports queryAll") -} - -/* - * Verify that the NodeList returned by queryAll is static and and that a new list is created after - * each call. A static list should not be affected by subsequent changes to the DOM. - */ -function verifyStaticList(type, doc, root) { - var pre, post, preLength; - - test(function() { - pre = root.queryAll("div"); - preLength = pre.length; - - var div = doc.createElement("div"); - (root.body || root).appendChild(div); - - assert_equals(pre.length, preLength, "The length of the NodeList should not change.") - }, type + ": static NodeList") - - test(function() { - post = root.queryAll("div"), - assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.") - }, type + ": new NodeList") -} - -/* - * Verify handling of special values for the selector parameter, including stringification of - * null and undefined, and the handling of the empty string. - */ -function runSpecialSelectorTests(type, root) { - test(function() { // 1 - assert_equals(root.queryAll(null).length, 1, "This should query one element with the tag name 'NULL'."); - }, type + ".queryAll null") - - test(function() { // 2 - assert_equals(root.queryAll(undefined).length, 1, "This should query one elements with the tag name 'UNDEFINED'."); - }, type + ".queryAll undefined") - - test(function() { // 3 - assert_throws(TypeError(), function() { - root.queryAll(); - }, "This should throw a TypeError.") - }, type + ".queryAll no parameter") - - test(function() { // 4 - var elm = root.query(null) - assert_not_equals(elm, null, "This should query an element."); - assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.") - }, type + ".query null") - - test(function() { // 5 - var elm = root.query(undefined) - assert_not_equals(elm, undefined, "This should query an element."); - assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.") - }, type + ".query undefined") - - test(function() { // 6 - assert_throws(TypeError(), function() { - root.query(); - }, "This should throw a TypeError.") - }, type + ".query no parameter.") - - test(function() { // 7 - result = root.queryAll("*"); - var i = 0; - traverse(root, function(elem) { - if (elem !== root) { - assert_equals(elem, result[i++], "The result in index " + i + " should be in tree order.") - } - }) - }, type + ".queryAll tree order"); -} - -/* - * Execute queries with the specified valid selectors for both query() and queryAll() - * Only run these tests when results are expected. Don't run for syntax error tests. - * - * context.queryAll(selector, refNodes) - * context.queryAll(selector) // Only if refNodes is not specified - * root.queryAll(selector, context) // Only if refNodes is not specified - * root.queryAll(selector, refNodes) // Only if context is not specified - * root.queryAll(selector) // Only if neither context nor refNodes is specified - * - * Equivalent tests will be run for .query() as well. - */ -function runValidSelectorTest(type, root, selectors, docType) { - var nodeType = getNodeType(root); - - for (var i = 0; i < selectors.length; i++) { - var s = selectors[i]; - var n = s["name"]; - var q = s["selector"]; - var e = s["expect"]; - - var ctx = s["ctx"]; - var ref = s["ref"]; - - if (!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) { - var foundall, found, context, refNodes, refArray; - - if (s["testType"] & TEST_FIND) { - - - /* - * If ctx and ref are specified: - * context.queryAll(selector, refNodes) - * context.query(selector, refNodes) - */ - if (ctx && ref) { - context = root.querySelector(ctx); - refNodes = root.querySelectorAll(ref); - refArray = Array.prototype.slice.call(refNodes, 0); - - test(function() { - foundall = context.queryAll(q, refNodes); - verifyNodeList(foundall, expect); - }, type + " [Context Element].queryAll: " + n + " (with refNodes NodeList): " + q); - - test(function() { - foundall = context.queryAll(q, refArray); - verifyNodeList(foundall, expect); - }, type + " [Context Element].queryAll: " + n + " (with refNodes Array): " + q); - - test(function() { - found = context.query(q, refNodes); - verifyElement(found, foundall, expect) - }, type + " [Context Element].query: " + n + " (with refNodes NodeList): " + q); - - test(function() { - found = context.query(q, refArray); - verifyElement(found, foundall, expect) - }, type + " [Context Element].query: " + n + " (with refNodes Array): " + q); - } - - - /* - * If ctx is specified, ref is not: - * context.queryAll(selector) - * context.query(selector) - * root.queryAll(selector, context) - * root.query(selector, context) - */ - if (ctx && !ref) { - context = root.querySelector(ctx); - - test(function() { - foundall = context.queryAll(q); - verifyNodeList(foundall, expect); - }, type + " [Context Element].queryAll: " + n + " (with no refNodes): " + q); - - test(function() { - found = context.query(q); - verifyElement(found, foundall, expect) - }, type + " [Context Element].query: " + n + " (with no refNodes): " + q); - - test(function() { - foundall = root.queryAll(q, context); - verifyNodeList(foundall, expect); - }, type + " [Root Node].queryAll: " + n + " (with refNode Element): " + q); - - test(function() { - foundall = root.query(q, context); - verifyElement(found, foundall, expect); - }, type + " [Root Node].query: " + n + " (with refNode Element): " + q); - } - - /* - * If ref is specified, ctx is not: - * root.queryAll(selector, refNodes) - * root.query(selector, refNodes) - */ - if (!ctx && ref) { - refNodes = root.querySelectorAll(ref); - refArray = Array.prototype.slice.call(refNodes, 0); - - test(function() { - foundall = root.queryAll(q, refNodes); - verifyNodeList(foundall, expect); - }, type + " [Root Node].queryAll: " + n + " (with refNodes NodeList): " + q); - - test(function() { - foundall = root.queryAll(q, refArray); - verifyNodeList(foundall, expect); - }, type + " [Root Node].queryAll: " + n + " (with refNodes Array): " + q); - - test(function() { - found = root.query(q, refNodes); - verifyElement(found, foundall, expect); - }, type + " [Root Node].query: " + n + " (with refNodes NodeList): " + q); - - test(function() { - found = root.query(q, refArray); - verifyElement(found, foundall, expect); - }, type + " [Root Node].query: " + n + " (with refNodes Array): " + q); - } - - /* - * If neither ctx nor ref is specified: - * root.queryAll(selector) - * root.query(selector) - */ - if (!ctx && !ref) { - test(function() { - foundall = root.queryAll(q); - verifyNodeList(foundall, expect); - }, type + ".queryAll: " + n + " (with no refNodes): " + q); - - test(function() { - found = root.query(q); - verifyElement(found, foundall, expect); - }, type + ".query: " + n + " (with no refNodes): " + q); - } - } - } - } -} - -/* - * Execute queries with the specified invalid selectors for both query() and queryAll() - * Only run these tests when errors are expected. Don't run for valid selector tests. - */ -function runInvalidSelectorTestQuery(type, root, selectors) { - for (var i = 0; i < selectors.length; i++) { - var s = selectors[i]; - var n = s["name"]; - var q = s["selector"]; - - test(function() { - assert_throws("SyntaxError", function() { - root.query(q) - }) - }, type + ".query: " + n + ": " + q); - - test(function() { - assert_throws("SyntaxError", function() { - root.queryAll(q) - }) - }, type + ".queryAll: " + n + ": " + q); - } -} - -function verifyNodeList(resultAll, expect) { - assert_not_equals(resultAll, null, "The method should not return null."); - assert_equals(resultAll.length, e.length, "The method should return the expected number of matches."); - - for (var i = 0; i < e.length; i++) { - assert_not_equals(resultAll[i], null, "The item in index " + i + " should not be null.") - assert_equals(resultAll[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID."); - assert_false(resultAll[i].hasAttribute("data-clone"), "This should not be a cloned element."); - } -} - -function verifyElement(result, resultAll, expect) { - if (expect.length > 0) { - assert_not_equals(result, null, "The method should return a match.") - assert_equals(found.getAttribute("id"), e[0], "The method should return the first match."); - assert_equals(result, resultAll[0], "The result should match the first item from querySelectorAll."); - assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element."); - } else { - assert_equals(result, null, "The method should not match anything."); - } -} diff --git a/testing/web-platform/tests/selectors/attribute-selectors/attribute-case/syntax.html b/testing/web-platform/tests/selectors/attribute-selectors/attribute-case/syntax.html index 9d895b8ef2d2..baa1244c7061 100644 --- a/testing/web-platform/tests/selectors/attribute-selectors/attribute-case/syntax.html +++ b/testing/web-platform/tests/selectors/attribute-selectors/attribute-case/syntax.html @@ -106,9 +106,7 @@ onload = function() { assert_equals(global.getComputedStyle(elm).visibility, 'visible', 'invalid selector matched'); }, s + ' in ' + global.mode); test(function() { - // Should be TypeError but this is not widely implemented yet - // and this isn't intended to be a querySelector API conformance test. - assert_throws(null, function() { + assert_throws("SyntaxError", function() { global.document.querySelector(s); }, 'invalid selector'); }, s + ' with querySelector in ' + global.mode); diff --git a/testing/web-platform/tests/server-timing/resources/blue.png b/testing/web-platform/tests/server-timing/resources/blue.png new file mode 100644 index 000000000000..4498dd258a20 Binary files /dev/null and b/testing/web-platform/tests/server-timing/resources/blue.png differ diff --git a/testing/web-platform/tests/server-timing/resources/blue.png.sub.headers b/testing/web-platform/tests/server-timing/resources/blue.png.sub.headers new file mode 100644 index 000000000000..5f3e54310d6a --- /dev/null +++ b/testing/web-platform/tests/server-timing/resources/blue.png.sub.headers @@ -0,0 +1 @@ +Server-Timing: metric2=3.4;blue.png diff --git a/testing/web-platform/tests/server-timing/resources/green.png b/testing/web-platform/tests/server-timing/resources/green.png new file mode 100644 index 000000000000..28a1faab3779 Binary files /dev/null and b/testing/web-platform/tests/server-timing/resources/green.png differ diff --git a/testing/web-platform/tests/server-timing/resources/green.png.sub.headers b/testing/web-platform/tests/server-timing/resources/green.png.sub.headers new file mode 100644 index 000000000000..1c6d74512a48 --- /dev/null +++ b/testing/web-platform/tests/server-timing/resources/green.png.sub.headers @@ -0,0 +1 @@ +Server-Timing: metric3=5.6;green.png diff --git a/testing/web-platform/tests/server-timing/test_server_timing.html b/testing/web-platform/tests/server-timing/test_server_timing.html new file mode 100644 index 000000000000..2a6ffa264999 --- /dev/null +++ b/testing/web-platform/tests/server-timing/test_server_timing.html @@ -0,0 +1,50 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/server-timing/test_server_timing.html.sub.headers b/testing/web-platform/tests/server-timing/test_server_timing.html.sub.headers new file mode 100644 index 000000000000..ddff591c1e4a --- /dev/null +++ b/testing/web-platform/tests/server-timing/test_server_timing.html.sub.headers @@ -0,0 +1 @@ +Server-Timing: metric1=1.2;document diff --git a/testing/web-platform/tests/service-workers/cache-storage/resources/test-helpers.js b/testing/web-platform/tests/service-workers/cache-storage/resources/test-helpers.js index d3b810942197..050ac0b54245 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/resources/test-helpers.js +++ b/testing/web-platform/tests/service-workers/cache-storage/resources/test-helpers.js @@ -141,23 +141,26 @@ var vary_entries = [ // Run |test_function| with a Cache object and a map of entries. Prior to the // call, the Cache is populated by cache entries from |entries|. The latter is // expected to be an Object mapping arbitrary keys to objects of the form -// {request: , response: }. There's no -// guarantee on the order in which entries will be added to the cache. +// {request: , response: }. Entries are +// serially added to the cache in the order specified. // // |test_function| should return a Promise that can be used with promise_test. function prepopulated_cache_test(entries, test_function, description) { cache_test(function(cache) { var p = Promise.resolve(); var hash = {}; - return Promise.all(entries.map(function(entry) { + entries.forEach(function(entry) { hash[entry.name] = entry; - return cache.put(entry.request.clone(), - entry.response.clone()) - .catch(function(e) { - assert_unreached( - 'Test setup failed for entry ' + entry.name + ': ' + e); - }); - })) + p = p.then(function() { + return cache.put(entry.request.clone(), entry.response.clone()) + .catch(function(e) { + assert_unreached( + 'Test setup failed for entry ' + entry.name + ': ' + e + ); + }); + }); + }); + return p .then(function() { assert_equals(Object.keys(hash).length, entries.length); }) @@ -236,6 +239,30 @@ function assert_response_in_array(actual, expected_array, description) { }), description); } +// Helper for testing with Request objects. Compares simple +// attributes defined on the interfaces, as well as the headers. +function assert_request_equals(actual, expected, description) { + assert_class_string(actual, "Request", description); + ["url"].forEach(function(attribute) { + assert_equals(actual[attribute], expected[attribute], + description + " Attributes differ: " + attribute + "."); + }); + assert_header_equals(actual.headers, expected.headers, description); +} + +// Asserts that two arrays |actual| and |expected| contain the same +// set of Requests as determined by assert_request_equals(). The +// corresponding elements must occupy corresponding indices in their +// respective arrays. +function assert_request_array_equals(actual, expected, description) { + assert_true(Array.isArray(actual), description); + assert_equals(actual.length, expected.length, description); + actual.forEach(function(value, index) { + assert_request_equals(value, expected[index], + description + " : object[" + index + "]"); + }); +} + // Deletes all caches, returning a promise indicating success. function delete_all_caches() { return self.caches.keys() diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-add.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-add.js index 237ba473504c..c03faeb0e837 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-add.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-add.js @@ -84,7 +84,7 @@ cache_test(function(cache) { }, 'Cache.add with request with null body (not consumed)'); cache_test(function(cache, test) { - return assert_promise_rejects( + return promise_rejects( test, new TypeError(), cache.add('../resources/fetch-status.py?status=206'), @@ -98,6 +98,7 @@ cache_test(function(cache, test) { return new Request(url); }); return promise_rejects( + test, new TypeError(), cache.addAll(requests), 'Cache.addAll should reject with TypeError if any request fails'); @@ -116,7 +117,7 @@ cache_test(function(cache, test) { return promise_rejects( test, new TypeError(), - cache.add('../resources/fetch-status.php?status=500'), + cache.add('../resources/fetch-status.py?status=500'), 'Cache.add should reject if response is !ok'); }, 'Cache.add with request that results in a status of 500'); diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-delete.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-delete.js index bf7841a7e5f6..3cf9aeb4c23a 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-delete.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-delete.js @@ -71,9 +71,39 @@ cache_test(function(cache) { .then(function(result) { assert_response_equals(result, response, 'Cache.delete should leave non-matching response in the cache.'); + return cache.delete(new Request(test_url, {method: 'HEAD'}), + {ignoreMethod: true}); + }) + .then(function(result) { + assert_true(result, + 'Cache.delete should match a non-GET request ' + + ' if ignoreMethod is true.'); }); }, 'Cache.delete called with a HEAD request'); +cache_test(function(cache) { + var vary_request = new Request('http://example.com/c', + {headers: {'Cookies': 'is-for-cookie'}}); + var vary_response = new Response('', {headers: {'Vary': 'Cookies'}}); + var mismatched_vary_request = new Request('http://example.com/c'); + + return cache.put(vary_request.clone(), vary_response.clone()) + .then(function() { + return cache.delete(mismatched_vary_request.clone()); + }) + .then(function(result) { + assert_false(result, + 'Cache.delete should not delete if vary does not ' + + 'match unless ignoreVary is true'); + return cache.delete(mismatched_vary_request.clone(), + {ignoreVary: true}); + }) + .then(function(result) { + assert_true(result, + 'Cache.delete should ignore vary if ignoreVary is true'); + }); + }, 'Cache.delete supports ignoreVary'); + cache_test(function(cache) { return cache.delete(test_url) .then(function(result) { @@ -83,33 +113,52 @@ cache_test(function(cache) { }); }, 'Cache.delete with a non-existent entry'); -var cache_entries = { - a: { - request: new Request('http://example.com/abc'), - response: new Response('') +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a_with_query.request, + { ignoreSearch: true }) + .then(function(result) { + assert_response_array_equals( + result, + [ + entries.a.response, + entries.a_with_query.response + ]); + return cache.delete(entries.a_with_query.request, + { ignoreSearch: true }); + }) + .then(function(result) { + return cache.matchAll(entries.a_with_query.request, + { ignoreSearch: true }); + }) + .then(function(result) { + assert_response_array_equals(result, []); + }); }, + 'Cache.delete with ignoreSearch option (request with search parameters)'); - b: { - request: new Request('http://example.com/b'), - response: new Response('') +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a_with_query.request, + { ignoreSearch: true }) + .then(function(result) { + assert_response_array_equals( + result, + [ + entries.a.response, + entries.a_with_query.response + ]); + // cache.delete()'s behavior should be the same if ignoreSearch is + // not provided or if ignoreSearch is false. + return cache.delete(entries.a_with_query.request, + { ignoreSearch: false }); + }) + .then(function(result) { + return cache.matchAll(entries.a_with_query.request, + { ignoreSearch: true }); + }) + .then(function(result) { + assert_response_array_equals(result, [ entries.a.response ]); + }); }, - - a_with_query: { - request: new Request('http://example.com/abc?q=r'), - response: new Response('') - } -}; - -function prepopulated_cache_test(test_function, description) { - cache_test(function(cache) { - return Promise.all(Object.keys(cache_entries).map(function(k) { - return cache.put(cache_entries[k].request.clone(), - cache_entries[k].response.clone()); - })) - .then(function() { - return test_function(cache); - }); - }, description); -} + 'Cache.delete with ignoreSearch option (when it is specified as false)'); done(); diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-keys.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-keys.js new file mode 100644 index 000000000000..96bd43b673a4 --- /dev/null +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-keys.js @@ -0,0 +1,192 @@ +if (self.importScripts) { + importScripts('/resources/testharness.js'); + importScripts('../resources/test-helpers.js'); +} + +cache_test(cache => { + return cache.keys() + .then(requests => { + assert_equals( + requests.length, 0, + 'Cache.keys should resolve to an empty array for an empty cache'); + }); + }, 'Cache.keys() called on an empty cache'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys('not-present-in-the-cache') + .then(function(result) { + assert_request_array_equals( + result, [], + 'Cache.keys should resolve with an empty array on failure.'); + }); + }, 'Cache.keys with no matching entries'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys(entries.a.request.url) + .then(function(result) { + assert_request_array_equals(result, [entries.a.request], + 'Cache.keys should match by URL.'); + }); + }, 'Cache.keys with URL'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys(entries.a.request) + .then(function(result) { + assert_request_array_equals( + result, [entries.a.request], + 'Cache.keys should match by Request.'); + }); + }, 'Cache.keys with Request'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys(new Request(entries.a.request.url)) + .then(function(result) { + assert_request_array_equals( + result, [entries.a.request], + 'Cache.keys should match by Request.'); + }); + }, 'Cache.keys with new Request'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys(entries.a.request, {ignoreSearch: true}) + .then(function(result) { + assert_request_array_equals( + result, + [ + entries.a.request, + entries.a_with_query.request + ], + 'Cache.keys with ignoreSearch should ignore the ' + + 'search parameters of cached request.'); + }); + }, + 'Cache.keys with ignoreSearch option (request with no search ' + + 'parameters)'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys(entries.a_with_query.request, {ignoreSearch: true}) + .then(function(result) { + assert_request_array_equals( + result, + [ + entries.a.request, + entries.a_with_query.request + ], + 'Cache.keys with ignoreSearch should ignore the ' + + 'search parameters of request.'); + }); + }, + 'Cache.keys with ignoreSearch option (request with search parameters)'); + +cache_test(function(cache) { + var request = new Request('http://example.com/'); + var head_request = new Request('http://example.com/', {method: 'HEAD'}); + var response = new Response('foo'); + return cache.put(request.clone(), response.clone()) + .then(function() { + return cache.keys(head_request.clone()); + }) + .then(function(result) { + assert_request_array_equals( + result, [], + 'Cache.keys should resolve with an empty array with a ' + + 'mismatched method.'); + return cache.keys(head_request.clone(), + {ignoreMethod: true}); + }) + .then(function(result) { + assert_request_array_equals( + result, + [ + request, + ], + 'Cache.keys with ignoreMethod should ignore the ' + + 'method of request.'); + }); + }, 'Cache.keys supports ignoreMethod'); + +cache_test(function(cache) { + var vary_request = new Request('http://example.com/c', + {headers: {'Cookies': 'is-for-cookie'}}); + var vary_response = new Response('', {headers: {'Vary': 'Cookies'}}); + var mismatched_vary_request = new Request('http://example.com/c'); + + return cache.put(vary_request.clone(), vary_response.clone()) + .then(function() { + return cache.keys(mismatched_vary_request.clone()); + }) + .then(function(result) { + assert_request_array_equals( + result, [], + 'Cache.keys should resolve with an empty array with a ' + + 'mismatched vary.'); + return cache.keys(mismatched_vary_request.clone(), + {ignoreVary: true}); + }) + .then(function(result) { + assert_request_array_equals( + result, + [ + vary_request, + ], + 'Cache.keys with ignoreVary should ignore the ' + + 'vary of request.'); + }); + }, 'Cache.keys supports ignoreVary'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys(entries.cat.request.url + '#mouse') + .then(function(result) { + assert_request_array_equals( + result, + [ + entries.cat.request, + ], + 'Cache.keys should ignore URL fragment.'); + }); + }, 'Cache.keys with URL containing fragment'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys('http') + .then(function(result) { + assert_request_array_equals( + result, [], + 'Cache.keys should treat query as a URL and not ' + + 'just a string fragment.'); + }); + }, 'Cache.keys with string fragment "http" as query'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys() + .then(function(result) { + assert_request_array_equals( + result, + [ + entries.a.request, + entries.b.request, + entries.a_with_query.request, + entries.A.request, + entries.a_https.request, + entries.a_org.request, + entries.cat.request, + entries.catmandu.request, + entries.cat_num_lives.request, + entries.cat_in_the_hat.request, + entries.non_2xx_response.request, + entries.error_response.request + ], + 'Cache.keys without parameters should match all entries.'); + }); + }, 'Cache.keys without parameters'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.keys(new Request(entries.cat.request.url, {method: 'HEAD'})) + .then(function(result) { + assert_request_array_equals( + result, [], + 'Cache.keys should not match HEAD request unless ignoreMethod ' + + 'option is set.'); + }); + }, 'Cache.keys with a HEAD Request'); + +done(); diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-match.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-match.js index 32c9ec92a698..3d00f0f04af3 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-match.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-match.js @@ -27,6 +27,23 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }); }, 'Cache.match with Request'); +prepopulated_cache_test(simple_entries, function(cache, entries) { + var alt_response = new Response('', {status: 201}); + + return self.caches.open('second_matching_cache') + .then(function(cache) { + return cache.put(entries.a.request, alt_response.clone()); + }) + .then(function() { + return cache.match(entries.a.request); + }) + .then(function(result) { + assert_response_equals( + result, entries.a.response, + 'Cache.match should match the first cache.'); + }); + }, 'Cache.match with multiple cache hits'); + prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match(new Request(entries.a.request.url)) .then(function(result) { @@ -76,6 +93,56 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }, 'Cache.match with ignoreSearch option (request with search parameter)'); +cache_test(function(cache) { + var request = new Request('http://example.com/'); + var head_request = new Request('http://example.com/', {method: 'HEAD'}); + var response = new Response('foo'); + return cache.put(request.clone(), response.clone()) + .then(function() { + return cache.match(head_request.clone()); + }) + .then(function(result) { + assert_equals( + result, undefined, + 'Cache.match should resolve as undefined with a ' + + 'mismatched method.'); + return cache.match(head_request.clone(), + {ignoreMethod: true}); + }) + .then(function(result) { + assert_response_equals( + result, response, + 'Cache.match with ignoreMethod should ignore the ' + + 'method of request.'); + }); + }, 'Cache.match supports ignoreMethod'); + +cache_test(function(cache) { + var vary_request = new Request('http://example.com/c', + {headers: {'Cookies': 'is-for-cookie'}}); + var vary_response = new Response('', {headers: {'Vary': 'Cookies'}}); + var mismatched_vary_request = new Request('http://example.com/c'); + + return cache.put(vary_request.clone(), vary_response.clone()) + .then(function() { + return cache.match(mismatched_vary_request.clone()); + }) + .then(function(result) { + assert_equals( + result, undefined, + 'Cache.match should resolve as undefined with a ' + + 'mismatched vary.'); + return cache.match(mismatched_vary_request.clone(), + {ignoreVary: true}); + }) + .then(function(result) { + assert_response_equals( + result, vary_response, + 'Cache.match with ignoreVary should ignore the ' + + 'vary of request.'); + }); + }, 'Cache.match supports ignoreVary'); + prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match(entries.cat.request.url + '#mouse') .then(function(result) { @@ -166,6 +233,36 @@ cache_test(function(cache) { }); }, 'Cache.match invoked multiple times for the same Request/Response'); +cache_test(function(cache) { + var request_url = new URL('../resources/simple.txt', location.href).href; + return fetch(request_url) + .then(function(fetch_result) { + return cache.put(new Request(request_url), fetch_result); + }) + .then(function() { + return cache.match(request_url); + }) + .then(function(result) { + return result.blob(); + }) + .then(function(blob) { + var sliced = blob.slice(2,8); + + return new Promise(function (resolve, reject) { + var reader = new FileReader(); + reader.onloadend = function(event) { + resolve(event.target.result); + }; + reader.readAsText(sliced); + }); + }) + .then(function(text) { + assert_equals(text, 'simple', + 'A Response blob returned by Cache.match should be ' + + 'sliceable.' ); + }); + }, 'Cache.match blob should be sliceable'); + prepopulated_cache_test(simple_entries, function(cache, entries) { var request = new Request(entries.a.request.clone(), {method: 'POST'}); return cache.match(request) @@ -218,7 +315,7 @@ cache_test(function(cache) { }) .then(function(text) { assert_equals(text, data.toString(), 'cloned body text can be read correctly'); - }) + }); }, 'Cache produces large Responses that can be cloned and read correctly.'); done(); diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-matchAll.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-matchAll.js index feace5a9899d..b7c7bd63785c 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-matchAll.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-matchAll.js @@ -6,7 +6,7 @@ if (self.importScripts) { prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.matchAll('not-present-in-the-cache') .then(function(result) { - assert_response_array_equivalent( + assert_response_array_equals( result, [], 'Cache.matchAll should resolve with an empty array on failure.'); }); @@ -52,7 +52,7 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.matchAll(entries.a.request, {ignoreSearch: true}) .then(function(result) { - assert_response_array_equivalent( + assert_response_array_equals( result, [ entries.a.response, @@ -69,7 +69,7 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.matchAll(entries.a_with_query.request, {ignoreSearch: true}) .then(function(result) { - assert_response_array_equivalent( + assert_response_array_equals( result, [ entries.a.response, @@ -79,12 +79,62 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { 'search parameters of request.'); }); }, - 'Cache.matchAll with ignoreSearch option (request with search parameter)'); + 'Cache.matchAll with ignoreSearch option (request with search parameters)'); + +cache_test(function(cache) { + var request = new Request('http://example.com/'); + var head_request = new Request('http://example.com/', {method: 'HEAD'}); + var response = new Response('foo'); + return cache.put(request.clone(), response.clone()) + .then(function() { + return cache.matchAll(head_request.clone()); + }) + .then(function(result) { + assert_response_array_equals( + result, [], + 'Cache.matchAll should resolve with empty array for a ' + + 'mismatched method.'); + return cache.matchAll(head_request.clone(), + {ignoreMethod: true}); + }) + .then(function(result) { + assert_response_array_equals( + result, [response], + 'Cache.matchAll with ignoreMethod should ignore the ' + + 'method of request.'); + }); + }, 'Cache.matchAll supports ignoreMethod'); + +cache_test(function(cache) { + var vary_request = new Request('http://example.com/c', + {headers: {'Cookies': 'is-for-cookie'}}); + var vary_response = new Response('', {headers: {'Vary': 'Cookies'}}); + var mismatched_vary_request = new Request('http://example.com/c'); + + return cache.put(vary_request.clone(), vary_response.clone()) + .then(function() { + return cache.matchAll(mismatched_vary_request.clone()); + }) + .then(function(result) { + assert_response_array_equals( + result, [], + 'Cache.matchAll should resolve as undefined with a ' + + 'mismatched vary.'); + return cache.matchAll(mismatched_vary_request.clone(), + {ignoreVary: true}); + }) + .then(function(result) { + assert_response_array_equals( + result, [vary_response], + 'Cache.matchAll with ignoreVary should ignore the ' + + 'vary of request.'); + }); + }, 'Cache.matchAll supports ignoreVary'); prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.matchAll(entries.cat.request.url + '#mouse') .then(function(result) { - assert_response_array_equivalent( + assert_response_array_equals( result, [ entries.cat.response, @@ -96,17 +146,40 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.matchAll('http') .then(function(result) { - assert_response_array_equivalent( + assert_response_array_equals( result, [], 'Cache.matchAll should treat query as a URL and not ' + 'just a string fragment.'); }); }, 'Cache.matchAll with string fragment "http" as query'); +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll() + .then(function(result) { + assert_response_array_equals( + result, + [ + entries.a.response, + entries.b.response, + entries.a_with_query.response, + entries.A.response, + entries.a_https.response, + entries.a_org.response, + entries.cat.response, + entries.catmandu.response, + entries.cat_num_lives.response, + entries.cat_in_the_hat.response, + entries.non_2xx_response.response, + entries.error_response.response + ], + 'Cache.matchAll without parameters should match all entries.'); + }); + }, 'Cache.matchAll without parameters'); + prepopulated_cache_test(vary_entries, function(cache, entries) { return cache.matchAll('http://example.com/c') .then(function(result) { - assert_response_array_equivalent( + assert_response_array_equals( result, [ entries.vary_cookie_absent.response @@ -122,7 +195,7 @@ prepopulated_cache_test(vary_entries, function(cache, entries) { {headers: {'Cookies': 'none-of-the-above'}})); }) .then(function(result) { - assert_response_array_equivalent( + assert_response_array_equals( result, [ ], @@ -137,7 +210,7 @@ prepopulated_cache_test(vary_entries, function(cache, entries) { {headers: {'Cookies': 'is-for-cookie'}})); }) .then(function(result) { - assert_response_array_equivalent( + assert_response_array_equals( result, [entries.vary_cookie_is_cookie.response], 'Cache.matchAll should match the entire header if a vary header ' + @@ -149,15 +222,16 @@ prepopulated_cache_test(vary_entries, function(cache, entries) { return cache.matchAll('http://example.com/c', {ignoreVary: true}) .then(function(result) { - assert_response_array_equivalent( + assert_response_array_equals( result, [ entries.vary_cookie_is_cookie.response, entries.vary_cookie_is_good.response, entries.vary_cookie_absent.response ], - 'Cache.matchAll should honor "ignoreVary" parameter.'); + 'Cache.matchAll should support multiple vary request/response ' + + 'pairs.'); }); - }, 'Cache.matchAll with "ignoreVary" parameter'); + }, 'Cache.matchAll with multiple vary pairs'); done(); diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-put.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-put.js index 9e9fd67a3fe9..467e0b38e9c3 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-put.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-put.js @@ -102,18 +102,32 @@ cache_test(function(cache) { }); }, 'Cache.put with an empty response body'); -cache_test(function(cache) { +cache_test(function(cache, test) { var request = new Request(test_url); var response = new Response('', { status: 206, headers: [['Content-Type', 'text/plain']] }); - return assert_promise_rejects( - cache.put(request, response), + return promise_rejects( + test, new TypeError(), + cache.put(request, response), 'Cache.put should reject 206 Responses with a TypeError.'); - }, 'Cache.put with 206 response'); + }, 'Cache.put with synthetic 206 response'); + +cache_test(function(cache, test) { + var test_url = new URL('../resources/fetch-status.py?status=206', location.href).href; + var request = new Request(test_url); + var response; + return fetch(test_url) + .then(function(fetch_result) { + assert_equals(fetch_result.status, 206, + 'Test framework error: The status code should be 206.'); + response = fetch_result.clone(); + return promise_rejects(test, new TypeError, cache.put(request, fetch_result)); + }); + }, 'Cache.put with HTTP 206 response'); cache_test(function(cache) { var test_url = new URL('../resources/fetch-status.py?status=500', location.href).href; diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage-match.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage-match.js index 21517b1eccdd..354652048642 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage-match.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage-match.js @@ -133,4 +133,110 @@ promise_test(function(test) { }); }, 'CacheStorageMatch with no caches available but name provided'); +cache_test(function(cache) { + var transaction = create_unique_transaction(); + + return self.caches.delete('') + .then(function() { + return self.caches.has(''); + }) + .then(function(has_cache) { + assert_false(has_cache, "The cache should not exist."); + return cache.put(transaction.request, transaction.response.clone()); + }) + .then(function() { + return self.caches.match(transaction.request, {cacheName: ''}); + }) + .then(function(response) { + assert_equals(response, undefined, + 'The response should not be found.'); + return self.caches.open(''); + }) + .then(function(cache) { + return cache.put(transaction.request, transaction.response); + }) + .then(function() { + return self.caches.match(transaction.request, {cacheName: ''}); + }) + .then(function(response) { + assert_response_equals(response, transaction.response, + 'The response should be matched.'); + return self.caches.delete(''); + }); +}, 'CacheStorageMatch with empty cache name provided'); + +cache_test(function(cache) { + var request = new Request('http://example.com/?foo'); + var no_query_request = new Request('http://example.com/'); + var response = new Response('foo'); + return cache.put(request.clone(), response.clone()) + .then(function() { + return self.caches.match(no_query_request.clone()); + }) + .then(function(result) { + assert_equals( + result, undefined, + 'CacheStorageMatch should resolve as undefined with a ' + + 'mismatched query.'); + return self.caches.match(no_query_request.clone(), + {ignoreSearch: true}); + }) + .then(function(result) { + assert_response_equals( + result, response, + 'CacheStorageMatch with ignoreSearch should ignore the ' + + 'query of the request.'); + }); + }, 'CacheStorageMatch supports ignoreSearch'); + +cache_test(function(cache) { + var request = new Request('http://example.com/'); + var head_request = new Request('http://example.com/', {method: 'HEAD'}); + var response = new Response('foo'); + return cache.put(request.clone(), response.clone()) + .then(function() { + return self.caches.match(head_request.clone()); + }) + .then(function(result) { + assert_equals( + result, undefined, + 'CacheStorageMatch should resolve as undefined with a ' + + 'mismatched method.'); + return self.caches.match(head_request.clone(), + {ignoreMethod: true}); + }) + .then(function(result) { + assert_response_equals( + result, response, + 'CacheStorageMatch with ignoreMethod should ignore the ' + + 'method of request.'); + }); + }, 'Cache.match supports ignoreMethod'); + +cache_test(function(cache) { + var vary_request = new Request('http://example.com/c', + {headers: {'Cookies': 'is-for-cookie'}}); + var vary_response = new Response('', {headers: {'Vary': 'Cookies'}}); + var mismatched_vary_request = new Request('http://example.com/c'); + + return cache.put(vary_request.clone(), vary_response.clone()) + .then(function() { + return self.caches.match(mismatched_vary_request.clone()); + }) + .then(function(result) { + assert_equals( + result, undefined, + 'CacheStorageMatch should resolve as undefined with a ' + + ' mismatched vary.'); + return self.caches.match(mismatched_vary_request.clone(), + {ignoreVary: true}); + }) + .then(function(result) { + assert_response_equals( + result, vary_response, + 'CacheStorageMatch with ignoreVary should ignore the ' + + 'vary of request.'); + }); + }, 'CacheStorageMatch supports ignoreVary'); + done(); diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage.js index 521d3bbc25df..2011afd69581 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage.js @@ -15,6 +15,40 @@ promise_test(function(t) { }); }, 'CacheStorage.open'); +promise_test(function(t) { + var cache_name = 'cache-storage/bar'; + var first_cache = null; + var second_cache = null; + return self.caches.open(cache_name) + .then(function(cache) { + first_cache = cache; + return self.caches.delete(cache_name); + }) + .then(function() { + return first_cache.add('../resources/simple.txt'); + }) + .then(function() { + return self.caches.keys(); + }) + .then(function(cache_names) { + assert_equals(cache_names.indexOf(cache_name), -1); + return self.caches.open(cache_name); + }) + .then(function(cache) { + second_cache = cache; + return second_cache.keys(); + }) + .then(function(keys) { + assert_equals(keys.length, 0); + return first_cache.keys(); + }) + .then(function(keys) { + assert_equals(keys.length, 1); + // Clean up + return self.caches.delete(cache_name); + }); + }, 'CacheStorage.delete dooms, but does not delete immediately'); + promise_test(function(t) { // Note that this test may collide with other tests running in the same // origin that also uses an empty cache name. diff --git a/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-keys.https.html b/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-keys.https.html new file mode 100644 index 000000000000..736f74d98960 --- /dev/null +++ b/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-keys.https.html @@ -0,0 +1,10 @@ + +Cache.keys + + + + + + diff --git a/testing/web-platform/tests/service-workers/cache-storage/window/cache-keys.https.html b/testing/web-platform/tests/service-workers/cache-storage/window/cache-keys.https.html new file mode 100644 index 000000000000..8398c33e146c --- /dev/null +++ b/testing/web-platform/tests/service-workers/cache-storage/window/cache-keys.https.html @@ -0,0 +1,8 @@ + +Cache Storage: Cache.keys + + + + + + diff --git a/testing/web-platform/tests/service-workers/cache-storage/worker/cache-keys.https.html b/testing/web-platform/tests/service-workers/cache-storage/worker/cache-keys.https.html new file mode 100644 index 000000000000..6bafe21d30bb --- /dev/null +++ b/testing/web-platform/tests/service-workers/cache-storage/worker/cache-keys.https.html @@ -0,0 +1,9 @@ + +Cache.keys + + + + + diff --git a/testing/web-platform/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/error-worker.js b/testing/web-platform/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/error-worker.js new file mode 100644 index 000000000000..f6838ffb3947 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/error-worker.js @@ -0,0 +1,12 @@ +var source; + +self.addEventListener('message', function(e) { + source = e.source; + throw 'testError'; +}); + +self.addEventListener('error', function(e) { + source.postMessage({ + error: e.error, filename: e.filename, message: e.message, lineno: e.lineno, + colno: e.colno}); +}); diff --git a/testing/web-platform/tests/service-workers/service-worker/ServiceWorkerGlobalScope/service-worker-error-event.https.html b/testing/web-platform/tests/service-workers/service-worker/ServiceWorkerGlobalScope/service-worker-error-event.https.html new file mode 100644 index 000000000000..988f5466b9e1 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/ServiceWorkerGlobalScope/service-worker-error-event.https.html @@ -0,0 +1,31 @@ + +ServiceWorkerGlobalScope: Error event error message + + + + diff --git a/testing/web-platform/tests/service-workers/service-worker/client-id.https.html b/testing/web-platform/tests/service-workers/service-worker/client-id.https.html new file mode 100644 index 000000000000..a53c10c96919 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/client-id.https.html @@ -0,0 +1,55 @@ + +Service Worker: Client.id + + + + diff --git a/testing/web-platform/tests/service-workers/service-worker/clients-get-client-types.https.html b/testing/web-platform/tests/service-workers/service-worker/clients-get-client-types.https.html new file mode 100644 index 000000000000..0005f98c4bb4 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/clients-get-client-types.https.html @@ -0,0 +1,69 @@ + +Service Worker: Clients.get with window and worker clients + + + + diff --git a/testing/web-platform/tests/service-workers/service-worker/clients-get-cross-origin.https.html b/testing/web-platform/tests/service-workers/service-worker/clients-get-cross-origin.https.html index d5622054de82..1e4acfb286c6 100644 --- a/testing/web-platform/tests/service-workers/service-worker/clients-get-cross-origin.https.html +++ b/testing/web-platform/tests/service-workers/service-worker/clients-get-cross-origin.https.html @@ -7,36 +7,63 @@ diff --git a/testing/web-platform/tests/service-workers/service-worker/clients-get.https.html b/testing/web-platform/tests/service-workers/service-worker/clients-get.https.html index 85c70a2f1dc8..45da2b35eff0 100644 --- a/testing/web-platform/tests/service-workers/service-worker/clients-get.https.html +++ b/testing/web-platform/tests/service-workers/service-worker/clients-get.https.html @@ -2,69 +2,67 @@ Service Worker: Clients.get - diff --git a/testing/web-platform/tests/service-workers/service-worker/clients-matchall-client-types.https.html b/testing/web-platform/tests/service-workers/service-worker/clients-matchall-client-types.https.html index 3be0fe2ac723..420e4e0d5e3b 100644 --- a/testing/web-platform/tests/service-workers/service-worker/clients-matchall-client-types.https.html +++ b/testing/web-platform/tests/service-workers/service-worker/clients-matchall-client-types.https.html @@ -8,36 +8,36 @@ var scope = 'resources/clients-matchall-client-types'; var iframe_url = scope + '-iframe.html'; var shared_worker_url = scope + '-shared-worker.js'; -/* visibilityState, focused, url, frameType */ +/* visibilityState, focused, url, type, frameType */ var expected_only_window = [ ['visible', true, new URL(iframe_url, location).href, 'window', 'nested'] ]; var expected_only_shared_worker = [ - [,,new URL(shared_worker_url, location).href, 'sharedworker', 'none'] + [undefined, undefined, new URL(shared_worker_url, location).href, 'sharedworker', 'none'] ]; var expected_window_and_shared_worker = [ - ['visible', true, new URL(iframe_url, location).href, 'window', 'nested'], - [,,new URL(shared_worker_url, location).href, 'sharedworker', 'none'] + expected_only_window[0], expected_only_shared_worker[0] ]; function test_matchall(frame, expected, query_options) { // Make sure the frame gets focus. frame.focus(); - expected.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; }); return new Promise(function(resolve, reject) { var channel = new MessageChannel(); - channel.port1.onmessage = function(e) { - if (typeof e.data === 'string') { - return reject(e.data); - } - assert_equals(e.data.length, expected.length); - for (var i = 0; i < e.data.length; i++) - assert_array_equals(e.data[i], expected[i]); - resolve(); - }; + channel.port1.onmessage = function(e) { resolve(e.data); }; frame.contentWindow.navigator.serviceWorker.controller.postMessage( {port:channel.port2, options:query_options}, [channel.port2]); + }).then(function(data) { + if (typeof data === 'string') { + throw new Error(data); + } + + assert_equals(data.length, expected.length, 'result count'); + + for (var i = 0; i < data.length; ++i) { + assert_array_equals(data[i], expected[i]); + } }); } diff --git a/testing/web-platform/tests/service-workers/service-worker/clients-matchall-on-evaluation.https.html b/testing/web-platform/tests/service-workers/service-worker/clients-matchall-on-evaluation.https.html new file mode 100644 index 000000000000..8705f85b5684 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/clients-matchall-on-evaluation.https.html @@ -0,0 +1,24 @@ + +Service Worker: Clients.matchAll on script evaluation + + + + diff --git a/testing/web-platform/tests/service-workers/service-worker/extendable-event-waituntil.https.html b/testing/web-platform/tests/service-workers/service-worker/extendable-event-waituntil.https.html index b2029ae42614..8e790d0ef5ad 100644 --- a/testing/web-platform/tests/service-workers/service-worker/extendable-event-waituntil.https.html +++ b/testing/web-platform/tests/service-workers/service-worker/extendable-event-waituntil.https.html @@ -16,14 +16,17 @@ function runTest(test, scope, onRegister) { // |obj.synced| to true once ack'd. function syncWorker(test, worker, obj) { var channel = new MessageChannel(); - channel.port1.onmessage = test.step_func(function(e) { - var message = e.data; - assert_equals(message, 'SYNC', - 'Should receive sync message from worker.'); - obj.synced = true; - channel.port1.postMessage('ACK'); - }); worker.postMessage({port: channel.port2}, [channel.port2]); + return new Promise(function(resolve) { + channel.port1.onmessage = test.step_func(function(e) { + var message = e.data; + assert_equals(message, 'SYNC', + 'Should receive sync message from worker.'); + obj.synced = true; + channel.port1.postMessage('ACK'); + resolve(); + }); + }); } async_test(function(t) { @@ -68,13 +71,28 @@ async_test(function(t) { async_test(function(t) { var scope = 'resources/install-reject-precedence'; var onRegister = function(worker) { - var obj = {}; + var obj1 = {}; + var obj2 = {}; wait_for_state(t, worker, 'redundant') .then(function() { + assert_true( + obj1.synced, + 'The "redundant" state was entered after the first "extend ' + + 'lifetime promise" resolved.' + ); + assert_true( + obj2.synced, + 'The "redundant" state was entered after the third "extend ' + + 'lifetime promise" resolved.' + ); service_worker_unregister_and_done(t, scope); }) .catch(unreached_rejection(t)); - syncWorker(t, worker, obj); + + syncWorker(t, worker, obj1) + .then(function() { + syncWorker(t, worker, obj2); + }); }; runTest(t, scope, onRegister); }, 'Test ExtendableEvent waitUntil reject precedence.'); diff --git a/testing/web-platform/tests/service-workers/service-worker/fetch-csp.https.html b/testing/web-platform/tests/service-workers/service-worker/fetch-csp.https.html index 9f3365056a98..91a774a133fd 100644 --- a/testing/web-platform/tests/service-workers/service-worker/fetch-csp.https.html +++ b/testing/web-platform/tests/service-workers/service-worker/fetch-csp.https.html @@ -5,28 +5,107 @@ diff --git a/testing/web-platform/tests/service-workers/service-worker/fetch-event-async-respond-with.https.html b/testing/web-platform/tests/service-workers/service-worker/fetch-event-async-respond-with.https.html index 912e709ca38f..a2b93acfc5b2 100644 --- a/testing/web-platform/tests/service-workers/service-worker/fetch-event-async-respond-with.https.html +++ b/testing/web-platform/tests/service-workers/service-worker/fetch-event-async-respond-with.https.html @@ -1,6 +1,5 @@ - - + + + diff --git a/testing/web-platform/tests/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html b/testing/web-platform/tests/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html index 5d3346e7b281..cd6861a9d453 100644 --- a/testing/web-platform/tests/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html +++ b/testing/web-platform/tests/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html @@ -1,6 +1,5 @@ - - diff --git a/testing/web-platform/tests/service-workers/service-worker/interfaces.https.html b/testing/web-platform/tests/service-workers/service-worker/interfaces.https.html index 403a005344ec..889142fe3af9 100644 --- a/testing/web-platform/tests/service-workers/service-worker/interfaces.https.html +++ b/testing/web-platform/tests/service-workers/service-worker/interfaces.https.html @@ -13,7 +13,9 @@ test(function() { { register: 'function', getRegistration: 'function', - oncontrollerchange: EVENT_HANDLER + oncontrollerchange: EVENT_HANDLER, + onmessage: EVENT_HANDLER, + onmessageerror: EVENT_HANDLER }); }, 'Interfaces and attributes of ServiceWorkerContainer'); diff --git a/testing/web-platform/tests/service-workers/service-worker/navigation-preload/resource-timing.https.html b/testing/web-platform/tests/service-workers/service-worker/navigation-preload/resource-timing.https.html new file mode 100644 index 000000000000..5f0953c76d13 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/navigation-preload/resource-timing.https.html @@ -0,0 +1,92 @@ + + +Navigation Preload Resource Timing + + + + diff --git a/testing/web-platform/tests/service-workers/service-worker/navigation-preload/resources/resource-timing-scope.py b/testing/web-platform/tests/service-workers/service-worker/navigation-preload/resources/resource-timing-scope.py new file mode 100644 index 000000000000..1820be4400e3 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/navigation-preload/resources/resource-timing-scope.py @@ -0,0 +1,19 @@ +import zlib + +def main(request, response): + type = request.GET.first("type") + + if type == "normal": + content = "This is Navigation Preload Resource Timing test." + output = zlib.compress(content, 9) + headers = [("Content-type", "text/plain"), + ("Content-Encoding", "deflate"), + ("X-Decoded-Body-Size", len(content)), + ("X-Encoded-Body-Size", len(output)), + ("Content-Length", len(output))] + return headers, output + + if type == "redirect": + response.status = 302 + response.headers.append("Location", "redirect-redirected.html") + return "" diff --git a/testing/web-platform/tests/service-workers/service-worker/navigation-preload/resources/resource-timing-worker.js b/testing/web-platform/tests/service-workers/service-worker/navigation-preload/resources/resource-timing-worker.js new file mode 100644 index 000000000000..46af6456aec3 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/navigation-preload/resources/resource-timing-worker.js @@ -0,0 +1,19 @@ +self.addEventListener('activate', event => { + event.waitUntil(self.registration.navigationPreload.enable()); + }); + +self.addEventListener('fetch', event => { + event.respondWith( + event.preloadResponse + .then(response => { + var headers = response.headers; + return response.text().then(text => + new Response( + JSON.stringify({ + decodedBodySize: headers.get('X-Decoded-Body-Size'), + encodedBodySize: headers.get('X-Encoded-Body-Size'), + timingEntries: performance.getEntriesByName(event.request.url) + }), + {headers: {'Content-Type': 'text/html'}})); + })); + }); diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/client-id-worker.js b/testing/web-platform/tests/service-workers/service-worker/resources/client-id-worker.js new file mode 100644 index 000000000000..ec71b3458b72 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/resources/client-id-worker.js @@ -0,0 +1,27 @@ +self.onmessage = function(e) { + var port = e.data.port; + var message = []; + + var promise = Promise.resolve() + .then(function() { + // 1st matchAll() + return self.clients.matchAll().then(function(clients) { + clients.forEach(function(client) { + message.push(client.id); + }); + }); + }) + .then(function() { + // 2nd matchAll() + return self.clients.matchAll().then(function(clients) { + clients.forEach(function(client) { + message.push(client.id); + }); + }); + }) + .then(function() { + // Send an array containing ids of clients from 1st and 2nd matchAll() + port.postMessage(message); + }); + e.waitUntil(promise); +}; diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-client-types-frame.html b/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-client-types-frame.html new file mode 100644 index 000000000000..7c949110082e --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-client-types-frame.html @@ -0,0 +1,10 @@ + + diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-client-types-shared-worker.js b/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-client-types-shared-worker.js new file mode 100644 index 000000000000..fadef970374b --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-client-types-shared-worker.js @@ -0,0 +1,10 @@ +onconnect = function(e) { + var port = e.ports[0]; + fetch('clientId') + .then(function(response) { + return response.text(); + }) + .then(function(text) { + port.postMessage({clientId: text}); + }); +}; diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-cross-origin-frame.html b/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-cross-origin-frame.html new file mode 100644 index 000000000000..eaade327bc59 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-cross-origin-frame.html @@ -0,0 +1,53 @@ + + + + + + diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-worker.js b/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-worker.js index 9ac2c2264589..ca4444f35335 100644 --- a/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-worker.js +++ b/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-worker.js @@ -1,53 +1,48 @@ +// This worker is designed to expose information about clients that is only available from Service Worker contexts. +// +// In the case of the `onfetch` handler, it provides the `clientId` property of +// the `event` object. In the case of the `onmessage` handler, it provides the +// Client instance attributes of the requested clients. self.onfetch = function(e) { - if (e.request.url.indexOf("clients-get-frame.html") >= 0) { - if (e.clientId === null) { - e.respondWith(fetch(e.request)); - } else { - e.respondWith(Response.error()); - } + if (e.request.mode === 'navigate' && e.clientId !== null) { + e.respondWith(Response.error( + '`clientId` incorrectly set to non-null value for request with mode `navigate`' + )); + return; + } + + if (/\/clientId$/.test(e.request.url)) { + e.respondWith(new Response(e.clientId)); 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 = []; + var client_ids = 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]; + e.waitUntil(Promise.all( + client_ids.map(function(client_id) { + return self.clients.get(client_id); + })) + .then(function(clients) { + // No matching client for a given id or a matched client is off-origin + // from the service worker. + if (clients.length == 1 && clients[0] == undefined) { + port.postMessage(clients[0]); } else { - message = client; + 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); } - port.postMessage(message); - }); - } + })); }; diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-client-types-iframe.html b/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-client-types-iframe.html index 51b4dca03141..7607b035de31 100644 --- a/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-client-types-iframe.html +++ b/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-client-types-iframe.html @@ -4,5 +4,5 @@ Change the page URL using the History API to ensure that ServiceWorkerClient uses the creation URL. --> - + diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-on-evaluation-worker.js b/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-on-evaluation-worker.js new file mode 100644 index 000000000000..f1559aca39b6 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-on-evaluation-worker.js @@ -0,0 +1,11 @@ +importScripts('test-helpers.sub.js'); + +var page_url = normalizeURL('../clients-matchall-on-evaluation.https.html'); + +self.clients.matchAll({includeUncontrolled: true}) + .then(function(clients) { + clients.forEach(function(client) { + if (client.url == page_url) + client.postMessage('matched'); + }); + }); diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-worker.js b/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-worker.js index 8849b2ce2b9d..d6634f4d40ef 100644 --- a/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-worker.js +++ b/testing/web-platform/tests/service-workers/service-worker/resources/clients-matchall-worker.js @@ -2,29 +2,30 @@ 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, - client.type, - frame_type]); - }); - // Sort by url - if (!e.data.disableSort) { - message.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; }); - } - port.postMessage(message); - }) - .catch(e => { - port.postMessage('clients.matchAll() rejected: ' + e); - }) + e.waitUntil(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, + client.type, + frame_type]); + }); + // Sort by url + if (!e.data.disableSort) { + message.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; }); + } + port.postMessage(message); + }) + .catch(e => { + port.postMessage('clients.matchAll() rejected: ' + e); + })); }; diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/extendable-event-waituntil.js b/testing/web-platform/tests/service-workers/service-worker/resources/extendable-event-waituntil.js index 48fdf1b99fd1..20a9eb023f62 100644 --- a/testing/web-platform/tests/service-workers/service-worker/resources/extendable-event-waituntil.js +++ b/testing/web-platform/tests/service-workers/service-worker/resources/extendable-event-waituntil.js @@ -57,8 +57,20 @@ oninstall = function(e) { e.waitUntil(fulfillPromise()); break; case 'install-reject-precedence': + // Three "extend lifetime promises" are needed to verify that the user + // agent waits for all promises to settle even in the event of rejection. + // The first promise is fulfilled on demand by the client, the second is + // immediately scheduled for rejection, and the third is fulfilled on + // demand by the client (but only after the first promise has been + // fulfilled). + // + // User agents which simply expose `Promise.all` semantics in this case + // (by entering the "redundant state" following the rejection of the + // second promise but prior to the fulfillment of the third) can be + // identified from the client context. e.waitUntil(fulfillPromise()); e.waitUntil(rejectPromise()); + e.waitUntil(fulfillPromise()); break; } }; diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-csp-iframe.html b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-csp-iframe.html index df2183643854..33bf0416d585 100644 --- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-csp-iframe.html +++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-csp-iframe.html @@ -1,72 +1,16 @@ - - diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-respond-with-argument-iframe.html b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-respond-with-argument-iframe.html new file mode 100644 index 000000000000..33b47e78a349 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-respond-with-argument-iframe.html @@ -0,0 +1,55 @@ + + diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-respond-with-argument-worker.js b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-respond-with-argument-worker.js new file mode 100644 index 000000000000..712c4b73c9bc --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-respond-with-argument-worker.js @@ -0,0 +1,14 @@ +self.addEventListener('fetch', function(event) { + var testcase = new URL(event.request.url).search; + switch (testcase) { + case '?response-object': + event.respondWith(new Response('body')); + break; + case '?response-promise-object': + event.respondWith(Promise.resolve(new Response('body'))); + break; + case '?other-value': + event.respondWith(new Object()); + break; + } + }); diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-test-worker.js b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-test-worker.js index 55ba4ab4d116..61ae85e98986 100644 --- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-test-worker.js +++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-test-worker.js @@ -113,6 +113,11 @@ function handleIntegrity(event) { event.respondWith(new Response(event.request.integrity)); } +function handleHeaders(event) { + const headers = Array.from(event.request.headers); + event.respondWith(new Response(JSON.stringify(headers))); +} + self.addEventListener('fetch', function(event) { var url = event.request.url; var handlers = [ @@ -132,6 +137,7 @@ self.addEventListener('fetch', function(event) { { pattern: '?cache', fn: handleCache }, { pattern: '?eventsource', fn: handleEventSource }, { pattern: '?integrity', fn: handleIntegrity }, + { pattern: '?headers', fn: handleHeaders }, ]; var handler = null; diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/import-mime-type-worker.py b/testing/web-platform/tests/service-workers/service-worker/resources/import-mime-type-worker.py new file mode 100644 index 000000000000..aa885e7a4de0 --- /dev/null +++ b/testing/web-platform/tests/service-workers/service-worker/resources/import-mime-type-worker.py @@ -0,0 +1,10 @@ +def main(request, response): + if 'mime' in request.GET: + return ( + [('Content-Type', 'application/javascript')], + "importScripts('./mime-type-worker.py?mime={0}');".format(request.GET['mime']) + ) + return ( + [('Content-Type', 'application/javascript')], + "importScripts('./mime-type-worker.py');" + ) diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/interfaces-worker.sub.js b/testing/web-platform/tests/service-workers/service-worker/resources/interfaces-worker.sub.js index e5ed36fcebaf..2ae75ba9f947 100644 --- a/testing/web-platform/tests/service-workers/service-worker/resources/interfaces-worker.sub.js +++ b/testing/web-platform/tests/service-workers/service-worker/resources/interfaces-worker.sub.js @@ -15,7 +15,8 @@ test(function() { onactivate: EVENT_HANDLER, onfetch: EVENT_HANDLER, oninstall: EVENT_HANDLER, - onmessage: EVENT_HANDLER + onmessage: EVENT_HANDLER, + onmessageerror: EVENT_HANDLER }); }, 'ServiceWorkerGlobalScope'); diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/registration-tests.js b/testing/web-platform/tests/service-workers/service-worker/resources/registration-tests.js index 9b50a53744ce..cf606281912a 100644 --- a/testing/web-platform/tests/service-workers/service-worker/resources/registration-tests.js +++ b/testing/web-platform/tests/service-workers/service-worker/resources/registration-tests.js @@ -137,6 +137,70 @@ function registration_tests(register_method, check_error_types) { 'Registration of plain text script should fail.'); }, 'Registering script with bad MIME type'); + const validMimeTypes = [ + 'application/ecmascript', + 'application/javascript', + 'application/x-ecmascript', + 'application/x-javascript', + 'text/ecmascript', + 'text/javascript', + 'text/javascript1.0', + 'text/javascript1.1', + 'text/javascript1.2', + 'text/javascript1.3', + 'text/javascript1.4', + 'text/javascript1.5', + 'text/jscript', + 'text/livescript', + 'text/x-ecmascript', + 'text/x-javascript' + ]; + + for (const validMimeType of validMimeTypes) { + promise_test(() => { + var script = `resources/mime-type-worker.py?mime=${validMimeType}`; + var scope = 'resources/scope/good-mime-type-worker/'; + + return register_method(script, {scope}).then(registration => { + assert_true( + registration instanceof ServiceWorkerRegistration, + 'Successfully registered.'); + return registration.unregister(); + }); + }, `Registering script with good MIME type ${validMimeType}`); + + promise_test(() => { + var script = `resources/import-mime-type-worker.py?mime=${validMimeType}`; + var scope = 'resources/scope/good-mime-type-worker/'; + + return register_method(script, { scope }).then(registration => { + assert_true( + registration instanceof ServiceWorkerRegistration, + 'Successfully registered.'); + return registration.unregister(); + }); + }, `Registering script that imports script with good MIME type ${validMimeType}`); + } + + promise_test(function(t) { + var script = 'resources/import-mime-type-worker.py'; + var scope = 'resources/scope/no-mime-type-worker/'; + return promise_rejects(t, + check_error_types ? 'SecurityError' : null, + register_method(script, {scope: scope}), + 'Registration of no MIME type imported script should fail.'); + }, 'Registering script that imports script with no MIME type'); + + promise_test(function(t) { + var script = 'resources/import-mime-type-worker.py?mime=text/plain'; + var scope = 'resources/scope/bad-mime-type-worker/'; + return promise_rejects(t, + check_error_types ? 'SecurityError' : null, + register_method(script, {scope: scope}), + 'Registration of plain text imported script should fail.'); + }, 'Registering script that imports script with bad MIME type'); + + promise_test(function(t) { var script = 'resources/redirect.py?Redirect=' + encodeURIComponent('/resources/registration-worker.js'); diff --git a/testing/web-platform/tests/shadow-dom/slots-fallback-in-document.html b/testing/web-platform/tests/shadow-dom/slots-fallback-in-document.html new file mode 100644 index 000000000000..91acc5d5f2d7 --- /dev/null +++ b/testing/web-platform/tests/shadow-dom/slots-fallback-in-document.html @@ -0,0 +1,56 @@ + +Shadow DOM: Slots and fallback contents in Document tree + + + + + +
+
+ +
This is fallback content
+
+
+ + + +
+
+ +
+
+ + diff --git a/testing/web-platform/tests/staticrange/OWNERS b/testing/web-platform/tests/staticrange/OWNERS new file mode 100644 index 000000000000..5692d1b94a29 --- /dev/null +++ b/testing/web-platform/tests/staticrange/OWNERS @@ -0,0 +1,2 @@ +@garykac +@siusin diff --git a/testing/web-platform/tests/staticrange/idlharness.html b/testing/web-platform/tests/staticrange/idlharness.html new file mode 100644 index 000000000000..e35bca1e7e49 --- /dev/null +++ b/testing/web-platform/tests/staticrange/idlharness.html @@ -0,0 +1,31 @@ +Static Range IDL tests + + + + + + +
+interface Node {
+};
+
+ +
+interface StaticRange {
+    readonly attribute Node startContainer;
+    readonly attribute unsigned long startOffset;
+    readonly attribute Node endContainer;
+    readonly attribute unsigned long endOffset;
+    readonly attribute boolean collapsed;
+};
+
+ + diff --git a/testing/web-platform/tests/storage/resources/storagemanager-persist-worker.js b/testing/web-platform/tests/storage/resources/storagemanager-persist-worker.js new file mode 100644 index 000000000000..1152e4ec7349 --- /dev/null +++ b/testing/web-platform/tests/storage/resources/storagemanager-persist-worker.js @@ -0,0 +1,7 @@ +importScripts('/resources/testharness.js'); + +test(function() { + assert_false('persist' in navigator.storage); +}, 'navigator.storage.persist should not exist in workers'); + +done(); diff --git a/testing/web-platform/tests/storage/resources/storagemanager-persisted-worker.js b/testing/web-platform/tests/storage/resources/storagemanager-persisted-worker.js new file mode 100644 index 000000000000..979c8be3cd39 --- /dev/null +++ b/testing/web-platform/tests/storage/resources/storagemanager-persisted-worker.js @@ -0,0 +1,13 @@ +importScripts('/resources/testharness.js'); + +promise_test(function() { + var promise = navigator.storage.persisted(); + assert_true(promise instanceof Promise, + 'navigator.storage.persisted() returned a Promise.'); + return promise.then(function (result) { + assert_equals(typeof result, 'boolean', + result + ' should be a boolean'); + }); +}, 'navigator.storage.persisted returns a promise that resolves.'); + +done(); diff --git a/testing/web-platform/tests/storage/storagemanager-estimate.https.html b/testing/web-platform/tests/storage/storagemanager-estimate.https.html new file mode 100644 index 000000000000..08a699adfb00 --- /dev/null +++ b/testing/web-platform/tests/storage/storagemanager-estimate.https.html @@ -0,0 +1,68 @@ + + +StorageManager: estimate() + + + + diff --git a/testing/web-platform/tests/storage/storagemanager-persist-worker.https.html b/testing/web-platform/tests/storage/storagemanager-persist-worker.https.html new file mode 100644 index 000000000000..9c89a2f67125 --- /dev/null +++ b/testing/web-platform/tests/storage/storagemanager-persist-worker.https.html @@ -0,0 +1,10 @@ + + +StorageManager: persist() (worker) + + + + diff --git a/testing/web-platform/tests/storage/storagemanager-persist.https.html b/testing/web-platform/tests/storage/storagemanager-persist.https.html new file mode 100644 index 000000000000..61624fe272a6 --- /dev/null +++ b/testing/web-platform/tests/storage/storagemanager-persist.https.html @@ -0,0 +1,18 @@ + + +StorageManager: persist() + + + + diff --git a/testing/web-platform/tests/storage/storagemanager-persisted-worker.https.html b/testing/web-platform/tests/storage/storagemanager-persisted-worker.https.html new file mode 100644 index 000000000000..75004946164d --- /dev/null +++ b/testing/web-platform/tests/storage/storagemanager-persisted-worker.https.html @@ -0,0 +1,10 @@ + + +StorageManager: persisted() (worker) + + + + diff --git a/testing/web-platform/tests/storage/storagemanager-persisted.https.html b/testing/web-platform/tests/storage/storagemanager-persisted.https.html new file mode 100644 index 000000000000..1d88c11bd8aa --- /dev/null +++ b/testing/web-platform/tests/storage/storagemanager-persisted.https.html @@ -0,0 +1,18 @@ + + +StorageManager: persist() + + + + diff --git a/testing/web-platform/tests/streams/piping/close-propagation-forward.js b/testing/web-platform/tests/streams/piping/close-propagation-forward.js index 3f39c6afe934..35eac87a877b 100644 --- a/testing/web-platform/tests/streams/piping/close-propagation-forward.js +++ b/testing/web-platform/tests/streams/piping/close-propagation-forward.js @@ -424,4 +424,38 @@ promise_test(() => { }, 'Closing must be propagated forward: shutdown must not occur until the final write completes'); +promise_test(() => { + + const rs = recordingReadableStream(); + + let resolveWritePromise; + const ws = recordingWritableStream({ + write() { + return new Promise(resolve => { + resolveWritePromise = resolve; + }); + } + }); + + let pipeComplete = false; + const pipePromise = rs.pipeTo(ws, { preventClose: true }).then(() => { + pipeComplete = true; + }); + + rs.controller.enqueue('a'); + rs.controller.close(); + + // Flush async events and verify that no shutdown occurs. + return flushAsyncEvents().then(() => { + assert_array_equals(ws.events, ['write', 'a'], + 'the chunk must have been written, but close must not have happened yet'); + assert_equals(pipeComplete, false, 'the pipe must not be complete'); + + resolveWritePromise(); + + return pipePromise; + }); + +}, 'Closing must be propagated forward: shutdown must not occur until the final write completes; preventClose = true'); + done(); diff --git a/testing/web-platform/tests/streams/piping/flow-control.js b/testing/web-platform/tests/streams/piping/flow-control.js index 2bb04090820e..04c56ec40d0b 100644 --- a/testing/web-platform/tests/streams/piping/flow-control.js +++ b/testing/web-platform/tests/streams/piping/flow-control.js @@ -170,16 +170,44 @@ promise_test(() => { }, 'Piping from a ReadableStream to a WritableStream that desires more chunks before finishing with previous ones'); -promise_test(() => { +class StepTracker { + constructor() { + this.waiters = []; + this.wakers = []; + } + // Returns promise which resolves when step `n` is reached. Also schedules step n + 1 to happen shortly after the + // promise is resolved. + waitThenAdvance(n) { + if (this.waiters[n] === undefined) { + this.waiters[n] = new Promise(resolve => { + this.wakers[n] = resolve; + }); + this.waiters[n] + .then(() => flushAsyncEvents()) + .then(() => { + if (this.wakers[n + 1] !== undefined) { + this.wakers[n + 1](); + } + }); + } + if (n == 0) { + this.wakers[0](); + } + return this.waiters[n]; + } +} + +promise_test(() => { + const steps = new StepTracker(); const desiredSizes = []; const rs = recordingReadableStream({ start(controller) { - delay(100).then(() => enqueue('a')); - delay(200).then(() => enqueue('b')); - delay(300).then(() => enqueue('c')); - delay(400).then(() => enqueue('d')); - delay(500).then(() => controller.close()); + steps.waitThenAdvance(1).then(() => enqueue('a')); + steps.waitThenAdvance(3).then(() => enqueue('b')); + steps.waitThenAdvance(5).then(() => enqueue('c')); + steps.waitThenAdvance(7).then(() => enqueue('d')); + steps.waitThenAdvance(11).then(() => controller.close()); function enqueue(chunk) { controller.enqueue(chunk); @@ -190,80 +218,86 @@ promise_test(() => { const chunksFinishedWriting = []; const writableStartPromise = Promise.resolve(); + let writeCalled = false; const ws = recordingWritableStream({ start() { return writableStartPromise; }, write(chunk) { - return delay(350).then(() => { + const waitForStep = writeCalled ? 12 : 9; + writeCalled = true; + return steps.waitThenAdvance(waitForStep).then(() => { chunksFinishedWriting.push(chunk); }); } }); return writableStartPromise.then(() => { + const pipePromise = rs.pipeTo(ws); + steps.waitThenAdvance(0); + return Promise.all([ - rs.pipeTo(ws).then(() => { - assert_array_equals(desiredSizes, [1, 0, -1, -2], 'backpressure must have been exerted at the source'); - assert_array_equals(chunksFinishedWriting, ['a', 'b', 'c', 'd'], 'all chunks started writing'); - - assert_array_equals(rs.eventsWithoutPulls, [], 'nothing unexpected should happen to the ReadableStream'); - assert_array_equals(ws.events, ['write', 'a', 'write', 'b', 'write', 'c', 'write', 'd', 'close'], - 'all chunks were written (and the WritableStream closed)'); - }), - - delay(125).then(() => { - assert_array_equals(chunksFinishedWriting, [], 'at t = 125 ms, zero chunks must have finished writing'); - assert_array_equals(ws.events, ['write', 'a'], 'at t = 125 ms, one chunk must have been written'); + steps.waitThenAdvance(2).then(() => { + assert_array_equals(chunksFinishedWriting, [], 'at step 2, zero chunks must have finished writing'); + assert_array_equals(ws.events, ['write', 'a'], 'at step 2, one chunk must have been written'); // When 'a' (the very first chunk) was enqueued, it was immediately used to fulfill the outstanding read request // promise, leaving the queue empty. assert_array_equals(desiredSizes, [1], - 'at t = 125 ms, the desiredSize at the last enqueue (100 ms) must have been 1'); - assert_equals(rs.controller.desiredSize, 1, 'at t = 125 ms, the current desiredSize must be 1'); + 'at step 2, the desiredSize at the last enqueue (step 1) must have been 1'); + assert_equals(rs.controller.desiredSize, 1, 'at step 2, the current desiredSize must be 1'); }), - delay(225).then(() => { - assert_array_equals(chunksFinishedWriting, [], 'at t = 225 ms, zero chunks must have finished writing'); - assert_array_equals(ws.events, ['write', 'a'], 'at t = 225 ms, one chunk must have been written'); + steps.waitThenAdvance(4).then(() => { + assert_array_equals(chunksFinishedWriting, [], 'at step 4, zero chunks must have finished writing'); + assert_array_equals(ws.events, ['write', 'a'], 'at step 4, one chunk must have been written'); - // When 'b' was enqueued at 200 ms, the queue was also empty, since immediately after enqueuing 'a' at - // t = 100 ms, it was dequeued in order to fulfill the read() call that was made at time t = 0. Thus the queue + // When 'b' was enqueued at step 3, the queue was also empty, since immediately after enqueuing 'a' at + // step 1, it was dequeued in order to fulfill the read() call that was made at step 0. Thus the queue // had size 1 (thus desiredSize of 0). assert_array_equals(desiredSizes, [1, 0], - 'at t = 225 ms, the desiredSize at the last enqueue (200 ms) must have been 0'); - assert_equals(rs.controller.desiredSize, 0, 'at t = 225 ms, the current desiredSize must be 0'); + 'at step 4, the desiredSize at the last enqueue (step 3) must have been 0'); + assert_equals(rs.controller.desiredSize, 0, 'at step 4, the current desiredSize must be 0'); }), - delay(325).then(() => { - assert_array_equals(chunksFinishedWriting, [], 'at t = 325 ms, zero chunks must have finished writing'); - assert_array_equals(ws.events, ['write', 'a'], 'at t = 325 ms, one chunk must have been written'); + steps.waitThenAdvance(6).then(() => { + assert_array_equals(chunksFinishedWriting, [], 'at step 6, zero chunks must have finished writing'); + assert_array_equals(ws.events, ['write', 'a'], 'at step 6, one chunk must have been written'); - // When 'c' was enqueued at 300 ms, the queue was not empty; it had 'b' in it, since 'b' will not be read until - // the first write completes at 450 ms. Thus, the queue size is 2 after enqueuing 'c', giving a desiredSize of + // When 'c' was enqueued at step 5, the queue was not empty; it had 'b' in it, since 'b' will not be read until + // the first write completes at step 9. Thus, the queue size is 2 after enqueuing 'c', giving a desiredSize of // -1. assert_array_equals(desiredSizes, [1, 0, -1], - 'at t = 325 ms, the desiredSize at the last enqueue (300 ms) must have been -1'); - assert_equals(rs.controller.desiredSize, -1, 'at t = 325 ms, the current desiredSize must be -1'); + 'at step 6, the desiredSize at the last enqueue (step 5) must have been -1'); + assert_equals(rs.controller.desiredSize, -1, 'at step 6, the current desiredSize must be -1'); }), - delay(425).then(() => { - assert_array_equals(chunksFinishedWriting, [], 'at t = 425 ms, zero chunks must have finished writing'); - assert_array_equals(ws.events, ['write', 'a'], 'at t = 425 ms, one chunk must have been written'); + steps.waitThenAdvance(8).then(() => { + assert_array_equals(chunksFinishedWriting, [], 'at step 8, zero chunks must have finished writing'); + assert_array_equals(ws.events, ['write', 'a'], 'at step 8, one chunk must have been written'); - // When 'd' was enqueued at 400 ms, the situation is the same as before, leading to a queue containing 'b', 'c', - // and 'd'. (Remember the first write will only finish at 100 ms + 350 ms = 450 ms.) + // When 'd' was enqueued at step 7, the situation is the same as before, leading to a queue containing 'b', 'c', + // and 'd'. assert_array_equals(desiredSizes, [1, 0, -1, -2], - 'at t = 425 ms, the desiredSize at the last enqueue (400 ms) must have been -2'); - assert_equals(rs.controller.desiredSize, -2, 'at t = 425 ms, the current desiredSize must be -2'); + 'at step 8, the desiredSize at the last enqueue (step 7) must have been -2'); + assert_equals(rs.controller.desiredSize, -2, 'at step 8, the current desiredSize must be -2'); }), - delay(475).then(() => { - assert_array_equals(chunksFinishedWriting, ['a'], 'at t = 475 ms, one chunk must have finished writing'); + steps.waitThenAdvance(10).then(() => { + assert_array_equals(chunksFinishedWriting, ['a'], 'at step 10, one chunk must have finished writing'); assert_array_equals(ws.events, ['write', 'a', 'write', 'b'], - 'at t = 475 ms, two chunks must have been written'); + 'at step 10, two chunks must have been written'); - assert_equals(rs.controller.desiredSize, -1, 'at t = 475 ms, the current desiredSize must be -1'); + assert_equals(rs.controller.desiredSize, -1, 'at step 10, the current desiredSize must be -1'); + }), + + pipePromise.then(() => { + assert_array_equals(desiredSizes, [1, 0, -1, -2], 'backpressure must have been exerted at the source'); + assert_array_equals(chunksFinishedWriting, ['a', 'b', 'c', 'd'], 'all chunks finished writing'); + + assert_array_equals(rs.eventsWithoutPulls, [], 'nothing unexpected should happen to the ReadableStream'); + assert_array_equals(ws.events, ['write', 'a', 'write', 'b', 'write', 'c', 'write', 'd', 'close'], + 'all chunks were written (and the WritableStream closed)'); }) ]); }); diff --git a/testing/web-platform/tests/streams/piping/multiple-propagation.js b/testing/web-platform/tests/streams/piping/multiple-propagation.js index 79ec39956625..447433f59806 100644 --- a/testing/web-platform/tests/streams/piping/multiple-propagation.js +++ b/testing/web-platform/tests/streams/piping/multiple-propagation.js @@ -71,19 +71,48 @@ promise_test(t => { }); const ws = recordingWritableStream(); const writer = ws.getWriter(); - writer.close(); + const closePromise = writer.close(); writer.releaseLock(); return promise_rejects(t, error1, rs.pipeTo(ws), 'pipeTo must reject with the readable stream\'s error').then(() => { assert_array_equals(rs.events, []); - assert_array_equals(ws.events, ['close']); + assert_array_equals(ws.events, ['abort', error1]); return Promise.all([ promise_rejects(t, error1, rs.getReader().closed, 'the readable stream must be errored with error1'), - ws.getWriter().closed + promise_rejects(t, new TypeError(), ws.getWriter().closed, + 'closed must reject with a TypeError indicating the writable stream was aborted'), + promise_rejects(t, new TypeError(), closePromise, + 'close() must reject with a TypeError indicating the writable stream was aborted'), ]); }); +}, 'Piping from an errored readable stream to a closing writable stream'); + +promise_test(t => { + const rs = recordingReadableStream({ + start(c) { + c.error(error1); + } + }); + const ws = recordingWritableStream(); + const writer = ws.getWriter(); + const closePromise = writer.close(); + writer.releaseLock(); + + return flushAsyncEvents().then(() => { + return promise_rejects(t, error1, rs.pipeTo(ws), 'pipeTo must reject with the readable stream\'s error').then(() => { + assert_array_equals(rs.events, []); + assert_array_equals(ws.events, ['close']); + + return Promise.all([ + promise_rejects(t, error1, rs.getReader().closed, 'the readable stream must be errored with error1'), + ws.getWriter().closed, + closePromise + ]); + }); + }); + }, 'Piping from an errored readable stream to a closed writable stream'); promise_test(t => { diff --git a/testing/web-platform/tests/streams/piping/pipe-through.js b/testing/web-platform/tests/streams/piping/pipe-through.js index 57277cf6d728..bc4ac909c193 100644 --- a/testing/web-platform/tests/streams/piping/pipe-through.js +++ b/testing/web-platform/tests/streams/piping/pipe-through.js @@ -104,4 +104,44 @@ test(() => { }, 'pipeThrough can handle calling a pipeTo that returns a non-promise thenable object'); +promise_test(() => { + const dummy = { + pipeTo() { + return Promise.reject(new Error('this rejection should not be reported as unhandled')); + } + }; + + ReadableStream.prototype.pipeThrough.call(dummy, { }); + + // The test harness should complain about unhandled rejections by then. + return flushAsyncEvents(); + +}, 'pipeThrough should mark a real promise from a fake readable as handled'); + +test(() => { + let thenCalled = false + let catchCalled = false; + const dummy = { + pipeTo() { + const fakePromise = Object.create(Promise.prototype); + fakePromise.then = () => { + thenCalled = true; + }; + fakePromise.catch = () => { + catchCalled = true; + }; + assert_true(fakePromise instanceof Promise, 'fakePromise fools instanceof'); + return fakePromise; + } + }; + + // An incorrect implementation which uses an internal method to mark the promise as handled will throw or crash here. + ReadableStream.prototype.pipeThrough.call(dummy, { }); + + // An incorrect implementation that tries to mark the promise as handled by calling .then() or .catch() on the object + // will fail these tests. + assert_false(thenCalled, 'then should not be called'); + assert_false(catchCalled, 'catch should not be called'); +}, 'pipeThrough should not be fooled by an object whose instanceof Promise returns true'); + done(); diff --git a/testing/web-platform/tests/streams/readable-byte-streams/general.js b/testing/web-platform/tests/streams/readable-byte-streams/general.js index 374c52ca2e8e..23989113509a 100644 --- a/testing/web-platform/tests/streams/readable-byte-streams/general.js +++ b/testing/web-platform/tests/streams/readable-byte-streams/general.js @@ -1897,6 +1897,28 @@ promise_test(t => { }, 'ReadableStream with byte source: Throwing in pull in response to read(view) must be ignored if the stream is ' + 'errored in it'); +promise_test(() => { + // Tests https://github.com/whatwg/streams/issues/686 + + let controller; + const rs = new ReadableStream({ + autoAllocateChunkSize: 128, + start(c) { + controller = c; + }, + type: "bytes" + }); + + const readPromise = rs.getReader().read(); + + const br = controller.byobRequest; + controller.close(); + + br.respond(0); + + return readPromise; +}, 'ReadableStream with byte source: default reader + autoAllocateChunkSize + byobRequest interaction'); + test(() => { const ReadableStreamBYOBReader = new ReadableStream({ type: 'bytes' }).getReader({ mode: 'byob' }).constructor; const stream = new ReadableStream({ type: 'bytes' }); diff --git a/testing/web-platform/tests/streams/readable-streams/floating-point-total-queue-size.js b/testing/web-platform/tests/streams/readable-streams/floating-point-total-queue-size.js index 3bb3b6a90d05..f7c76248b0b2 100644 --- a/testing/web-platform/tests/streams/readable-streams/floating-point-total-queue-size.js +++ b/testing/web-platform/tests/streams/readable-streams/floating-point-total-queue-size.js @@ -117,3 +117,5 @@ function setupTestStream() { return { reader: rs.getReader(), controller }; } + +done(); diff --git a/testing/web-platform/tests/streams/resources/recording-streams.js b/testing/web-platform/tests/streams/resources/recording-streams.js index 9837318dbcc0..3f949313f970 100644 --- a/testing/web-platform/tests/streams/resources/recording-streams.js +++ b/testing/web-platform/tests/streams/resources/recording-streams.js @@ -52,18 +52,16 @@ self.recordingWritableStream = (extras = {}, strategy) => { return undefined; }, - write(chunk) { + write(chunk, controller) { stream.events.push('write', chunk); if (extras.write) { - return extras.write(chunk); + return extras.write(chunk, controller); } return undefined; }, - close(...args) { - assert_array_equals(args, [controllerToCopyOver], 'close must always be called with the controller'); - + close() { stream.events.push('close'); if (extras.close) { diff --git a/testing/web-platform/tests/streams/writable-streams/aborting.js b/testing/web-platform/tests/streams/writable-streams/aborting.js index 9f589ec152ff..a04befd69d2c 100644 --- a/testing/web-platform/tests/streams/writable-streams/aborting.js +++ b/testing/web-platform/tests/streams/writable-streams/aborting.js @@ -14,9 +14,7 @@ error2.name = 'error2'; promise_test(t => { const ws = new WritableStream({ - write() { - return new Promise(() => { }); // forever-pending, so normally .ready would not fulfill. - } + write: t.unreached_func('write() should not be called') }); const writer = ws.getWriter(); @@ -66,11 +64,12 @@ promise_test(t => { .then(() => { const writer = ws.getWriter(); - writer.abort(); + const abortPromise = writer.abort(); return Promise.all([ promise_rejects(t, new TypeError(), writer.write(1), 'write(1) must reject with a TypeError'), - promise_rejects(t, new TypeError(), writer.write(2), 'write(2) must reject with a TypeError') + promise_rejects(t, new TypeError(), writer.write(2), 'write(2) must reject with a TypeError'), + abortPromise ]); }) .then(() => { @@ -182,7 +181,7 @@ promise_test(t => { const ws = new WritableStream(); const writer = ws.getWriter(); - writer.abort(error1); + const abortPromise = writer.abort(error1); const events = []; writer.ready.catch(() => { @@ -193,6 +192,7 @@ promise_test(t => { }); return Promise.all([ + abortPromise, promise_rejects(t, new TypeError(), writer.write(), 'writing should reject with a TypeError'), promise_rejects(t, new TypeError(), writer.close(), 'closing should reject with a TypeError'), promise_rejects(t, new TypeError(), writer.abort(), 'aborting should reject with a TypeError'), @@ -231,7 +231,7 @@ promise_test(t => { }); }, 'Closing but then immediately aborting a WritableStream causes the stream to error'); -promise_test(t => { +promise_test(() => { let resolveClose; const ws = new WritableStream({ close() { @@ -311,11 +311,11 @@ promise_test(t => { return writer.ready.then(() => { const writePromise = writer.write('a'); writer.abort(error1); - let closedResolved = false; + let closedRejected = false; return Promise.all([ - writePromise.then(() => assert_false(closedResolved, '.closed should not resolve before write()')), + writePromise.then(() => assert_false(closedRejected, '.closed should not resolve before write()')), promise_rejects(t, new TypeError(), writer.closed, '.closed should reject').then(() => { - closedResolved = true; + closedRejected = true; }) ]); }); @@ -331,17 +331,18 @@ promise_test(t => { return writer.ready.then(() => { const writePromise = writer.write('a'); const abortPromise = writer.abort(error2); - let closedResolved = false; + let closedRejected = false; return Promise.all([ promise_rejects(t, error1, writePromise, 'write() should reject') - .then(() => assert_false(closedResolved, '.closed should not resolve before write()')), - promise_rejects(t, error1, writer.closed, '.closed should reject') + .then(() => assert_false(closedRejected, '.closed should not resolve before write()')), + promise_rejects(t, new TypeError(), writer.closed, '.closed should reject') .then(() => { - closedResolved = true; + closedRejected = true; }), - promise_rejects(t, error1, abortPromise, 'abort() should reject')]); + abortPromise + ]); }); -}, '.closed should not resolve before rejected write(); write() error should overwrite abort() error'); +}, '.closed should not resolve before rejected write(); write() error should not overwrite abort() error'); promise_test(t => { const ws = new WritableStream({ @@ -375,11 +376,11 @@ promise_test(t => { return Promise.all([ promise_rejects(t, error1, writer.write('1'), 'in-flight write should be rejected') .then(() => settlementOrder.push(1)), - promise_rejects(t, error1, writer.write('2'), 'first queued write should be rejected') + promise_rejects(t, new TypeError(), writer.write('2'), 'first queued write should be rejected') .then(() => settlementOrder.push(2)), - promise_rejects(t, error1, writer.write('3'), 'second queued write should be rejected') + promise_rejects(t, new TypeError(), writer.write('3'), 'second queued write should be rejected') .then(() => settlementOrder.push(3)), - promise_rejects(t, error1, writer.abort(error1), 'abort should be rejected') + writer.abort(error2) ]).then(() => assert_array_equals([1, 2, 3], settlementOrder, 'writes should be satisfied in order')); }); }, 'writes should be satisfied in order after rejected write when aborting'); @@ -394,11 +395,12 @@ promise_test(t => { return writer.ready.then(() => { return Promise.all([ promise_rejects(t, error1, writer.write('a'), 'writer.write() should reject with error from underlying write()'), - promise_rejects(t, error1, writer.close(), 'writer.close() should reject with error from underlying write()'), - promise_rejects(t, error1, writer.abort(), 'writer.abort() should reject with error from underlying write()') + promise_rejects(t, new TypeError(), writer.close(), + 'writer.close() should reject with error from underlying write()'), + writer.abort() ]); }); -}, 'close() should use error from underlying write() on abort'); +}, 'close() should reject with TypeError when abort() is first error'); promise_test(() => { let resolveWrite; @@ -583,7 +585,7 @@ promise_test(t => { }); abortPromise = writer.abort(error1); - abortPromise.catch(() => { + abortPromise.then(() => { events.push('abortPromise'); }); @@ -602,21 +604,20 @@ promise_test(t => { return Promise.all([ promise_rejects(t, error2, writePromise, 'writePromise must reject with the error returned from the sink\'s write method'), - promise_rejects(t, error2, abortPromise, - 'abortPromise must reject with the error returned from the sink\'s write method'), - promise_rejects(t, error2, writer.closed, - 'writer.closed must reject with the error returned from the sink\'s write method'), + abortPromise, + promise_rejects(t, new TypeError(), writer.closed, + 'writer.closed must reject with an error indicating abort'), flushAsyncEvents() ]); }).then(() => { - assert_array_equals(events, ['writePromise', 'closed', 'abortPromise'], - 'writePromise, abortPromise and writer.closed must reject'); + assert_array_equals(events, ['writePromise', 'abortPromise', 'closed'], + 'writePromise, abortPromise and writer.closed must settle'); const writePromise3 = writer.write('a'); return Promise.all([ - promise_rejects(t, error2, writePromise3, - 'writePromise3 must reject with the error returned from the sink\'s write method'), + promise_rejects(t, new TypeError(), writePromise3, + 'writePromise3 must reject with an error indicating abort'), promise_rejects(t, new TypeError(), writer.ready, 'writer.ready must be still rejected with the error indicating abort') ]); @@ -663,7 +664,7 @@ promise_test(t => { }); abortPromise = writer.abort(error1); - abortPromise.catch(() => { + abortPromise.then(() => { events.push('abortPromise'); }); @@ -677,13 +678,14 @@ promise_test(t => { }).then(() => { assert_array_equals(events, [], 'writePromise, abortPromise and writer.closed must not be fulfilled/rejected yet'); + // This error is too late to change anything. abort() has already changed the stream state to 'erroring'. controller.error(error2); const writePromise3 = writer.write('a'); return Promise.all([ - promise_rejects(t, error2, writePromise3, - 'writePromise3 must reject with the error passed to the controller\'s error method'), + promise_rejects(t, new TypeError(), writePromise3, + 'writePromise3 must reject with an error indicating abort'), promise_rejects(t, new TypeError(), writer.ready, 'writer.ready must be still rejected with the error indicating abort'), flushAsyncEvents() @@ -698,22 +700,21 @@ promise_test(t => { return Promise.all([ writePromise, - promise_rejects(t, error2, abortPromise, - 'abortPromise must reject with the error passed to the controller\'s error method'), - promise_rejects(t, error2, writer.closed, - 'writer.closed must reject with the error passed to the controller\'s error method'), + abortPromise, + promise_rejects(t, new TypeError(), writer.closed, + 'writer.closed must reject with an error indicating abort'), flushAsyncEvents() ]); }).then(() => { assert_array_equals(events, ['writePromise', 'abortPromise', 'closed'], - 'writePromise, abortPromise and writer.closed must reject'); + 'writePromise, abortPromise and writer.closed must settle'); const writePromise4 = writer.write('a'); return Promise.all([ writePromise, - promise_rejects(t, error2, writePromise4, - 'writePromise4 must reject with the error passed to the controller\'s error method'), + promise_rejects(t, new TypeError(), writePromise4, + 'writePromise4 must reject with an error indicating abort'), promise_rejects(t, new TypeError(), writer.ready, 'writer.ready must be still rejected with the error indicating abort') ]); @@ -750,7 +751,7 @@ promise_test(t => { const writer = ws.getWriter(); - writer.closed.catch(() => { + writer.closed.then(() => { events.push('closed'); }); @@ -762,7 +763,7 @@ promise_test(t => { }); abortPromise = writer.abort(error1); - abortPromise.catch(() => { + abortPromise.then(() => { events.push('abortPromise'); }); @@ -794,15 +795,13 @@ promise_test(t => { return Promise.all([ closePromise, - promise_rejects(t, error2, abortPromise, - 'abortPromise must reject with the error passed to the controller\'s error method'), - promise_rejects(t, error2, writer.closed, - 'writer.closed must reject with the error passed to the controller\'s error method'), + abortPromise, + writer.closed, flushAsyncEvents() ]); }).then(() => { assert_array_equals(events, ['closePromise', 'abortPromise', 'closed'], - 'closedPromise, abortPromise and writer.closed must reject'); + 'closedPromise, abortPromise and writer.closed must fulfill'); return Promise.all([ promise_rejects(t, new TypeError(), writer.close(), @@ -827,7 +826,7 @@ promise_test(t => { promise_test(t => { let resolveWrite; let controller; - const ws = new WritableStream({ + const ws = recordingWritableStream({ write(chunk, c) { controller = c; return new Promise(resolve => { @@ -876,27 +875,28 @@ promise_test(t => { const writePromise3 = writer.write('a'); return Promise.all([ - promise_rejects(t, error2, abortPromise, - 'abortPromise must reject with the error passed to the controller\'s error method'), promise_rejects(t, error2, writePromise3, 'writePromise3 must reject with the error passed to the controller\'s error method'), flushAsyncEvents() ]); }).then(() => { assert_array_equals( - events, ['abortPromise'], + events, [], 'writePromise and writer.closed must not be fulfilled/rejected yet even after writer.abort()'); resolveWrite(); return Promise.all([ + promise_rejects(t, error2, abortPromise, + 'abort() must reject with the error passed to the controller\'s error method'), promise_rejects(t, error2, writer.closed, 'writer.closed must reject with the error passed to the controller\'s error method'), flushAsyncEvents() ]); }).then(() => { - assert_array_equals(events, ['abortPromise', 'writePromise', 'closed'], + assert_array_equals(events, ['writePromise', 'abortPromise', 'closed'], 'writePromise, abortPromise and writer.closed must fulfill/reject'); + assert_array_equals(ws.events, ['write', 'a'], 'sink abort() should not be called'); const writePromise4 = writer.write('a'); @@ -940,7 +940,7 @@ promise_test(t => { const writer = ws.getWriter(); - writer.closed.catch(() => { + writer.closed.then(() => { events.push('closed'); }); @@ -958,7 +958,7 @@ promise_test(t => { assert_array_equals(events, [], 'closePromise must not be fulfilled/rejected yet'); abortPromise = writer.abort(error1); - abortPromise.catch(() => { + abortPromise.then(() => { events.push('abortPromise'); }); @@ -969,7 +969,7 @@ promise_test(t => { ]); }).then(() => { assert_array_equals( - events, ['abortPromise'], + events, [], 'closePromise and writer.closed must not be fulfilled/rejected yet even after writer.abort()'); resolveClose(); @@ -978,12 +978,11 @@ promise_test(t => { closePromise, promise_rejects(t, error2, writer.ready, 'writer.ready must be still rejected with the error passed to the controller\'s error method'), - promise_rejects(t, error2, writer.closed, - 'writer.closed must reject with the error passed to the controller\'s error method'), + writer.closed, flushAsyncEvents() ]); }).then(() => { - assert_array_equals(events, ['abortPromise', 'closePromise', 'closed'], + assert_array_equals(events, ['closePromise', 'abortPromise', 'closed'], 'abortPromise, closePromise and writer.closed must fulfill/reject'); }).then(() => { writer.releaseLock(); @@ -1020,6 +1019,7 @@ promise_test(t => { }); }, 'releaseLock() while aborting should reject the original closed promise'); +// TODO(ricea): Consider removing this test if it is no longer useful. promise_test(t => { let resolveWrite; let resolveAbort; @@ -1048,16 +1048,15 @@ promise_test(t => { resolveWrite(); return abortStarted.then(() => { writer.releaseLock(); - assert_not_equals(writer.closed, closed, 'closed promise should have changed'); + assert_equals(writer.closed, closed, 'closed promise should not have changed'); resolveAbort(); return Promise.all([ writePromise, abortPromise, - promise_rejects(t, new TypeError(), closed, 'original closed should reject'), - promise_rejects(t, new TypeError(), writer.closed, 'new closed should reject')]); + promise_rejects(t, new TypeError(), closed, 'closed should reject')]); }); }); -}, 'releaseLock() during delayed async abort() should create a new rejected closed promise'); +}, 'releaseLock() during delayed async abort() should reject the writer.closed promise'); promise_test(() => { let resolveStart; @@ -1078,7 +1077,7 @@ promise_test(() => { }); }, 'sink abort() should not be called until sink start() is done'); -promise_test(t => { +promise_test(() => { let resolveStart; let controller; const ws = recordingWritableStream({ @@ -1092,21 +1091,20 @@ promise_test(t => { const abortPromise = ws.abort('done'); controller.error(error1); resolveStart(); - return promise_rejects(t, error1, abortPromise, 'abort() should reject if start() errors the controller') - .then(() => - assert_array_equals(ws.events, [], 'abort() should be not be called if start() errors the controller')); -}, 'abort() promise should reject if start() errors the controller'); + return abortPromise.then(() => + assert_array_equals(ws.events, ['abort', 'done'], + 'abort() should still be called if start() errors the controller')); +}, 'if start attempts to error the controller after abort() has been called, then it should lose'); -promise_test(t => { +promise_test(() => { const ws = recordingWritableStream({ start() { return Promise.reject(error1); } }); - return promise_rejects(t, error1, ws.abort('done'), 'abort() should reject if start() rejects') - .then(() => - assert_array_equals(ws.events, [], 'abort() should be not be called if start() rejects')); -}, 'stream abort() promise should reject if sink start() rejects'); + return ws.abort('done').then(() => + assert_array_equals(ws.events, ['abort', 'done'], 'abort() should still be called if start() rejects')); +}, 'stream abort() promise should still resolve if sink start() rejects'); promise_test(t => { const ws = new WritableStream(); @@ -1120,21 +1118,25 @@ promise_test(t => { }, 'writer abort() during sink start() should replace the writer.ready promise synchronously'); promise_test(t => { - const promises = []; - const resolved = []; + const events = []; const ws = recordingWritableStream(); const writer = ws.getWriter(); - promises.push(promise_rejects(t, new TypeError(), writer.write(1), 'first write() should reject') - .then(() => resolved.push('write1'))); - promises.push(writer.abort('a') - .then(() => resolved.push('abort'))); - promises.push(promise_rejects(t, new TypeError(), writer.write(2), 'second write() should reject') - .then(() => resolved.push('write2'))); - promises.push(promise_rejects(t, new TypeError(), writer.close(), 'close() should reject') - .then(() => resolved.push('close'))); - return Promise.all(promises) + const writePromise1 = writer.write(1); + const abortPromise = writer.abort('a'); + const writePromise2 = writer.write(2); + const closePromise = writer.close(); + writePromise1.catch(() => events.push('write1')); + abortPromise.then(() => events.push('abort')); + writePromise2.catch(() => events.push('write2')); + closePromise.catch(() => events.push('close')); + return Promise.all([ + promise_rejects(t, new TypeError(), writePromise1, 'first write() should reject'), + abortPromise, + promise_rejects(t, new TypeError(), writePromise2, 'second write() should reject'), + promise_rejects(t, new TypeError(), closePromise, 'close() should reject') + ]) .then(() => { - assert_array_equals(resolved, ['write2', 'close', 'write1', 'abort'], + assert_array_equals(events, ['write2', 'write1', 'abort', 'close'], 'promises should resolve in the standard order'); assert_array_equals(ws.events, ['abort', 'a'], 'underlying sink write() should not be called'); }); @@ -1159,17 +1161,19 @@ promise_test(t => { writeReject(error2); return Promise.all([ promise_rejects(t, error2, writePromise, 'write() should reject with error2'), - promise_rejects(t, error1, abortPromise, 'abort() should reject with error1') + abortPromise ]); }); -}, 'abort() should be rejected with the error passed to controller.error() during pending write()'); +}, 'abort() should succeed despite rejection from write'); promise_test(t => { let closeReject; let controller; const ws = new WritableStream({ - close(c) { + start(c) { controller = c; + }, + close() { return new Promise((resolve, reject) => { closeReject = reject; }); @@ -1183,9 +1187,115 @@ promise_test(t => { closeReject(error2); return Promise.all([ promise_rejects(t, error2, closePromise, 'close() should reject with error2'), - promise_rejects(t, error1, abortPromise, 'abort() should reject with error1') + promise_rejects(t, error2, abortPromise, 'abort() should reject with error2') ]); }); -}, 'abort() should be rejected with the error passed to controller.error() during pending close()'); +}, 'abort() should be rejected with the rejection returned from close()'); + +promise_test(t => { + let rejectWrite; + const ws = recordingWritableStream({ + write() { + return new Promise((resolve, reject) => { + rejectWrite = reject; + }); + } + }); + const writer = ws.getWriter(); + return writer.ready.then(() => { + const writePromise = writer.write('1'); + const abortPromise = writer.abort(error2); + rejectWrite(error1); + return Promise.all([ + promise_rejects(t, error1, writePromise, 'write should reject'), + abortPromise, + promise_rejects(t, new TypeError(), writer.closed, 'closed should reject with TypeError') + ]); + }).then(() => { + assert_array_equals(ws.events, ['write', '1', 'abort', error2], 'abort sink method should be called'); + }); +}, 'a rejecting sink.write() should not prevent sink.abort() from being called'); + +promise_test(() => { + const ws = recordingWritableStream({ + start() { + return Promise.reject(error1); + } + }); + return ws.abort(error2) + .then(() => { + assert_array_equals(ws.events, ['abort', error2]); + }); +}, 'when start errors after stream abort(), underlying sink abort() should be called anyway'); + +promise_test(t => { + const ws = new WritableStream(); + const abortPromise1 = ws.abort(); + const abortPromise2 = ws.abort(); + return Promise.all([ + abortPromise1, + promise_rejects(t, new TypeError(), abortPromise2, 'second abort() should reject') + ]); +}, 'when calling abort() twice on the same stream, the second call should reject'); + +promise_test(t => { + let controller; + let resolveWrite; + const ws = recordingWritableStream({ + start(c) { + controller = c; + }, + write() { + return new Promise(resolve => { + resolveWrite = resolve; + }); + } + }); + const writer = ws.getWriter(); + return writer.ready.then(() => { + const writePromise = writer.write('chunk'); + controller.error(error1); + const abortPromise = writer.abort(error2); + resolveWrite(); + return Promise.all([ + writePromise, + promise_rejects(t, error1, abortPromise, 'abort() should reject') + ]).then(() => { + assert_array_equals(ws.events, ['write', 'chunk'], 'sink abort() should not be called'); + }); + }); +}, 'sink abort() should not be called if stream was erroring due to controller.error() before abort() was called'); + +promise_test(t => { + let resolveWrite; + let size = 1; + const ws = recordingWritableStream({ + write() { + return new Promise(resolve => { + resolveWrite = resolve; + }); + } + }, { + size() { + return size; + }, + highWaterMark: 1 + }); + const writer = ws.getWriter(); + return writer.ready.then(() => { + const writePromise1 = writer.write('chunk1'); + size = NaN; + const writePromise2 = writer.write('chunk2'); + const abortPromise = writer.abort(error2); + resolveWrite(); + return Promise.all([ + writePromise1, + promise_rejects(t, new RangeError(), writePromise2, 'second write() should reject'), + promise_rejects(t, new RangeError(), abortPromise, 'abort() should reject') + ]).then(() => { + assert_array_equals(ws.events, ['write', 'chunk1'], 'sink abort() should not be called'); + }); + }); +}, 'sink abort() should not be called if stream was erroring due to bad strategy before abort() was called'); done(); diff --git a/testing/web-platform/tests/streams/writable-streams/close.js b/testing/web-platform/tests/streams/writable-streams/close.js index 536e887135a2..bf9472ef3bbd 100644 --- a/testing/web-platform/tests/streams/writable-streams/close.js +++ b/testing/web-platform/tests/streams/writable-streams/close.js @@ -26,39 +26,51 @@ promise_test(() => { }, 'fulfillment value of ws.close() call must be undefined even if the underlying sink returns a non-undefined ' + 'value'); -promise_test(t => { - const passedError = new Error('error me'); +promise_test(() => { let controller; + let resolveClose; const ws = new WritableStream({ - close(c) { + start(c) { controller = c; - return delay(50); + }, + close() { + return new Promise(resolve => { + resolveClose = resolve; + }); } }); const writer = ws.getWriter(); - return Promise.all([ - writer.close(), - delay(10).then(() => controller.error(passedError)), - promise_rejects(t, passedError, writer.closed, - 'closed promise should be rejected with the passed error'), - delay(70).then(() => promise_rejects(t, passedError, writer.closed, 'closed should stay rejected')) - ]); -}, 'when sink calls error asynchronously while closing, the stream should become errored'); + const closePromise = writer.close(); + return flushAsyncEvents().then(() => { + controller.error(error1); + return flushAsyncEvents(); + }).then(() => { + resolveClose(); + return Promise.all([ + closePromise, + writer.closed, + flushAsyncEvents().then(() => writer.closed)]); + }); +}, 'when sink calls error asynchronously while sink close is in-flight, the stream should not become errored'); -promise_test(t => { +promise_test(() => { + let controller; const passedError = new Error('error me'); const ws = new WritableStream({ - close(controller) { + start(c) { + controller = c; + }, + close() { controller.error(passedError); } }); const writer = ws.getWriter(); - return writer.close().then(() => promise_rejects(t, passedError, writer.closed, 'closed should stay rejected')); -}, 'when sink calls error synchronously while closing, the stream should become errored'); + return writer.close().then(() => writer.closed); +}, 'when sink calls error synchronously while closing, the stream should not become errored'); promise_test(t => { const ws = new WritableStream({ @@ -94,8 +106,12 @@ promise_test(() => { }, 'releaseLock on a stream with a pending write in which the stream has been errored'); promise_test(() => { + let controller; const ws = new WritableStream({ - close(controller) { + start(c) { + controller = c; + }, + close() { controller.error(error1); return new Promise(() => {}); } @@ -107,7 +123,7 @@ promise_test(() => { return delay(0).then(() => { writer.releaseLock(); }); -}, 'releaseLock on a stream with a pending close in which the stream has been errored'); +}, 'releaseLock on a stream with a pending close in which controller.error() was called'); promise_test(() => { const ws = recordingWritableStream(); @@ -293,7 +309,7 @@ promise_test(() => { }); }, 'promises must fulfill/reject in the expected order on closure'); -promise_test(t => { +promise_test(() => { const ws = new WritableStream({}); // Wait until the WritableStream starts so that the close() call gets processed. Otherwise, abort() will be @@ -316,7 +332,7 @@ promise_test(t => { events.push('closed'); }) ]).then(() => { - assert_array_equals(events, ['closePromise', 'closed', 'abortPromise'], + assert_array_equals(events, ['closePromise', 'abortPromise', 'closed'], 'promises must fulfill/reject in the expected order'); }); }); @@ -337,27 +353,54 @@ promise_test(t => { const abortPromise = writer.abort(error2); const events = []; + closePromise.catch(() => events.push('closePromise')); + abortPromise.catch(() => events.push('abortPromise')); + writer.closed.catch(() => events.push('closed')); return Promise.all([ promise_rejects(t, error1, closePromise, - 'closePromise must reject with the error returned from the sink\'s close method') - .then(() => { - events.push('closePromise'); - }), + 'closePromise must reject with the error returned from the sink\'s close method'), promise_rejects(t, error1, abortPromise, - 'abortPromise must reject with the error returned from the sink\'s close method') - .then(() => { - events.push('abortPromise'); - }), - promise_rejects(t, error1, writer.closed, - 'writer.closed must reject with the error returned from the sink\'s close method') - .then(() => { - events.push('closed'); - }) + 'abortPromise must reject with the error returned from the sink\'s close method'), + promise_rejects(t, new TypeError(), writer.closed, + 'writer.closed must reject with a TypeError indicating the stream was aborted') ]).then(() => { - assert_array_equals(events, ['closePromise', 'closed', 'abortPromise'], + assert_array_equals(events, ['closePromise', 'abortPromise', 'closed'], 'promises must fulfill/reject in the expected order'); }); }); }, 'promises must fulfill/reject in the expected order on aborted and errored closure'); +promise_test(t => { + let resolveWrite; + let controller; + const ws = new WritableStream({ + write(chunk, c) { + controller = c; + return new Promise(resolve => { + resolveWrite = resolve; + }); + } + }); + const writer = ws.getWriter(); + return writer.ready.then(() => { + const writePromise = writer.write('c'); + controller.error(error1); + const closePromise = writer.close(); + let closeRejected = false; + closePromise.catch(() => { + closeRejected = true; + }); + return flushAsyncEvents().then(() => { + assert_false(closeRejected); + resolveWrite(); + return Promise.all([ + writePromise, + promise_rejects(t, error1, closePromise, 'close() should reject') + ]).then(() => { + assert_true(closeRejected); + }); + }); + }); +}, 'close() should not reject until no sink methods are in flight'); + done(); diff --git a/testing/web-platform/tests/streams/writable-streams/constructor.js b/testing/web-platform/tests/streams/writable-streams/constructor.js index dc2bef9a1dfb..a2d986c020c6 100644 --- a/testing/web-platform/tests/streams/writable-streams/constructor.js +++ b/testing/web-platform/tests/streams/writable-streams/constructor.js @@ -37,24 +37,23 @@ promise_test(t => { return Promise.all([ writer.write('a'), - promise_rejects(t, error1, writer.closed, 'controller.error() in write() should errored the stream') + promise_rejects(t, error1, writer.closed, 'controller.error() in write() should error the stream') ]); }, 'controller argument should be passed to write method'); +// Older versions of the standard had the controller argument passed to close(). It wasn't useful, and so has been +// removed. This test remains to identify implementations that haven't been updated. promise_test(t => { const ws = new WritableStream({ - close(controller) { - controller.error(error1); + close(...args) { + t.step(() => { + assert_array_equals(args, [], 'no arguments should be passed to close'); + }); } }); - const writer = ws.getWriter(); - - return Promise.all([ - writer.close(), - promise_rejects(t, error1, writer.closed, 'controller.error() in close() should error the stream') - ]); -}, 'controller argument should be passed to close method'); + return ws.getWriter().close(); +}, 'controller argument should not be passed to close method'); promise_test(() => { const ws = new WritableStream({}, { diff --git a/testing/web-platform/tests/streams/writable-streams/error.dedicatedworker.html b/testing/web-platform/tests/streams/writable-streams/error.dedicatedworker.html new file mode 100644 index 000000000000..9e49ce90a589 --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/error.dedicatedworker.html @@ -0,0 +1,11 @@ + + +error.js dedicated worker wrapper file + + + + + diff --git a/testing/web-platform/tests/streams/writable-streams/error.html b/testing/web-platform/tests/streams/writable-streams/error.html new file mode 100644 index 000000000000..94fa110c2d21 --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/error.html @@ -0,0 +1,10 @@ + + +error.js browser context wrapper file + + + + + + + diff --git a/testing/web-platform/tests/streams/writable-streams/error.js b/testing/web-platform/tests/streams/writable-streams/error.js new file mode 100644 index 000000000000..511f5f7572b1 --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/error.js @@ -0,0 +1,69 @@ +'use strict'; + +if (self.importScripts) { + self.importScripts('/resources/testharness.js'); +} + +const error1 = new Error('error1'); +error1.name = 'error1'; + +const error2 = new Error('error2'); +error2.name = 'error2'; + +promise_test(t => { + const ws = new WritableStream({ + start(controller) { + controller.error(error1); + } + }); + return promise_rejects(t, error1, ws.getWriter().closed, 'stream should be errored'); +}, 'controller.error() should error the stream'); + +test(() => { + let controller; + const ws = new WritableStream({ + start(c) { + controller = c; + } + }); + ws.abort(); + controller.error(error1); +}, 'controller.error() on erroring stream should not throw'); + +promise_test(t => { + let controller; + const ws = new WritableStream({ + start(c) { + controller = c; + } + }); + controller.error(error1); + controller.error(error2); + return promise_rejects(t, error1, ws.getWriter().closed, 'first controller.error() should win'); +}, 'surplus calls to controller.error() should be a no-op'); + +promise_test(() => { + let controller; + const ws = new WritableStream({ + start(c) { + controller = c; + } + }); + return ws.abort().then(() => { + controller.error(error1); + }); +}, 'controller.error() on errored stream should not throw'); + +promise_test(() => { + let controller; + const ws = new WritableStream({ + start(c) { + controller = c; + } + }); + return ws.getWriter().close().then(() => { + controller.error(error1); + }); +}, 'controller.error() on closed stream should not throw'); + +done(); diff --git a/testing/web-platform/tests/streams/writable-streams/error.serviceworker.https.html b/testing/web-platform/tests/streams/writable-streams/error.serviceworker.https.html new file mode 100644 index 000000000000..bec793e8a2bc --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/error.serviceworker.https.html @@ -0,0 +1,12 @@ + + +error.js service worker wrapper file + + + + + + diff --git a/testing/web-platform/tests/streams/writable-streams/error.sharedworker.html b/testing/web-platform/tests/streams/writable-streams/error.sharedworker.html new file mode 100644 index 000000000000..84e628b22a9b --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/error.sharedworker.html @@ -0,0 +1,11 @@ + + +error.js shared worker wrapper file + + + + + diff --git a/testing/web-platform/tests/streams/writable-streams/floating-point-total-queue-size.js b/testing/web-platform/tests/streams/writable-streams/floating-point-total-queue-size.js index 44cf5fb22fd3..932ac2715e70 100644 --- a/testing/web-platform/tests/streams/writable-streams/floating-point-total-queue-size.js +++ b/testing/web-platform/tests/streams/writable-streams/floating-point-total-queue-size.js @@ -88,3 +88,5 @@ function setupTestStream() { return ws.getWriter(); } + +done(); diff --git a/testing/web-platform/tests/streams/writable-streams/general.js b/testing/web-platform/tests/streams/writable-streams/general.js index 0e773ce2a949..1702479337aa 100644 --- a/testing/web-platform/tests/streams/writable-streams/general.js +++ b/testing/web-platform/tests/streams/writable-streams/general.js @@ -226,7 +226,7 @@ promise_test(() => { return writer2.ready; }, 'redundant releaseLock() is no-op'); -promise_test(t => { +promise_test(() => { const events = []; const ws = new WritableStream(); const writer = ws.getWriter(); diff --git a/testing/web-platform/tests/streams/writable-streams/properties.dedicatedworker.html b/testing/web-platform/tests/streams/writable-streams/properties.dedicatedworker.html new file mode 100644 index 000000000000..50d63ed0edb2 --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/properties.dedicatedworker.html @@ -0,0 +1,11 @@ + + +properties.js dedicated worker wrapper file + + + + + diff --git a/testing/web-platform/tests/streams/writable-streams/properties.html b/testing/web-platform/tests/streams/writable-streams/properties.html new file mode 100644 index 000000000000..ad410a53c825 --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/properties.html @@ -0,0 +1,10 @@ + + +properties.js browser context wrapper file + + + + + + + diff --git a/testing/web-platform/tests/streams/writable-streams/properties.js b/testing/web-platform/tests/streams/writable-streams/properties.js new file mode 100644 index 000000000000..6ccb1a2b286d --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/properties.js @@ -0,0 +1,219 @@ +'use strict'; + +if (self.importScripts) { + self.importScripts('/resources/testharness.js'); +} + +// The purpose of this file is to test for objects, attributes and arguments that should not exist. +// The test cases are generated from data tables to reduce duplication. + +// Courtesy of André Bargull. Source is https://esdiscuss.org/topic/isconstructor#content-11. +function IsConstructor(o) { + try { + new new Proxy(o, { construct: () => ({}) })(); + return true; + } catch (e) { + return false; + } +} + +for (const func of ['WritableStreamDefaultController', 'WritableStreamDefaultWriter']) { + test(() => { + assert_equals(self[func], undefined, `${func} should not be defined`); + }, `${func} should not be exported on the global object`); +} + +// Now get hold of the symbols so we can test their properties. +self.WritableStreamDefaultController = (() => { + let controller; + new WritableStream({ + start(c) { + controller = c; + } + }); + return controller.constructor; +})(); +self.WritableStreamDefaultWriter = new WritableStream().getWriter().constructor; + +const expected = { + WritableStream: { + constructor: { + type: 'constructor', + length: 0 + }, + locked: { + type: 'getter' + }, + abort: { + type: 'method', + length: 1 + }, + getWriter: { + type: 'method', + length: 0 + } + }, + WritableStreamDefaultController: { + constructor: { + type: 'constructor', + length: 4 + }, + error: { + type: 'method', + length: 1 + } + }, + WritableStreamDefaultWriter: { + constructor: { + type: 'constructor', + length: 1 + }, + closed: { + type: 'getter' + }, + desiredSize: { + type: 'getter' + }, + ready: { + type: 'getter' + }, + abort: { + type: 'method', + length: 1 + }, + close: { + type: 'method', + length: 0 + }, + releaseLock: { + type: 'method', + length: 0 + }, + write: { + type: 'method', + length: 1 + } + } +}; + +for (const c in expected) { + const properties = expected[c]; + const prototype = self[c].prototype; + for (const name in properties) { + const fullName = `${c}.prototype.${name}`; + const descriptor = Object.getOwnPropertyDescriptor(prototype, name); + test(() => { + const { configurable, enumerable } = descriptor; + assert_true(configurable, `${name} should be configurable`); + assert_false(enumerable, `${name} should not be enumerable`); + }, `${fullName} should have standard properties`); + const type = properties[name].type; + switch (type) { + case 'getter': + test(() => { + const { writable, get, set } = descriptor; + assert_equals(writable, undefined, `${name} should not be a data descriptor`); + assert_equals(typeof get, 'function', `${name} should have a getter`); + assert_equals(set, undefined, `${name} should not have a setter`); + }, `${fullName} should be a getter`); + break; + + case 'constructor': + case 'method': + test(() => { + assert_true(descriptor.writable, `${name} should be writable`); + assert_equals(typeof prototype[name], 'function', `${name} should be a function`); + assert_equals(prototype[name].length, properties[name].length, + `${name} should take ${properties[name].length} arguments`); + if (type === 'constructor') { + assert_true(IsConstructor(prototype[name]), `${name} should be a constructor`); + } else { + assert_false(IsConstructor(prototype[name]), `${name} should not be a constructor`); + } + }, `${fullName} should be a ${type}`); + break; + } + } + test(() => { + const expectedPropertyNames = Object.keys(properties).sort(); + const actualPropertyNames = Object.getOwnPropertyNames(prototype).sort(); + assert_array_equals(actualPropertyNames, expectedPropertyNames, + `${c} properties should match expected properties`); + }, `${c}.prototype should have exactly the expected properties`); +} + +const sinkMethods = { + start: { + length: 1, + trigger: () => {} + }, + write: { + length: 2, + trigger: writer => writer.write() + }, + close: { + length: 0, + trigger: writer => writer.close() + }, + abort: { + length: 1, + trigger: writer => writer.abort() + } +}; + +for (const method in sinkMethods) { + const { length, trigger } = sinkMethods[method]; + + // Some semantic tests of how sink methods are called can be found in general.js, as well as in the test files + // specific to each method. + promise_test(() => { + let argCount; + const ws = new WritableStream({ + [method](...args) { + argCount = args.length; + } + }); + return Promise.resolve(trigger(ws.getWriter())).then(() => { + assert_equals(argCount, length, `${method} should be called with ${length} arguments`); + }); + }, `sink method ${method} should be called with the right number of arguments`); + + promise_test(() => { + let methodWasCalled = false; + function Sink() {} + Sink.prototype = { + [method]() { + methodWasCalled = true; + } + }; + const ws = new WritableStream(new Sink()); + return Promise.resolve(trigger(ws.getWriter())).then(() => { + assert_true(methodWasCalled, `${method} should be called`); + }); + }, `sink method ${method} should be called even when it's located on the prototype chain`); + + if (method !== 'start') { + promise_test(t => { + const unreachedTraps = ['getPrototypeOf', 'setPrototypeOf', 'isExtensible', 'preventExtensions', + 'getOwnPropertyDescriptor', 'defineProperty', 'has', 'set', 'deleteProperty', 'ownKeys', + 'apply', 'construct']; + const handler = { + get: t.step_func((target, property) => { + if (property === 'type') { + return undefined; + } + assert_in_array(property, ['start', method], `only start() and ${method}() should be called`); + return () => Promise.resolve(); + }) + }; + for (const trap of unreachedTraps) { + handler[trap] = t.unreached_func(`${trap} should not be trapped`); + } + const sink = new Proxy({}, handler); + const ws = new WritableStream(sink); + return trigger(ws.getWriter()); + }, `unexpected properties should not be accessed when calling sink method ${method}`); + } +} + +done(); diff --git a/testing/web-platform/tests/streams/writable-streams/properties.serviceworker.https.html b/testing/web-platform/tests/streams/writable-streams/properties.serviceworker.https.html new file mode 100644 index 000000000000..ba5c5135f2f7 --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/properties.serviceworker.https.html @@ -0,0 +1,12 @@ + + +properties.js service worker wrapper file + + + + + + diff --git a/testing/web-platform/tests/streams/writable-streams/properties.sharedworker.html b/testing/web-platform/tests/streams/writable-streams/properties.sharedworker.html new file mode 100644 index 000000000000..42fb3e5ebc0a --- /dev/null +++ b/testing/web-platform/tests/streams/writable-streams/properties.sharedworker.html @@ -0,0 +1,11 @@ + + +properties.js shared worker wrapper file + + + + + diff --git a/testing/web-platform/tests/streams/writable-streams/start.js b/testing/web-platform/tests/streams/writable-streams/start.js index ee6dd8d7298c..0122799b6697 100644 --- a/testing/web-platform/tests/streams/writable-streams/start.js +++ b/testing/web-platform/tests/streams/writable-streams/start.js @@ -132,12 +132,12 @@ promise_test(t => { const writePromise = writer.write('a'); const closePromise = writer.close(); controller.error(error1); + resolveStart(); return Promise.all([ promise_rejects(t, error1, writePromise, 'write() should fail'), promise_rejects(t, error1, closePromise, 'close() should fail') ]).then(() => { assert_array_equals(ws.events, [], 'sink write() and close() should not have been called'); - resolveStart(); }); }, 'controller.error() during async start should cause existing writes to fail'); diff --git a/testing/web-platform/tests/svg/interfaces.html b/testing/web-platform/tests/svg/interfaces.html index 737e0d1c4e6d..36132e2dcf1d 100644 --- a/testing/web-platform/tests/svg/interfaces.html +++ b/testing/web-platform/tests/svg/interfaces.html @@ -1,5 +1,6 @@ SVG interface tests +
diff --git a/testing/web-platform/tests/tools/.gitmodules b/testing/web-platform/tests/tools/.gitmodules index 12cee69142f1..021adfc6de44 100644 --- a/testing/web-platform/tests/tools/.gitmodules +++ b/testing/web-platform/tests/tools/.gitmodules @@ -1,7 +1,3 @@ -[submodule "tools/wptserve"] - path = wptserve - url = https://github.com/w3c/wptserve.git - ignore = dirty [submodule "tools/pywebsocket"] path = pywebsocket url = https://github.com/w3c/pywebsocket.git @@ -15,6 +11,3 @@ [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/testing/web-platform/tests/tools/.travis.yml b/testing/web-platform/tests/tools/.travis.yml deleted file mode 100644 index 37319bf0f5ea..000000000000 --- a/testing/web-platform/tests/tools/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -language: python - -sudo: false - -cache: - directories: - - $HOME/.cache/pip - -matrix: - include: - - python: 2.7 - env: TOXENV=py27 HYPOTHESIS_PROFILE=ci - - python: 3.5 - env: TOXENV=py35 HYPOTHESIS_PROFILE=ci - - python: 3.6 - env: TOXENV=py36 HYPOTHESIS_PROFILE=ci - - python: pypy - env: TOXENV=pypy HYPOTHESIS_PROFILE=ci_pypy - -# An ugly hack needed to make py.test believe our top level can be -# imported (on Travis CI, we end up in a wpt-tools directory, and of -# course you cannot import a name including a hyphen in Python, so it -# ignores the fact we have a __init__.py at the top level). -before_install: - - mv `pwd` /tmp/tools - - cd /tmp/tools - - export TRAVIS_BUILD_DIR=/tmp/tools - -install: - - pip install -U tox codecov - -script: - - tox - -after_success: - - coverage combine - - codecov diff --git a/testing/web-platform/tests/tools/lint/lint.py b/testing/web-platform/tests/tools/lint/lint.py index e1bbd606eac9..00fa6a9f011c 100644 --- a/testing/web-platform/tests/tools/lint/lint.py +++ b/testing/web-platform/tests/tools/lint/lint.py @@ -21,7 +21,28 @@ from six import binary_type, iteritems, itervalues from six.moves import range from six.moves.urllib.parse import urlsplit, urljoin -here = os.path.abspath(os.path.split(__file__)[0]) +import logging + +logger = None + +def setup_logging(prefix=False): + global logger + if logger is None: + logger = logging.getLogger(os.path.basename(os.path.splitext(__file__)[0])) + handler = logging.StreamHandler(sys.stdout) + logger.addHandler(handler) + if prefix: + format = logging.BASIC_FORMAT + else: + format = "%(message)s" + formatter = logging.Formatter(format) + for handler in logger.handlers: + handler.setFormatter(formatter) + logger.setLevel(logging.DEBUG) + + +setup_logging() + ERROR_MSG = """You must fix all errors; for details on how to fix them, see https://github.com/w3c/web-platform-tests/blob/master/docs/lint-tool.md @@ -613,23 +634,40 @@ def output_errors_text(errors): pos_string = path if line_number: pos_string += ":%s" % line_number - print("%s: %s (%s)" % (pos_string, description, error_type)) + logger.error("%s: %s (%s)" % (pos_string, description, error_type)) + +def output_errors_markdown(errors): + if not errors: + return + heading = """Got lint errors: + +| Error Type | Position | Message | +|------------|----------|---------|""" + for line in heading.split("\n"): + logger.error(line) + for error_type, description, path, line_number in errors: + pos_string = path + if line_number: + pos_string += ":%s" % line_number + logger.error("%s | %s | %s |" % (error_type, pos_string, description)) def output_errors_json(errors): for error_type, error, path, line_number in errors: print(json.dumps({"path": path, "lineno": line_number, "rule": error_type, "message": error})) + def output_error_count(error_count): if not error_count: return by_type = " ".join("%s: %d" % item for item in error_count.items()) count = sum(error_count.values()) + logger.info("") if count == 1: - print("There was 1 error (%s)" % (by_type,)) + logger.info("There was 1 error (%s)" % (by_type,)) else: - print("There were %d errors (%s)" % (count, by_type)) + logger.info("There were %d errors (%s)" % (count, by_type)) def parse_args(): parser = argparse.ArgumentParser() @@ -637,26 +675,39 @@ def parse_args(): help="List of paths to lint") parser.add_argument("--json", action="store_true", help="Output machine-readable JSON format") + parser.add_argument("--markdown", action="store_true", + help="Output markdown") parser.add_argument("--css-mode", action="store_true", help="Run CSS testsuite specific lints") return parser.parse_args() -def main(force_css_mode=False): - args = parse_args() - paths = list(args.paths if args.paths else all_filesystem_paths(repo_root)) - return lint(repo_root, paths, args.json, force_css_mode or args.css_mode) -def lint(repo_root, paths, output_json, css_mode): +def main(**kwargs): + if kwargs.get("json") and kwargs.get("markdown"): + logger.critical("Cannot specify --json and --markdown") + sys.exit(2) + + output_format = {(True, False): "json", + (False, True): "markdown", + (False, False): "normal"}[(kwargs.get("json", False), + kwargs.get("markdown", False))] + + paths = list(kwargs.get("paths") if kwargs.get("paths") else all_filesystem_paths(repo_root)) + if output_format == "markdown": + setup_logging(True) + return lint(repo_root, paths, output_format, kwargs.get("css_mode", False)) + + +def lint(repo_root, paths, output_format, css_mode): error_count = defaultdict(int) last = None with open(os.path.join(repo_root, "lint.whitelist")) as f: whitelist, ignored_files = parse_whitelist(f) - if output_json: - output_errors = output_errors_json - else: - output_errors = output_errors_text + output_errors = {"json": output_errors_json, + "markdown": output_errors_markdown, + "normal": output_errors_text}[output_format] def process_errors(errors): """ @@ -699,10 +750,11 @@ def lint(repo_root, paths, output_json, css_mode): errors = check_all_paths(repo_root, paths, css_mode) last = process_errors(errors) or last - if not output_json: + if output_format in ("normal", "markdown"): output_error_count(error_count) if error_count: - print(ERROR_MSG % (last[0], last[1], last[0], last[1])) + for line in (ERROR_MSG % (last[0], last[1], last[0], last[1])).split("\n"): + logger.info(line) return sum(itervalues(error_count)) path_lints = [check_path_length, check_worker_collision] @@ -710,6 +762,7 @@ all_paths_lints = [check_css_globally_unique] file_lints = [check_regexp_line, check_parsed, check_python_ast, check_script_metadata] if __name__ == "__main__": - error_count = main() + args = parse_args() + error_count = main(**vars(args)) if error_count > 0: sys.exit(1) diff --git a/testing/web-platform/tests/tools/lint/tests/test_lint.py b/testing/web-platform/tests/tools/lint/tests/test_lint.py index e8943d7a3c5c..2b41701799ba 100644 --- a/testing/web-platform/tests/tools/lint/tests/test_lint.py +++ b/testing/web-platform/tests/tools/lint/tests/test_lint.py @@ -9,11 +9,10 @@ import six from ...localpaths import repo_root from .. import lint as lint_mod -from ..lint import filter_whitelist_errors, parse_whitelist, lint +from ..lint import filter_whitelist_errors, parse_whitelist, lint, parse_args _dummy_repo = os.path.join(os.path.dirname(__file__), "dummy") - def _mock_lint(name, **kwargs): wrapped = getattr(lint_mod, name) return mock.patch(lint_mod.__name__ + "." + name, wraps=wrapped, **kwargs) @@ -108,313 +107,264 @@ CR AT EOL, INDENT TABS: html/test2.js: 42 assert ignored == expected_ignored -def test_lint_no_files(capsys): - rv = lint(_dummy_repo, [], False, False) +def test_lint_no_files(caplog): + rv = lint(_dummy_repo, [], "normal", False) assert rv == 0 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_lint_ignored_file(capsys): +def test_lint_ignored_file(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["broken_ignored.html"], False, False) + rv = lint(_dummy_repo, ["broken_ignored.html"], "normal", False) assert rv == 0 assert not mocked_check_path.called assert not mocked_check_file_contents.called - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_lint_not_existing_file(capsys): +def test_lint_not_existing_file(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: # really long path-linted filename name = "a" * 256 + ".html" - rv = lint(_dummy_repo, [name], False, False) + rv = lint(_dummy_repo, [name], "normal", False) assert rv == 0 assert not mocked_check_path.called assert not mocked_check_file_contents.called - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_lint_passing(capsys): +def test_lint_passing(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["okay.html"], False, False) + rv = lint(_dummy_repo, ["okay.html"], "normal", False) assert rv == 0 assert mocked_check_path.call_count == 1 assert mocked_check_file_contents.call_count == 1 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_lint_failing(capsys): +def test_lint_failing(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["broken.html"], False, False) + rv = lint(_dummy_repo, ["broken.html"], "normal", False) assert rv == 1 assert mocked_check_path.call_count == 1 assert mocked_check_file_contents.call_count == 1 - out, err = capsys.readouterr() - assert "TRAILING WHITESPACE" in out - assert "broken.html:1" in out - assert err == "" + assert "TRAILING WHITESPACE" in caplog.text + assert "broken.html:1" in caplog.text -def test_ref_existent_relative(capsys): +def test_ref_existent_relative(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["ref/existent_relative.html"], False, False) + rv = lint(_dummy_repo, ["ref/existent_relative.html"], "normal", False) assert rv == 0 assert mocked_check_path.call_count == 1 assert mocked_check_file_contents.call_count == 1 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_ref_existent_root_relative(capsys): +def test_ref_existent_root_relative(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["ref/existent_root_relative.html"], False, False) + rv = lint(_dummy_repo, ["ref/existent_root_relative.html"], "normal", False) assert rv == 0 assert mocked_check_path.call_count == 1 assert mocked_check_file_contents.call_count == 1 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_ref_non_existent_relative(capsys): +def test_ref_non_existent_relative(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["ref/non_existent_relative.html"], False, False) + rv = lint(_dummy_repo, ["ref/non_existent_relative.html"], "normal", False) assert rv == 1 assert mocked_check_path.call_count == 1 assert mocked_check_file_contents.call_count == 1 - out, err = capsys.readouterr() - assert "NON-EXISTENT-REF" in out - assert "ref/non_existent_relative.html" in out - assert "non_existent_file.html" in out - assert err == "" + assert "NON-EXISTENT-REF" in caplog.text + assert "ref/non_existent_relative.html" in caplog.text + assert "non_existent_file.html" in caplog.text -def test_ref_non_existent_root_relative(capsys): +def test_ref_non_existent_root_relative(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["ref/non_existent_root_relative.html"], False, False) + rv = lint(_dummy_repo, ["ref/non_existent_root_relative.html"], "normal", False) assert rv == 1 assert mocked_check_path.call_count == 1 assert mocked_check_file_contents.call_count == 1 - out, err = capsys.readouterr() - assert "NON-EXISTENT-REF" in out - assert "ref/non_existent_root_relative.html" in out - assert "/non_existent_file.html" in out - assert err == "" + assert "NON-EXISTENT-REF" in caplog.text + assert "ref/non_existent_root_relative.html" in caplog.text + assert "/non_existent_file.html" in caplog.text -def test_ref_absolute_url(capsys): + +def test_ref_absolute_url(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["ref/absolute.html"], False, False) + rv = lint(_dummy_repo, ["ref/absolute.html"], "normal", False) assert rv == 1 assert mocked_check_path.call_count == 1 assert mocked_check_file_contents.call_count == 1 - out, err = capsys.readouterr() - assert "ABSOLUTE-URL-REF" in out - assert "http://example.com/reference.html" in out - assert "ref/absolute.html" in out - assert err == "" + assert "ABSOLUTE-URL-REF" in caplog.text + assert "http://example.com/reference.html" in caplog.text + assert "ref/absolute.html" in caplog.text -def test_ref_same_file_empty(capsys): +def test_ref_same_file_empty(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["ref/same_file_empty.html"], False, False) + rv = lint(_dummy_repo, ["ref/same_file_empty.html"], "normal", False) assert rv == 1 assert mocked_check_path.call_count == 1 assert mocked_check_file_contents.call_count == 1 - out, err = capsys.readouterr() - assert "SAME-FILE-REF" in out - assert "same_file_empty.html" in out - assert err == "" + assert "SAME-FILE-REF" in caplog.text + assert "same_file_empty.html" in caplog.text -def test_ref_same_file_path(capsys): +def test_ref_same_file_path(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["ref/same_file_path.html"], False, False) + rv = lint(_dummy_repo, ["ref/same_file_path.html"], "normal", False) assert rv == 1 assert mocked_check_path.call_count == 1 assert mocked_check_file_contents.call_count == 1 - out, err = capsys.readouterr() - assert "SAME-FILE-REF" in out - assert "same_file_path.html" in out - assert err == "" + assert "SAME-FILE-REF" in caplog.text + assert "same_file_path.html" in caplog.text -def test_lint_passing_and_failing(capsys): +def test_lint_passing_and_failing(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["broken.html", "okay.html"], False, False) + rv = lint(_dummy_repo, ["broken.html", "okay.html"], "normal", False) assert rv == 1 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert "TRAILING WHITESPACE" in out - assert "broken.html:1" in out - assert "okay.html" not in out - assert err == "" + assert "TRAILING WHITESPACE" in caplog.text + assert "broken.html:1" in caplog.text + assert "okay.html" not in caplog.text -def test_check_css_globally_unique_identical_test(capsys): +def test_check_css_globally_unique_identical_test(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/match/a.html", "css-unique/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/match/a.html", "css-unique/a.html"], "normal", True) assert rv == 0 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_check_css_globally_unique_different_test(capsys): +def test_check_css_globally_unique_different_test(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/not-match/a.html", "css-unique/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/not-match/a.html", "css-unique/a.html"], "normal", True) assert rv == 2 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert "CSS-COLLIDING-TEST-NAME" in out - assert err == "" + assert "CSS-COLLIDING-TEST-NAME" in caplog.text -def test_check_css_globally_unique_different_spec_test(capsys): +def test_check_css_globally_unique_different_spec_test(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/selectors/a.html", "css-unique/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/selectors/a.html", "css-unique/a.html"], "normal", True) assert rv == 0 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_check_css_globally_unique_support_ignored(capsys): +def test_check_css_globally_unique_support_ignored(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/support/tools/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/support/tools/a.html"], "normal", True) assert rv == 0 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_check_css_globally_unique_support_identical(capsys): +def test_check_css_globally_unique_support_identical(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/match/support/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/match/support/a.html"], "normal", True) assert rv == 0 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_check_css_globally_unique_support_different(capsys): +def test_check_css_globally_unique_support_different(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/not-match/support/a.html", "css-unique/support/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/not-match/support/a.html", "css-unique/support/a.html"], "normal", True) assert rv == 2 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert "CSS-COLLIDING-SUPPORT-NAME" in out - assert err == "" + assert "CSS-COLLIDING-SUPPORT-NAME" in caplog.text -def test_check_css_globally_unique_test_support(capsys): +def test_check_css_globally_unique_test_support(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/a.html"], "normal", True) assert rv == 0 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_check_css_globally_unique_ref_identical(capsys): +def test_check_css_globally_unique_ref_identical(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/a-ref.html", "css-unique/match/a-ref.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/a-ref.html", "css-unique/match/a-ref.html"], "normal", True) assert rv == 0 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_check_css_globally_unique_ref_different(capsys): +def test_check_css_globally_unique_ref_different(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/not-match/a-ref.html", "css-unique/a-ref.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/not-match/a-ref.html", "css-unique/a-ref.html"], "normal", True) assert rv == 2 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert "CSS-COLLIDING-REF-NAME" in out - assert err == "" + assert "CSS-COLLIDING-REF-NAME" in caplog.text -def test_check_css_globally_unique_test_ref(capsys): +def test_check_css_globally_unique_test_ref(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/a-ref.html", "css-unique/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/a-ref.html", "css-unique/a.html"], "normal", True) assert rv == 0 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_check_css_globally_unique_ignored(capsys): +def test_check_css_globally_unique_ignored(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/tools/a.html", "css-unique/not-match/tools/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/tools/a.html", "css-unique/not-match/tools/a.html"], "normal", True) assert rv == 0 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" -def test_check_css_globally_unique_ignored_dir(capsys): +def test_check_css_globally_unique_ignored_dir(caplog): with _mock_lint("check_path") as mocked_check_path: with _mock_lint("check_file_contents") as mocked_check_file_contents: - rv = lint(_dummy_repo, ["css-unique/support/a.html", "css/work-in-progress/foo/support/a.html"], False, True) + rv = lint(_dummy_repo, ["css-unique/support/a.html", "css/work-in-progress/foo/support/a.html"], "normal", True) assert rv == 0 assert mocked_check_path.call_count == 2 assert mocked_check_file_contents.call_count == 2 - out, err = capsys.readouterr() - assert out == "" - assert err == "" + assert caplog.text == "" def test_all_filesystem_paths(): @@ -439,8 +389,8 @@ def test_main_with_args(): try: sys.argv = ['./lint', 'a', 'b', 'c'] with _mock_lint('lint', return_value=True) as m: - lint_mod.main() - m.assert_called_once_with(repo_root, ['a', 'b', 'c'], False, False) + lint_mod.main(**vars(parse_args())) + m.assert_called_once_with(repo_root, ['a', 'b', 'c'], "normal", False) finally: sys.argv = orig_argv @@ -451,7 +401,7 @@ def test_main_no_args(): sys.argv = ['./lint'] with _mock_lint('lint', return_value=True) as m: with _mock_lint('all_filesystem_paths', return_value=['foo', 'bar']) as m2: - lint_mod.main() - m.assert_called_once_with(repo_root, ['foo', 'bar'], False, False) + lint_mod.main(**vars(parse_args())) + m.assert_called_once_with(repo_root, ['foo', 'bar'], "normal", False) finally: sys.argv = orig_argv diff --git a/testing/web-platform/tests/tools/pytest.ini b/testing/web-platform/tests/tools/pytest.ini index 1fb328e1f977..8cc3d6f22395 100644 --- a/testing/web-platform/tests/tools/pytest.ini +++ b/testing/web-platform/tests/tools/pytest.ini @@ -1,2 +1,2 @@ [pytest] -norecursedirs = .* {arch} *.egg html5lib py pytest pywebsocket six webdriver wptserve +norecursedirs = .* {arch} *.egg html5lib py pytest pywebsocket six wptrunner diff --git a/testing/web-platform/tests/tools/tox.ini b/testing/web-platform/tests/tools/tox.ini index 4acefc401c7a..1ea30a5da186 100644 --- a/testing/web-platform/tests/tools/tox.ini +++ b/testing/web-platform/tests/tools/tox.ini @@ -6,12 +6,13 @@ skipsdist=True deps = flake8 pytest - coverage + pytest-cov mock hypothesis + pytest-catchlog commands = - coverage run -m pytest + pytest --cov flake8 passenv = @@ -20,4 +21,4 @@ passenv = [flake8] ignore = E128,E129,E221,E226,E231,E251,E265,E302,E303,E305,E402,E901,F401,F821,F841 max-line-length = 141 -exclude = .tox,html5lib,py,pytest,pywebsocket,six,webdriver,wptserve +exclude = .tox,html5lib,py,pytest,pywebsocket,six,_venv,webencodings,wptserve/docs,wptserve/tests/functional/docroot/,wptrunner diff --git a/testing/web-platform/tests/tools/webdriver/COPYING b/testing/web-platform/tests/tools/webdriver/COPYING deleted file mode 100644 index 14e2f777f6c3..000000000000 --- a/testing/web-platform/tests/tools/webdriver/COPYING +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - 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/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/testing/web-platform/tests/tools/webdriver/setup.py b/testing/web-platform/tests/tools/webdriver/setup.py index 720fcf05cd26..c473961cb64f 100644 --- a/testing/web-platform/tests/tools/webdriver/setup.py +++ b/testing/web-platform/tests/tools/webdriver/setup.py @@ -1,7 +1,3 @@ -# 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", @@ -10,7 +6,7 @@ setup(name="webdriver", "the W3C browser automation specification.", author="Mozilla Engineering Productivity", author_email="tools@lists.mozilla.org", - license="MPL 2.0", + license="BSD", packages=find_packages(), classifiers=["Development Status :: 4 - Beta", "Intended Audience :: Developers", diff --git a/testing/web-platform/tests/tools/webdriver/webdriver/__init__.py b/testing/web-platform/tests/tools/webdriver/webdriver/__init__.py index c827f59f138a..30243f7205d7 100644 --- a/testing/web-platform/tests/tools/webdriver/webdriver/__init__.py +++ b/testing/web-platform/tests/tools/webdriver/webdriver/__init__.py @@ -1,7 +1,3 @@ -# 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, diff --git a/testing/web-platform/tests/tools/webdriver/webdriver/client.py b/testing/web-platform/tests/tools/webdriver/webdriver/client.py index dc8679a547dc..c948c8e418ee 100644 --- a/testing/web-platform/tests/tools/webdriver/webdriver/client.py +++ b/testing/web-platform/tests/tools/webdriver/webdriver/client.py @@ -1,7 +1,3 @@ -# 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 error @@ -20,7 +16,7 @@ def command(func): if session.session_id is None: session.start() - assert session.session_id != None + assert session.session_id is not None return func(self, *args, **kwargs) @@ -89,26 +85,30 @@ class ActionSequence(object): .key_up("a") \ .perform() """ - def __init__(self, session, action_type, input_id): + def __init__(self, session, action_type, input_id, pointer_params=None): """Represents a sequence of actions of one type for one input source. :param session: WebDriver session. :param action_type: Action type; may be "none", "key", or "pointer". :param input_id: ID of input source. + :param pointer_params: Optional dictionary of pointer parameters. """ self.session = session - # TODO take advantage of remote end generating uuid self._id = input_id self._type = action_type self._actions = [] + self._pointer_params = pointer_params @property def dict(self): - return { - "type": self._type, - "id": self._id, - "actions": self._actions, + d = { + "type": self._type, + "id": self._id, + "actions": self._actions, } + if self._pointer_params is not None: + d["parameters"] = self._pointer_params + return d @command def perform(self): @@ -121,10 +121,6 @@ class ActionSequence(object): def _pointer_action(self, subtype, button): self._actions.append({"type": subtype, "button": button}) - def pause(self, duration): - self._actions.append({"type": "pause", "duration": duration}) - return self - def pointer_move(self, x, y, duration=None, origin=None): """Queue a pointerMove action. @@ -147,38 +143,22 @@ class ActionSequence(object): self._actions.append(action) return self - def pointer_up(self, button=0): + def pointer_up(self, button): """Queue a pointerUp action for `button`. :param button: Pointer button to perform action with. - Default: 0, which represents main device button. """ self._pointer_action("pointerUp", button) return self - def pointer_down(self, button=0): + def pointer_down(self, button): """Queue a pointerDown action for `button`. :param button: Pointer button to perform action with. - Default: 0, which represents main device button. """ self._pointer_action("pointerDown", button) return self - def click(self, element=None, button=0): - """Queue a click with the specified button. - - If an element is given, move the pointer to that element first, - otherwise click current pointer coordinates. - - :param element: Optional element to click. - :param button: Integer representing pointer button to perform action - with. Default: 0, which represents main device button. - """ - if element: - self.pointer_move(0, 0, origin=element) - return self.pointer_down(button).pointer_up(button) - def key_up(self, value): """Queue a keyUp action for `value`. @@ -232,6 +212,7 @@ class Actions(object): """ return ActionSequence(self.session, *args, **kwargs) + class Window(object): def __init__(self, session): self.session = session @@ -244,7 +225,8 @@ class Window(object): @size.setter @command - def size(self, (width, height)): + def size(self, data): + width, height = data body = {"width": width, "height": height} self.session.send_session_command("POST", "window/rect", body) @@ -256,7 +238,8 @@ class Window(object): @position.setter @command - def position(self, (x, y)): + def position(self, data): + data = x, y body = {"x": x, "y": y} self.session.send_session_command("POST", "window/rect", body) @@ -333,12 +316,11 @@ class UserPrompt(object): class Session(object): - def __init__(self, host, port, url_prefix="/", desired_capabilities=None, - required_capabilities=None, extension=None, timeout=None): + def __init__(self, host, port, url_prefix="/", capabilities=None, + timeout=None, extension=None): self.transport = transport.HTTPWireProtocol( host, port, url_prefix, timeout=timeout) - self.desired_capabilities = desired_capabilities - self.required_capabilities = required_capabilities + self.capabilities = capabilities self.session_id = None self.timeouts = None self.window = None @@ -369,13 +351,8 @@ class Session(object): 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 - body = caps + if self.capabilities is not None: + body["capabilities"] = self.capabilities value = self.send_command("POST", "session", body=body) self.session_id = value["sessionId"] @@ -618,12 +595,8 @@ class Element(object): self.send_element_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.send_element_command("POST", "value", body) + def send_keys(self, text): + return self.send_element_command("POST", "value", {"text": text}) @property @command diff --git a/testing/web-platform/tests/tools/webdriver/webdriver/error.py b/testing/web-platform/tests/tools/webdriver/webdriver/error.py index a6a703d674bb..0530ff9c5da0 100644 --- a/testing/web-platform/tests/tools/webdriver/webdriver/error.py +++ b/testing/web-platform/tests/tools/webdriver/webdriver/error.py @@ -1,8 +1,3 @@ -# 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 diff --git a/testing/web-platform/tests/tools/webdriver/webdriver/servo.py b/testing/web-platform/tests/tools/webdriver/webdriver/servo.py index fd1539f7bc72..2e0b722ababe 100644 --- a/testing/web-platform/tests/tools/webdriver/webdriver/servo.py +++ b/testing/web-platform/tests/tools/webdriver/webdriver/servo.py @@ -1,7 +1,3 @@ -# 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 diff --git a/testing/web-platform/tests/tools/webdriver/webdriver/transport.py b/testing/web-platform/tests/tools/webdriver/webdriver/transport.py index 0b025c5a12bc..de58d85690f7 100644 --- a/testing/web-platform/tests/tools/webdriver/webdriver/transport.py +++ b/testing/web-platform/tests/tools/webdriver/webdriver/transport.py @@ -1,12 +1,7 @@ -# 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 httplib import json import urlparse - class Response(object): """Describes an HTTP response received from a remote en"Describes an HTTP response received from a remote end whose body has been read and parsed as @@ -46,7 +41,6 @@ class Response(object): return cls(status, body) - class HTTPWireProtocol(object): """Transports messages (commands and responses) over the WebDriver wire protocol. diff --git a/testing/web-platform/tests/tools/wptrunner/.gitignore b/testing/web-platform/tests/tools/wptrunner/.gitignore new file mode 100644 index 000000000000..495616ef1d19 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/.gitignore @@ -0,0 +1,8 @@ +*.py[co] +*~ +*# +\#* +_virtualenv +test/test.cfg +test/metadata/MANIFEST.json +wptrunner.egg-info diff --git a/testing/web-platform/tests/tools/LICENSE b/testing/web-platform/tests/tools/wptrunner/LICENSE similarity index 100% rename from testing/web-platform/tests/tools/LICENSE rename to testing/web-platform/tests/tools/wptrunner/LICENSE diff --git a/testing/web-platform/tests/tools/wptrunner/MANIFEST.in b/testing/web-platform/tests/tools/wptrunner/MANIFEST.in new file mode 100644 index 000000000000..0c5e38bf2654 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/MANIFEST.in @@ -0,0 +1,17 @@ +exclude MANIFEST.in +include requirements.txt +include wptrunner/browsers/b2g_setup/* +include wptrunner.default.ini +include wptrunner/testharness_runner.html +include wptrunner/testharnessreport.js +include wptrunner/testharnessreport-servo.js +include wptrunner/testharnessreport-servodriver.js +include wptrunner/executors/testharness_marionette.js +include wptrunner/executors/testharness_servodriver.js +include wptrunner/executors/testharness_webdriver.js +include wptrunner/executors/reftest.js +include wptrunner/executors/reftest-wait.js +include wptrunner/executors/reftest-wait_servodriver.js +include wptrunner/executors/reftest-wait_webdriver.js +include wptrunner/config.json +include wptrunner/browsers/server-locations.txt \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/README.rst b/testing/web-platform/tests/tools/wptrunner/README.rst new file mode 100644 index 000000000000..fc650eec45ac --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/README.rst @@ -0,0 +1,242 @@ +wptrunner: A web-platform-tests harness +======================================= + +wptrunner is a harness for running the W3C `web-platform-tests testsuite`_. + +.. contents:: + +Installation +~~~~~~~~~~~~ + +wptrunner is expected to be installed into a virtualenv using pip. For +development, it can be installed using the `-e` option:: + + pip install -e ./ + +Running the Tests +~~~~~~~~~~~~~~~~~ + +After installation, the command ``wptrunner`` should be available to run +the tests. + +The ``wptrunner`` command takes multiple options, of which the +following are most significant: + +``--product`` (defaults to `firefox`) + The product to test against: `b2g`, `chrome`, `firefox`, or `servo`. + +``--binary`` (required if product is `firefox` or `servo`) + The path to a binary file for the product (browser) to test against. + +``--webdriver-binary`` (required if product is `chrome`) + The path to a `driver` binary; e.g., a `chromedriver` binary. + +``--certutil-binary`` (required if product is `firefox` [#]_) + The path to a `certutil` binary (for tests that must be run over https). + +``--metadata`` (required) + The path to a directory containing test metadata. [#]_ + +``--tests`` (required) + The path to a directory containing a web-platform-tests checkout. + +``--prefs-root`` (required only when testing a Firefox binary) + The path to a directory containing Firefox test-harness preferences. [#]_ + +``--config`` (should default to `wptrunner.default.ini`) + The path to the config (ini) file. + +.. [#] The ``--certutil-binary`` option is required when the product is + ``firefox`` unless ``--ssl-type=none`` is specified. + +.. [#] The ``--metadata`` path is to a directory that contains: + + * a ``MANIFEST.json`` file (instructions on generating this file are + available in the `detailed documentation + `_); + and + * (optionally) any expectation files (see below) + +.. [#] Example ``--prefs-root`` value: ``~/mozilla-central/testing/profiles``. + +There are also a variety of other options available; use ``--help`` to +list them. + +------------------------------- +Example: How to start wptrunner +------------------------------- + +To test a Firefox Nightly build in an OS X environment, you might start +wptrunner using something similar to the following example:: + + wptrunner --metadata=~/web-platform-tests/ --tests=~/web-platform-tests/ \ + --binary=~/mozilla-central/obj-x86_64-apple-darwin14.3.0/dist/Nightly.app/Contents/MacOS/firefox \ + --certutil-binary=~/mozilla-central/obj-x86_64-apple-darwin14.3.0/security/nss/cmd/certutil/certutil \ + --prefs-root=~/mozilla-central/testing/profiles + +And to test a Chromium build in an OS X environment, you might start +wptrunner using something similar to the following example:: + + wptrunner --metadata=~/web-platform-tests/ --tests=~/web-platform-tests/ \ + --binary=~/chromium/src/out/Release/Chromium.app/Contents/MacOS/Chromium \ + --webdriver-binary=/usr/local/bin/chromedriver --product=chrome + +------------------------------------- +Example: How to run a subset of tests +------------------------------------- + +To restrict a test run just to tests in a particular web-platform-tests +subdirectory, specify the directory name in the positional arguments after +the options; for example, run just the tests in the `dom` subdirectory:: + + wptrunner --metadata=~/web-platform-tests/ --tests=~/web-platform-tests/ \ + --binary=/path/to/firefox --certutil-binary=/path/to/certutil \ + --prefs-root=/path/to/testing/profiles \ + dom + +Output +~~~~~~ + +By default wptrunner just dumps its entire output as raw JSON messages +to stdout. This is convenient for piping into other tools, but not ideal +for humans reading the output. + +As an alternative, you can use the ``--log-mach`` option, which provides +output in a reasonable format for humans. The option requires a value: +either the path for a file to write the `mach`-formatted output to, or +"`-`" (a hyphen) to write the `mach`-formatted output to stdout. + +When using ``--log-mach``, output of the full raw JSON log is still +available, from the ``--log-raw`` option. So to output the full raw JSON +log to a file and a human-readable summary to stdout, you might start +wptrunner using something similar to the following example:: + + wptrunner --metadata=~/web-platform-tests/ --tests=~/web-platform-tests/ \ + --binary=/path/to/firefox --certutil-binary=/path/to/certutil \ + --prefs-root=/path/to/testing/profiles \ + --log-raw=output.log --log-mach=- + +Expectation Data +~~~~~~~~~~~~~~~~ + +wptrunner is designed to be used in an environment where it is not +just necessary to know which tests passed, but to compare the results +between runs. For this reason it is possible to store the results of a +previous run in a set of ini-like "expectation files". This format is +documented below. To generate the expectation files use `wptrunner` with +the `--log-raw=/path/to/log/file` option. This can then be used as +input to the `wptupdate` tool. + +Expectation File Format +~~~~~~~~~~~~~~~~~~~~~~~ + +Metadata about tests, notably including their expected results, is +stored in a modified ini-like format that is designed to be human +editable, but also to be machine updatable. + +Each test file that requires metadata to be specified (because it has +a non-default expectation or because it is disabled, for example) has +a corresponding expectation file in the `metadata` directory. For +example a test file `html/test1.html` containing a failing test would +have an expectation file called `html/test1.html.ini` in the +`metadata` directory. + +An example of an expectation file is:: + + example_default_key: example_value + + [filename.html] + type: testharness + + [subtest1] + expected: FAIL + + [subtest2] + expected: + if platform == 'win': TIMEOUT + if platform == 'osx': ERROR + FAIL + + [filename.html?query=something] + type: testharness + disabled: bug12345 + +The file consists of two elements, key-value pairs and +sections. + +Sections are delimited by headings enclosed in square brackets. Any +closing square bracket in the heading itself my be escaped with a +backslash. Each section may then contain any number of key-value pairs +followed by any number of subsections. So that it is clear which data +belongs to each section without the use of end-section markers, the +data for each section (i.e. the key-value pairs and subsections) must +be indented using spaces. Indentation need only be consistent, but +using two spaces per level is recommended. + +In a test expectation file, each resource provided by the file has a +single section, with the section heading being the part after the last +`/` in the test url. Tests that have subsections may have subsections +for those subtests in which the heading is the name of the subtest. + +Simple key-value pairs are of the form:: + + key: value + +Note that unlike ini files, only `:` is a valid seperator; `=` will +not work as expected. Key-value pairs may also have conditional +values of the form:: + + key: + if condition1: value1 + if condition2: value2 + default + +In this case each conditional is evaluated in turn and the value is +that on the right hand side of the first matching conditional. In the +case that no condition matches, the unconditional default is used. If +no condition matches and no default is provided it is equivalent to +the key not being present. Conditionals use a simple python-like expression +language e.g.:: + + if debug and (platform == "linux" or platform == "osx"): FAIL + +For test expectations the avaliable variables are those in the +`run_info` which for desktop are `version`, `os`, `bits`, `processor`, +`debug` and `product`. + +Key-value pairs specified at the top level of the file before any +sections are special as they provide defaults for the rest of the file +e.g.:: + + key1: value1 + + [section 1] + key2: value2 + + [section 2] + key1: value3 + +In this case, inside section 1, `key1` would have the value `value1` +and `key2` the value `value2` whereas in section 2 `key1` would have +the value `value3` and `key2` would be undefined. + +The web-platform-test harness knows about several keys: + +`expected` + Must evaluate to a possible test status indicating the expected + result of the test. The implicit default is PASS or OK when the + field isn't present. + +`disabled` + Any value indicates that the test is disabled. + +`type` + The test type e.g. `testharness`, `reftest`, or `wdspec`. + +`reftype` + The type of comparison for reftests; either `==` or `!=`. + +`refurl` + The reference url for reftests. + +.. _`web-platform-tests testsuite`: https://github.com/w3c/web-platform-tests diff --git a/testing/web-platform/tests/tools/wptrunner/docs/Makefile b/testing/web-platform/tests/tools/wptrunner/docs/Makefile new file mode 100644 index 000000000000..d02b6c5e7c4f --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/docs/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' 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 " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/wptrunner.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/wptrunner.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/wptrunner" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/wptrunner" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/testing/web-platform/tests/tools/wptrunner/docs/architecture.svg b/testing/web-platform/tests/tools/wptrunner/docs/architecture.svg new file mode 100644 index 000000000000..b8d5aa21c19a --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/docs/architecture.svg @@ -0,0 +1 @@ +
TestRunner
[Not supported by viewer]
Product under test
[Not supported by viewer]
TestRunnerManager
[Not supported by viewer]
ManagerGroup
[Not supported by viewer]
Executor
[Not supported by viewer]
Browser
[Not supported by viewer]
ExecutorBrowser
[Not supported by viewer]
run_tests
[Not supported by viewer]
TestLoader
[Not supported by viewer]
TestEnvironment
[Not supported by viewer]
wptserve
[Not supported by viewer]
pywebsocket
[Not supported by viewer]
Queue.get
serve.py
[Not supported by viewer]
Communication (cross process)Ownership (same process)Ownership (cross process)wptrunner classPer-product wptrunner classPer-protocol wptrunner classWeb-platform-tests componentBrowser process
TestRunnerManager
[Not supported by viewer]
TestRunnerManager
[Not supported by viewer]
Browser controlprotocol(e.g. WebDriver)HTTPwebsockets
Tests Queue
[Not supported by viewer]
diff --git a/testing/web-platform/tests/tools/wptrunner/docs/conf.py b/testing/web-platform/tests/tools/wptrunner/docs/conf.py new file mode 100644 index 000000000000..39e5cc4f0d20 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/docs/conf.py @@ -0,0 +1,267 @@ +# -*- coding: utf-8 -*- +# +# wptrunner documentation build configuration file, created by +# sphinx-quickstart on Mon May 19 18:14:20 2014. +# +# 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 +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.viewcode', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'wptrunner' +copyright = u'' + +# 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. +version = '0.3' +# The full version, including alpha/beta/rc tags. +release = '0.3' + +# 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 = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- 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'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a 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 = 'wptrunnerdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'wptrunner.tex', u'wptrunner Documentation', + u'James Graham', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'wptrunner', u'wptrunner Documentation', + [u'James Graham'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'wptrunner', u'wptrunner Documentation', + u'James Graham', 'wptrunner', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'python': ('http://docs.python.org/', None), + 'mozlog': ('http://mozbase.readthedocs.org/en/latest/', None)} diff --git a/testing/web-platform/tests/tools/wptrunner/docs/design.rst b/testing/web-platform/tests/tools/wptrunner/docs/design.rst new file mode 100644 index 000000000000..bf108a0087da --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/docs/design.rst @@ -0,0 +1,106 @@ +wptrunner Design +================ + +The design of wptrunner is intended to meet the following +requirements: + + * Possible to run tests from W3C web-platform-tests. + + * Tests should be run as fast as possible. In particular it should + not be necessary to restart the browser between tests, or similar. + + * As far as possible, the tests should run in a "normal" browser and + browsing context. In particular many tests assume that they are + running in a top-level browsing context, so we must avoid the use + of an ``iframe`` test container. + + * It must be possible to deal with all kinds of behaviour of the + browser runder test, for example, crashing, hanging, etc. + + * It should be possible to add support for new platforms and browsers + with minimal code changes. + + * It must be possible to run tests in parallel to further improve + performance. + + * Test output must be in a machine readable form. + +Architecture +------------ + +In order to meet the above requirements, wptrunner is designed to +push as much of the test scheduling as possible into the harness. This +allows the harness to monitor the state of the browser and perform +appropriate action if it gets into an unwanted state e.g. kill the +browser if it appears to be hung. + +The harness will typically communicate with the browser via some remote +control protocol such as WebDriver. However for browsers where no such +protocol is supported, other implementation strategies are possible, +typically at the expense of speed. + +The overall architecture of wptrunner is shown in the diagram below: + +.. image:: architecture.svg + +The main entry point to the code is :py:func:`run_tests` in +``wptrunner.py``. This is responsible for setting up the test +environment, loading the list of tests to be executed, and invoking +the remainder of the code to actually execute some tests. + +The test environment is encapsulated in the +:py:class:`TestEnvironment` class. This defers to code in +``web-platform-tests`` which actually starts the required servers to +run the tests. + +The set of tests to run is defined by the +:py:class:`TestLoader`. This is constructed with a +:py:class:`TestFilter` (not shown), which takes any filter arguments +from the command line to restrict the set of tests that will be +run. The :py:class:`TestLoader` reads both the ``web-platform-tests`` +JSON manifest and the expectation data stored in ini files and +produces a :py:class:`multiprocessing.Queue` of tests to run, and +their expected results. + +Actually running the tests happens through the +:py:class:`ManagerGroup` object. This takes the :py:class:`Queue` of +tests to be run and starts a :py:class:`testrunner.TestRunnerManager` for each +instance of the browser under test that will be started. These +:py:class:`TestRunnerManager` instances are each started in their own +thread. + +A :py:class:`TestRunnerManager` coordinates starting the product under +test, and outputting results from the test. In the case that the test +has timed out or the browser has crashed, it has to restart the +browser to ensure the test run can continue. The functionality for +initialising the browser under test, and probing its state +(e.g. whether the process is still alive) is implemented through a +:py:class:`Browser` object. An implementation of this class must be +provided for each product that is supported. + +The functionality for actually running the tests is provided by a +:py:class:`TestRunner` object. :py:class:`TestRunner` instances are +run in their own child process created with the +:py:mod:`multiprocessing` module. This allows them to run concurrently +and to be killed and restarted as required. Communication between the +:py:class:`TestRunnerManager` and the :py:class:`TestRunner` is +provided by a pair of queues, one for sending messages in each +direction. In particular test results are sent from the +:py:class:`TestRunner` to the :py:class:`TestRunnerManager` using one +of these queues. + +The :py:class:`TestRunner` object is generic in that the same +:py:class:`TestRunner` is used regardless of the product under +test. However the details of how to run the test may vary greatly with +the product since different products support different remote control +protocols (or none at all). These protocol-specific parts are placed +in the :py:class:`Executor` object. There is typically a different +:py:class:`Executor` class for each combination of control protocol +and test type. The :py:class:`TestRunner` is responsible for pulling +each test off the :py:class:`Queue` of tests and passing it down to +the :py:class:`Executor`. + +The executor often requires access to details of the particular +browser instance that it is testing so that it knows e.g. which port +to connect to to send commands to the browser. These details are +encapsulated in the :py:class:`ExecutorBrowser` class. diff --git a/testing/web-platform/tests/tools/wptrunner/docs/expectation.rst b/testing/web-platform/tests/tools/wptrunner/docs/expectation.rst new file mode 100644 index 000000000000..6a0c77684a3b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/docs/expectation.rst @@ -0,0 +1,248 @@ +Expectation Data +================ + +Introduction +------------ + +For use in continuous integration systems, and other scenarios where +regression tracking is required, wptrunner supports storing and +loading the expected result of each test in a test run. Typically +these expected results will initially be generated by running the +testsuite in a baseline build. They may then be edited by humans as +new features are added to the product that change the expected +results. The expected results may also vary for a single product +depending on the platform on which it is run. Therefore, the raw +structured log data is not a suitable format for storing these +files. Instead something is required that is: + + * Human readable + + * Human editable + + * Machine readable / writable + + * Capable of storing test id / result pairs + + * Suitable for storing in a version control system (i.e. text-based) + +The need for different results per platform means either having +multiple expectation files for each platform, or having a way to +express conditional values within a certain file. The former would be +rather cumbersome for humans updating the expectation files, so the +latter approach has been adopted, leading to the requirement: + + * Capable of storing result values that are conditional on the platform. + +There are few extant formats that meet these requirements, so +wptrunner uses a bespoke ``expectation manifest`` format, which is +closely based on the standard ``ini`` format. + +Directory Layout +---------------- + +Expectation manifest files must be stored under the ``metadata`` +directory passed to the test runner. The directory layout follows that +of web-platform-tests with each test path having a corresponding +manifest file. Tests that differ only by query string, or reftests +with the same test path but different ref paths share the same +reference file. The file name is taken from the last /-separated part +of the path, suffixed with ``.ini``. + +As an optimisation, files which produce only default results +(i.e. ``PASS`` or ``OK``) don't require a corresponding manifest file. + +For example a test with url:: + + /spec/section/file.html?query=param + +would have an expectation file :: + + metadata/spec/section/file.html.ini + + +.. _wptupdate-label: + +Generating Expectation Files +---------------------------- + +wptrunner provides the tool ``wptupdate`` to generate expectation +files from the results of a set of baseline test runs. The basic +syntax for this is:: + + wptupdate [options] [logfile]... + +Each ``logfile`` is a structured log file from a previous run. These +can be generated from wptrunner using the ``--log-raw`` option +e.g. ``--log-raw=structured.log``. The default behaviour is to update +all the test data for the particular combination of hardware and OS +used in the run corresponding to the log data, whilst leaving any +other expectations untouched. + +wptupdate takes several useful options: + +``--sync`` + Pull the latest version of web-platform-tests from the + upstream specified in the config file. If this is specified in + combination with logfiles, it is assumed that the results in the log + files apply to the post-update tests. + +``--no-check-clean`` + Don't attempt to check if the working directory is clean before + doing the update (assuming that the working directory is a git or + mercurial tree). + +``--patch`` + Create a a git commit, or a mq patch, with the changes made by wptupdate. + +``--ignore-existing`` + Overwrite all the expectation data for any tests that have a result + in the passed log files, not just data for the same platform. + +Examples +~~~~~~~~ + +Update the local copy of web-platform-tests without changing the +expectation data and commit (or create a mq patch for) the result:: + + wptupdate --patch --sync + +Update all the expectations from a set of cross-platform test runs:: + + wptupdate --no-check-clean --patch osx.log linux.log windows.log + +Add expectation data for some new tests that are expected to be +platform-independent:: + + wptupdate --no-check-clean --patch --ignore-existing tests.log + +Manifest Format +--------------- +The format of the manifest files is based on the ini format. Files are +divided into sections, each (apart from the root section) having a +heading enclosed in square braces. Within each section are key-value +pairs. There are several notable differences from standard .ini files, +however: + + * Sections may be hierarchically nested, with significant whitespace + indicating nesting depth. + + * Only ``:`` is valid as a key/value separator + +A simple example of a manifest file is:: + + root_key: root_value + + [section] + section_key: section_value + + [subsection] + subsection_key: subsection_value + + [another_section] + another_key: another_value + +Conditional Values +~~~~~~~~~~~~~~~~~~ + +In order to support values that depend on some external data, the +right hand side of a key/value pair can take a set of conditionals +rather than a plain value. These values are placed on a new line +following the key, with significant indentation. Conditional values +are prefixed with ``if`` and terminated with a colon, for example:: + + key: + if cond1: value1 + if cond2: value2 + value3 + +In this example, the value associated with ``key`` is determined by +first evaluating ``cond1`` against external data. If that is true, +``key`` is assigned the value ``value1``, otherwise ``cond2`` is +evaluated in the same way. If both ``cond1`` and ``cond2`` are false, +the unconditional ``value3`` is used. + +Conditions themselves use a Python-like expression syntax. Operands +can either be variables, corresponding to data passed in, numbers +(integer or floating point; exponential notation is not supported) or +quote-delimited strings. Equality is tested using ``==`` and +inequality by ``!=``. The operators ``and``, ``or`` and ``not`` are +used in the expected way. Parentheses can also be used for +grouping. For example:: + + key: + if (a == 2 or a == 3) and b == "abc": value1 + if a == 1 or b != "abc": value2 + value3 + +Here ``a`` and ``b`` are variables, the value of which will be +supplied when the manifest is used. + +Expectation Manifests +--------------------- + +When used for expectation data, manifests have the following format: + + * A section per test URL described by the manifest, with the section + heading being the part of the test URL following the last ``/`` in + the path (this allows multiple tests in a single manifest file with + the same path part of the URL, but different query parts). + + * A subsection per subtest, with the heading being the title of the + subtest. + + * A key ``type`` indicating the test type. This takes the values + ``testharness`` and ``reftest``. + + * For reftests, keys ``reftype`` indicating the reference type + (``==`` or ``!=``) and ``refurl`` indicating the URL of the + reference. + + * A key ``expected`` giving the expectation value of each (sub)test. + + * A key ``disabled`` which can be set to any value to indicate that + the (sub)test is disabled and should either not be run (for tests) + or that its results should be ignored (subtests). + + * A key ``restart-after`` which can be set to any value to indicate that + the runner should restart the browser after running this test (e.g. to + clear out unwanted state). + + * Variables ``debug``, ``os``, ``version``, ``processor`` and + ``bits`` that describe the configuration of the browser under + test. ``debug`` is a boolean indicating whether a build is a debug + build. ``os`` is a string indicating the operating system, and + ``version`` a string indicating the particular version of that + operating system. ``processor`` is a string indicating the + processor architecture and ``bits`` an integer indicating the + number of bits. This information is typically provided by + :py:mod:`mozinfo`. + + * Top level keys are taken as defaults for the whole file. So, for + example, a top level key with ``expected: FAIL`` would indicate + that all tests and subtests in the file are expected to fail, + unless they have an ``expected`` key of their own. + +An simple example manifest might look like:: + + [test.html?variant=basic] + type: testharness + + [Test something unsupported] + expected: FAIL + + [test.html?variant=broken] + expected: ERROR + + [test.html?variant=unstable] + disabled: http://test.bugs.example.org/bugs/12345 + +A more complex manifest with conditional properties might be:: + + [canvas_test.html] + expected: + if os == "osx": FAIL + if os == "windows" and version == "XP": FAIL + PASS + +Note that ``PASS`` in the above works, but is unnecessary; ``PASS`` +(or ``OK``) is always the default expectation for (sub)tests. diff --git a/testing/web-platform/tests/tools/wptrunner/docs/index.rst b/testing/web-platform/tests/tools/wptrunner/docs/index.rst new file mode 100644 index 000000000000..5147d3e31c3b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/docs/index.rst @@ -0,0 +1,24 @@ +.. wptrunner documentation master file, created by + sphinx-quickstart on Mon May 19 18:14:20 2014. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to wptrunner's documentation! +===================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + usage + expectation + design + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/testing/web-platform/tests/tools/wptrunner/docs/make.bat b/testing/web-platform/tests/tools/wptrunner/docs/make.bat new file mode 100644 index 000000000000..959c1615a289 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/docs/make.bat @@ -0,0 +1,242 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :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. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\wptrunner.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\wptrunner.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/testing/web-platform/tests/tools/wptrunner/docs/usage.rst b/testing/web-platform/tests/tools/wptrunner/docs/usage.rst new file mode 100644 index 000000000000..8e74a4320c82 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/docs/usage.rst @@ -0,0 +1,238 @@ +Getting Started +=============== + +Installing wptrunner +-------------------- + +The easiest way to install wptrunner is into a virtualenv, using pip:: + + virtualenv wptrunner + cd wptrunner + source bin/activate + pip install wptrunner + +This will install the base dependencies for wptrunner, but not any +extra dependencies required to test against specific browsers. In +order to do this you must use use the extra requirements files in +``$VIRTUAL_ENV/requirements/requirements_browser.txt``. For example, +in order to test against Firefox you would have to run:: + + pip install -r requirements/requirements_firefox.txt + +If you intend to work on the code, the ``-e`` option to pip should be +used in combination with a source checkout i.e. inside a virtual +environment created as above:: + + git clone https://github.com/w3c/wptrunner.git + cd wptrunner + pip install -e ./ + +In addition to the dependencies installed by pip, wptrunner requires +a copy of the web-platform-tests repository. This can be located +anywhere on the filesystem, but the easiest option is to put it +under the same parent directory as the wptrunner checkout:: + + git clone https://github.com/w3c/web-platform-tests.git + +It is also necessary to generate a web-platform-tests ``MANIFEST.json`` +file. It's recommended to also put that under the same parent directory as +the wptrunner checkout, in a directory named ``meta``:: + + mkdir meta + cd web-platform-tests + python manifest --path ../meta/MANIFEST.json + +The ``MANIFEST.json`` file needs to be regenerated each time the +web-platform-tests checkout is updated. To aid with the update process +there is a tool called ``wptupdate``, which is described in +:ref:`wptupdate-label`. + +Running the Tests +----------------- + +A test run is started using the ``wptrunner`` command. The command +takes multiple options, of which the following are most significant: + +``--product`` (defaults to `firefox`) + The product to test against: `b2g`, `chrome`, `firefox`, or `servo`. + +``--binary`` (required if product is `firefox` or `servo`) + The path to a binary file for the product (browser) to test against. + +``--webdriver-binary`` (required if product is `chrome`) + The path to a `*driver` binary; e.g., a `chromedriver` binary. + +``--certutil-binary`` (required if product is `firefox` [#]_) + The path to a `certutil` binary (for tests that must be run over https). + +``--metadata`` (required only when not `using default paths`_) + The path to a directory containing test metadata. [#]_ + +``--tests`` (required only when not `using default paths`_) + The path to a directory containing a web-platform-tests checkout. + +``--prefs-root`` (required only when testing a Firefox binary) + The path to a directory containing Firefox test-harness preferences. [#]_ + +``--config`` (should default to `wptrunner.default.ini`) + The path to the config (ini) file. + +.. [#] The ``--certutil-binary`` option is required when the product is + ``firefox`` unless ``--ssl-type=none`` is specified. + +.. [#] The ``--metadata`` path is to a directory that contains: + + * a ``MANIFEST.json`` file (the web-platform-tests documentation has + instructions on generating this file) + * (optionally) any expectation files (see :ref:`wptupdate-label`) + +.. [#] Example ``--prefs-root`` value: ``~/mozilla-central/testing/profiles``. + +There are also a variety of other command-line options available; use +``--help`` to list them. + +The following examples show how to start wptrunner with various options. + +------------------ +Starting wptrunner +------------------ + +The examples below assume the following directory layout, +though no specific folder structure is required:: + + ~/testtwf/wptrunner # wptrunner checkout + ~/testtwf/web-platform-tests # web-platform-tests checkout + ~/testtwf/meta # metadata + +To test a Firefox Nightly build in an OS X environment, you might start +wptrunner using something similar to the following example:: + + wptrunner --metadata=~/testtwf/meta/ --tests=~/testtwf/web-platform-tests/ \ + --binary=~/mozilla-central/obj-x86_64-apple-darwin14.3.0/dist/Nightly.app/Contents/MacOS/firefox \ + --certutil-binary=~/mozilla-central/obj-x86_64-apple-darwin14.3.0/security/nss/cmd/certutil/certutil \ + --prefs-root=~/mozilla-central/testing/profiles + + +And to test a Chromium build in an OS X environment, you might start +wptrunner using something similar to the following example:: + + wptrunner --metadata=~/testtwf/meta/ --tests=~/testtwf/web-platform-tests/ \ + --binary=~/chromium/src/out/Release/Chromium.app/Contents/MacOS/Chromium \ + --webdriver-binary=/usr/local/bin/chromedriver --product=chrome + +-------------------- +Running test subsets +-------------------- + +To restrict a test run just to tests in a particular web-platform-tests +subdirectory, specify the directory name in the positional arguments after +the options; for example, run just the tests in the `dom` subdirectory:: + + wptrunner --metadata=~/testtwf/meta --tests=~/testtwf/web-platform-tests/ \ + --binary=/path/to/firefox --certutil-binary=/path/to/certutil \ + --prefs-root=/path/to/testing/profiles \ + dom + +------------------- +Running in parallel +------------------- + +To speed up the testing process, use the ``--processes`` option to have +wptrunner run multiple browser instances in parallel. For example, to +have wptrunner attempt to run tests against with six browser instances +in parallel, specify ``--processes=6``. But note that behaviour in this +mode is necessarily less deterministic than with ``--processes=1`` (the +default), so there may be more noise in the test results. + +------------------- +Using default paths +------------------- + +The (otherwise-required) ``--tests`` and ``--metadata`` command-line +options/flags be omitted if any configuration file is found that +contains a section specifying the ``tests`` and ``metadata`` keys. + +See the `Configuration File`_ section for more information about +configuration files, including information about their expected +locations. + +The content of the ``wptrunner.default.ini`` default configuration file +makes wptrunner look for tests (that is, a web-platform-tests checkout) +as a subdirectory of the current directory named ``tests``, and for +metadata files in a subdirectory of the current directory named ``meta``. + +Output +------ + +wptrunner uses the :py:mod:`mozlog` package for output. This +structures events such as test results or log messages as JSON objects +that can then be fed to other tools for interpretation. More details +about the message format are given in the +:py:mod:`mozlog` documentation. + +By default the raw JSON messages are dumped to stdout. This is +convenient for piping into other tools, but not ideal for humans +reading the output. :py:mod:`mozlog` comes with several other +formatters, which are accessible through command line options. The +general format of these options is ``--log-name=dest``, where ``name`` +is the name of the format and ``dest`` is a path to a destination +file, or ``-`` for stdout. The raw JSON data is written by the ``raw`` +formatter so, the default setup corresponds to ``--log-raw=-``. + +A reasonable output format for humans is provided as ``mach``. So in +order to output the full raw log to a file and a human-readable +summary to stdout, one might pass the options:: + + --log-raw=output.log --log-mach=- + +Configuration File +------------------ + +wptrunner uses a ``.ini`` file to control some configuration +sections. The file has three sections; ``[products]``, +``[manifest:default]`` and ``[web-platform-tests]``. + +``[products]`` is used to +define the set of available products. By default this section is empty +which means that all the products distributed with wptrunner are +enabled (although their dependencies may not be installed). The set +of enabled products can be set by using the product name as the +key. For built in products the value is empty. It is also possible to +provide the path to a script implementing the browser functionality +e.g.:: + + [products] + chrome = + netscape4 = path/to/netscape.py + +``[manifest:default]`` specifies the default paths for the tests and metadata, +relative to the config file. For example:: + + [manifest:default] + tests = ~/testtwf/web-platform-tests + metadata = ~/testtwf/meta + + +``[web-platform-tests]`` is used to set the properties of the upstream +repository when updating the paths. ``remote_url`` specifies the git +url to pull from; ``branch`` the branch to sync against and +``sync_path`` the local path, relative to the configuration file, to +use when checking out the tests e.g.:: + + [web-platform-tests] + remote_url = https://github.com/w3c/web-platform-tests.git + branch = master + sync_path = sync + +A configuration file must contain all the above fields; falling back +to the default values for unspecified fields is not yet supported. + +The ``wptrunner`` and ``wptupdate`` commands will use configuration +files in the following order: + + * Any path supplied with a ``--config`` flag to the command. + + * A file called ``wptrunner.ini`` in the current directory + + * The default configuration file (``wptrunner.default.ini`` in the + source directory) diff --git a/testing/web-platform/tests/tools/wptrunner/requirements.txt b/testing/web-platform/tests/tools/wptrunner/requirements.txt new file mode 100644 index 000000000000..319a2ff984aa --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/requirements.txt @@ -0,0 +1,4 @@ +html5lib >= 0.99 +mozinfo >= 0.7 +mozlog >= 3.3 +mozdebug >= 0.1 diff --git a/testing/web-platform/tests/tools/wptrunner/requirements_chrome.txt b/testing/web-platform/tests/tools/wptrunner/requirements_chrome.txt new file mode 100644 index 000000000000..a2f54425f3ef --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/requirements_chrome.txt @@ -0,0 +1,2 @@ +mozprocess >= 0.19 +selenium >= 2.41.0 diff --git a/testing/web-platform/tests/tools/wptrunner/requirements_firefox.txt b/testing/web-platform/tests/tools/wptrunner/requirements_firefox.txt new file mode 100644 index 000000000000..379e522acc45 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/requirements_firefox.txt @@ -0,0 +1,5 @@ +marionette_driver >= 0.4 +mozprofile >= 0.21 +mozprocess >= 0.19 +mozcrash >= 0.13 +mozrunner >= 6.7 diff --git a/testing/web-platform/tests/tools/wptrunner/requirements_sauce.txt b/testing/web-platform/tests/tools/wptrunner/requirements_sauce.txt new file mode 100644 index 000000000000..7b828f84b08d --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/requirements_sauce.txt @@ -0,0 +1,2 @@ +mozprocess >= 0.19 +selenium >= 3.3.0 diff --git a/testing/web-platform/tests/tools/wptrunner/requirements_servo.txt b/testing/web-platform/tests/tools/wptrunner/requirements_servo.txt new file mode 100644 index 000000000000..22bcfa123a54 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/requirements_servo.txt @@ -0,0 +1 @@ +mozprocess >= 0.19 diff --git a/testing/web-platform/tests/tools/wptrunner/setup.py b/testing/web-platform/tests/tools/wptrunner/setup.py new file mode 100644 index 000000000000..7ec189fefd9a --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/setup.py @@ -0,0 +1,74 @@ +# 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 glob +import os +import sys +import textwrap + +from setuptools import setup, find_packages + +here = os.path.split(__file__)[0] + +PACKAGE_NAME = 'wptrunner' +PACKAGE_VERSION = '1.14' + +# Dependencies +with open(os.path.join(here, "requirements.txt")) as f: + deps = f.read().splitlines() + +# Browser-specific requirements +requirements_files = glob.glob("requirements_*.txt") + +profile_dest = None +dest_exists = False + +setup(name=PACKAGE_NAME, + version=PACKAGE_VERSION, + description="Harness for running the W3C web-platform-tests against various products", + author='Mozilla Automation and Testing Team', + author_email='tools@lists.mozilla.org', + license='MPL 2.0', + packages=find_packages(exclude=["tests", "metadata", "prefs"]), + entry_points={ + 'console_scripts': [ + 'wptrunner = wptrunner.wptrunner:main', + 'wptupdate = wptrunner.update:main', + ] + }, + zip_safe=False, + platforms=['Any'], + classifiers=['Development Status :: 4 - Beta', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: BSD License', + 'Operating System :: OS Independent'], + package_data={"wptrunner": ["executors/testharness_marionette.js", + "executors/testharness_webdriver.js", + "executors/reftest.js", + "executors/reftest-wait.js", + "testharnessreport.js", + "testharness_runner.html", + "config.json", + "wptrunner.default.ini", + "browsers/server-locations.txt", + "browsers/b2g_setup/*", + "browsers/sauce_setup/*", + "prefs/*"]}, + include_package_data=True, + data_files=[("requirements", requirements_files)], + install_requires=deps + ) + +if "install" in sys.argv: + path = os.path.relpath(os.path.join(sys.prefix, "requirements"), os.curdir) + print textwrap.fill("""In order to use with one of the built-in browser +products, you will need to install the extra dependencies. These are provided +as requirements_[name].txt in the %s directory and can be installed using +e.g.""" % path, 80) + + print """ + +pip install -r %s/requirements_firefox.txt +""" % path diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_and_fail.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_and_fail.html.ini new file mode 100644 index 000000000000..81aef049cd12 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_and_fail.html.ini @@ -0,0 +1,3 @@ +[reftest_and_fail.html] + type: reftest + expected: FAIL diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_cycle_fail.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_cycle_fail.html.ini new file mode 100644 index 000000000000..472b33f7764b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_cycle_fail.html.ini @@ -0,0 +1,3 @@ +[reftest_cycle_fail.html] + type: reftest + expected: FAIL diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_match_fail.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_match_fail.html.ini new file mode 100644 index 000000000000..f3dc3362fac4 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_match_fail.html.ini @@ -0,0 +1,3 @@ +[reftest_match_fail.html] + type: reftest + expected: FAIL diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_mismatch_fail.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_mismatch_fail.html.ini new file mode 100644 index 000000000000..1055337e2d65 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_mismatch_fail.html.ini @@ -0,0 +1,3 @@ +[reftest_mismatch_fail.html] + type: reftest + expected: FAIL diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_ref_timeout.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_ref_timeout.html.ini new file mode 100644 index 000000000000..8936241ad29c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_ref_timeout.html.ini @@ -0,0 +1,3 @@ +[reftest_ref_timeout.html] + type: reftest + expected: TIMEOUT diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_timeout.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_timeout.html.ini new file mode 100644 index 000000000000..0d1b9bade95d --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/reftest/reftest_timeout.html.ini @@ -0,0 +1,3 @@ +[reftest_timeout.html] + type: reftest + expected: TIMEOUT diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/firefox/__dir__.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/firefox/__dir__.ini new file mode 100644 index 000000000000..c9d164cd418a --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/firefox/__dir__.ini @@ -0,0 +1,2 @@ +prefs: ["browser.display.foreground_color:#FF0000", + "browser.display.background_color:#000000"] \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/firefox/subdir/test_pref_reset.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/firefox/subdir/test_pref_reset.html.ini new file mode 100644 index 000000000000..6c9198d9bbf1 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/firefox/subdir/test_pref_reset.html.ini @@ -0,0 +1,2 @@ +[test_pref_reset.html] + prefs: [@Reset] diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/firefox/test_pref_set.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/firefox/test_pref_set.html.ini new file mode 100644 index 000000000000..bc9bfb9c4139 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/firefox/test_pref_set.html.ini @@ -0,0 +1,3 @@ +[test_pref_set.html] + prefs: ["browser.display.foreground_color:#00FF00", + "browser.display.background_color:#000000"] diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/subdir/__dir__.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/subdir/__dir__.ini new file mode 100644 index 000000000000..a9157fbc6a9f --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/subdir/__dir__.ini @@ -0,0 +1 @@ +disabled: true \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/subdir/testharness_1.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/subdir/testharness_1.html.ini new file mode 100644 index 000000000000..db9393987b6c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/subdir/testharness_1.html.ini @@ -0,0 +1,2 @@ +[testharness_1.html] + disabled: @False \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/testharness_0.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/testharness_0.html.ini new file mode 100644 index 000000000000..90b9a6e9f012 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/testharness_0.html.ini @@ -0,0 +1,4 @@ +[testharness_0.html] + type: testharness + [Test that should fail] + expected: FAIL diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/testharness_error.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/testharness_error.html.ini new file mode 100644 index 000000000000..fa53e0733abc --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/testharness_error.html.ini @@ -0,0 +1,3 @@ +[testharness_error.html] + type: testharness + expected: ERROR diff --git a/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/testharness_timeout.html.ini b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/testharness_timeout.html.ini new file mode 100644 index 000000000000..55eca5191ab1 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/metadata/testharness/testharness_timeout.html.ini @@ -0,0 +1,3 @@ +[testharness_timeout.html] + type: testharness + expected: TIMEOUT diff --git a/testing/web-platform/tests/tools/wptrunner/test/test.cfg.example b/testing/web-platform/tests/tools/wptrunner/test/test.cfg.example new file mode 100644 index 000000000000..db48226216c3 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/test.cfg.example @@ -0,0 +1,20 @@ +[general] +tests=/path/to/web-platform-tests/ +metadata=/path/to/web-platform-tests/ +ssl-type=none + +# [firefox] +# binary=/path/to/firefox +# prefs-root=/path/to/gecko-src/testing/profiles/ + +# [servo] +# binary=/path/to/servo-src/target/release/servo +# exclude=testharness # Because it needs a special testharness.js + +# [servodriver] +# binary=/path/to/servo-src/target/release/servo +# exclude=testharness # Because it needs a special testharness.js + +# [chrome] +# binary=/path/to/chrome +# webdriver-binary=/path/to/chromedriver diff --git a/testing/web-platform/tests/tools/wptrunner/test/test.py b/testing/web-platform/tests/tools/wptrunner/test/test.py new file mode 100644 index 000000000000..034e317bd52f --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/test.py @@ -0,0 +1,166 @@ +import ConfigParser +import argparse +import json +import os +import sys +import tempfile +import threading +import time +from StringIO import StringIO + +from mozlog import structuredlog, reader +from mozlog.handlers import BaseHandler, StreamHandler, StatusHandler +from mozlog.formatters import MachFormatter +from wptrunner import wptcommandline, wptrunner + +here = os.path.abspath(os.path.dirname(__file__)) + +def setup_wptrunner_logging(logger): + structuredlog.set_default_logger(logger) + wptrunner.logger = logger + wptrunner.wptlogging.setup_stdlib_logger() + +class ResultHandler(BaseHandler): + def __init__(self, verbose=False, logger=None): + self.inner = StreamHandler(sys.stdout, MachFormatter()) + BaseHandler.__init__(self, self.inner) + self.product = None + self.verbose = verbose + self.logger = logger + + self.register_message_handlers("wptrunner-test", {"set-product": self.set_product}) + + def set_product(self, product): + self.product = product + + def __call__(self, data): + if self.product is not None and data["action"] in ["suite_start", "suite_end"]: + # Hack: mozlog sets some internal state to prevent multiple suite_start or + # suite_end messages. We actually want that here (one from the metaharness + # and one from the individual test type harness), so override that internal + # state (a better solution might be to not share loggers, but this works well + # enough) + self.logger._state.suite_started = True + return + + if (not self.verbose and + (data["action"] == "process_output" or + data["action"] == "log" and data["level"] not in ["error", "critical"])): + return + + if "test" in data: + data = data.copy() + data["test"] = "%s: %s" % (self.product, data["test"]) + + return self.inner(data) + +def test_settings(): + return { + "include": "_test", + "manifest-update": "", + "no-capture-stdio": "" + } + +def read_config(): + parser = ConfigParser.ConfigParser() + parser.read("test.cfg") + + rv = {"general":{}, + "products":{}} + + rv["general"].update(dict(parser.items("general"))) + + # This only allows one product per whatever for now + for product in parser.sections(): + if product != "general": + dest = rv["products"][product] = {} + for key, value in parser.items(product): + rv["products"][product][key] = value + + return rv + +def run_tests(product, kwargs): + kwargs["test_paths"]["/_test/"] = {"tests_path": os.path.join(here, "testdata"), + "metadata_path": os.path.join(here, "metadata")} + + wptrunner.run_tests(**kwargs) + +def settings_to_argv(settings): + rv = [] + for name, value in settings.iteritems(): + key = "--%s" % name + if not value: + rv.append(key) + elif isinstance(value, list): + for item in value: + rv.extend([key, item]) + else: + rv.extend([key, value]) + return rv + +def set_from_args(settings, args): + if args.test: + settings["include"] = args.test + if args.tags: + settings["tags"] = args.tags + +def run(config, args): + logger = structuredlog.StructuredLogger("web-platform-tests") + logger.add_handler(ResultHandler(logger=logger, verbose=args.verbose)) + setup_wptrunner_logging(logger) + + parser = wptcommandline.create_parser() + + logger.suite_start(tests=[]) + + for product, product_settings in config["products"].iteritems(): + if args.product and product not in args.product: + continue + + settings = test_settings() + settings.update(config["general"]) + settings.update(product_settings) + settings["product"] = product + set_from_args(settings, args) + + kwargs = vars(parser.parse_args(settings_to_argv(settings))) + wptcommandline.check_args(kwargs) + + logger.send_message("wptrunner-test", "set-product", product) + + run_tests(product, kwargs) + + logger.send_message("wptrunner-test", "set-product", None) + logger.suite_end() + +def get_parser(): + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--verbose", action="store_true", default=False, + help="verbose log output") + parser.add_argument("--product", action="append", + help="Specific product to include in test run") + parser.add_argument("--pdb", action="store_true", + help="Invoke pdb on uncaught exception") + parser.add_argument("--tag", action="append", dest="tags", + help="tags to select tests") + parser.add_argument("test", nargs="*", + help="Specific tests to include in test run") + return parser + +def main(): + config = read_config() + + args = get_parser().parse_args() + + try: + run(config, args) + except Exception: + if args.pdb: + import pdb, traceback + print traceback.format_exc() + pdb.post_mortem() + else: + raise + +if __name__ == "__main__": + main() diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/green-ref.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/green-ref.html new file mode 100644 index 000000000000..0e145d60b55b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/green-ref.html @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/green.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/green.html new file mode 100644 index 000000000000..38167bb58d57 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/green.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/red.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/red.html new file mode 100644 index 000000000000..2b677e00634b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/red.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest.https.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest.https.html new file mode 100644 index 000000000000..5a45f10f35eb --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest.https.html @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_and_fail.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_and_fail.html new file mode 100644 index 000000000000..296019535623 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_and_fail.html @@ -0,0 +1,5 @@ +Reftest chain that should fail + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_and_fail_0-ref.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_and_fail_0-ref.html new file mode 100644 index 000000000000..04fb9aa15176 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_and_fail_0-ref.html @@ -0,0 +1,5 @@ +Reftest chain that should fail + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle.html new file mode 100644 index 000000000000..4a84a3b6741e --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle.html @@ -0,0 +1,5 @@ +Reftest with cycle, all match + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_0-ref.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_0-ref.html new file mode 100644 index 000000000000..118bfd88447b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_0-ref.html @@ -0,0 +1,5 @@ +OR match that should pass + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_1-ref.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_1-ref.html new file mode 100644 index 000000000000..59be0b641def --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_1-ref.html @@ -0,0 +1,5 @@ +Reftest with cycle, all match + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_fail.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_fail.html new file mode 100644 index 000000000000..175e76c4cc9b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_fail.html @@ -0,0 +1,5 @@ +Reftest with cycle, fails + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_fail_0-ref.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_fail_0-ref.html new file mode 100644 index 000000000000..c8e548c46225 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_cycle_fail_0-ref.html @@ -0,0 +1,5 @@ +Reftest with cycle, fails + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_match.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_match.html new file mode 100644 index 000000000000..333cc6c1ecdf --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_match.html @@ -0,0 +1,5 @@ +rel=match that should pass + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_match_fail.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_match_fail.html new file mode 100644 index 000000000000..a9272ef74da8 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_match_fail.html @@ -0,0 +1,5 @@ +rel=match that should fail + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_mismatch.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_mismatch.html new file mode 100644 index 000000000000..af5fa0750d83 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_mismatch.html @@ -0,0 +1,5 @@ +rel=mismatch that should pass + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_mismatch_fail.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_mismatch_fail.html new file mode 100644 index 000000000000..8d160c4fc200 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_mismatch_fail.html @@ -0,0 +1,5 @@ +rel=mismatch that should fail + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_or_0.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_or_0.html new file mode 100644 index 000000000000..3a51de216441 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_or_0.html @@ -0,0 +1,6 @@ +OR match that should pass + + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_ref_timeout-ref.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_ref_timeout-ref.html new file mode 100644 index 000000000000..04cbb71e0c3c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_ref_timeout-ref.html @@ -0,0 +1,6 @@ + +rel=match that should time out in the ref + + diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_ref_timeout.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_ref_timeout.html new file mode 100644 index 000000000000..aaf68f5cb5fa --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_ref_timeout.html @@ -0,0 +1,6 @@ + +rel=match that should time out in the ref + + diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_timeout.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_timeout.html new file mode 100644 index 000000000000..b10e676bf005 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_timeout.html @@ -0,0 +1,6 @@ + +rel=match that should timeout + + diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_wait_0.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_wait_0.html new file mode 100644 index 000000000000..4f92715c61e7 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/reftest/reftest_wait_0.html @@ -0,0 +1,13 @@ + +rel=match that should fail + + + + diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/subdir/test_pref_inherit.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/subdir/test_pref_inherit.html new file mode 100644 index 000000000000..10b285194b4a --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/subdir/test_pref_inherit.html @@ -0,0 +1,10 @@ + +Example pref test + + +

Test requires the pref browser.display.foreground_color to be set to #00FF00

+ diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/subdir/test_pref_reset.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/subdir/test_pref_reset.html new file mode 100644 index 000000000000..5c75c1160522 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/subdir/test_pref_reset.html @@ -0,0 +1,10 @@ + +Example pref test + + +

Test requires the pref browser.display.foreground_color to be set to #00FF00

+ diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/test_pref_dir.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/test_pref_dir.html new file mode 100644 index 000000000000..105d9070c9dc --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/test_pref_dir.html @@ -0,0 +1,10 @@ + +Example pref test + + +

Test requires the pref browser.display.foreground_color to be set to #FF0000

+ diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/test_pref_set.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/test_pref_set.html new file mode 100644 index 000000000000..8e5e2989bf72 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/firefox/test_pref_set.html @@ -0,0 +1,10 @@ + +Example pref test + + +

Test requires the pref browser.display.foreground_color to be set to #00FF00

+ diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/subdir/testharness_1.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/subdir/testharness_1.html new file mode 100644 index 000000000000..fd2fc431d399 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/subdir/testharness_1.html @@ -0,0 +1,9 @@ + +Test should be enabled + + + diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness.https.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness.https.html new file mode 100644 index 000000000000..5871eac00148 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness.https.html @@ -0,0 +1,10 @@ + +Example https test + + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_0.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_0.html new file mode 100644 index 000000000000..ff0654cb9a09 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_0.html @@ -0,0 +1,9 @@ + +Test should be disabled + + + diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_error.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_error.html new file mode 100644 index 000000000000..0ac5ba46a330 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_error.html @@ -0,0 +1,7 @@ + +testharness.js test that should error + + + diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_long_timeout.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_long_timeout.html new file mode 100644 index 000000000000..fc94e055be0c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_long_timeout.html @@ -0,0 +1,9 @@ + +testharness.js test with long timeout + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_timeout.html b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_timeout.html new file mode 100644 index 000000000000..b99915ac7453 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/test/testdata/testharness/testharness_timeout.html @@ -0,0 +1,6 @@ + +Simple testharness.js usage + + + +// This file should time out, obviously \ No newline at end of file diff --git a/testing/web-platform/tests/tools/wptrunner/tox.ini b/testing/web-platform/tests/tools/wptrunner/tox.ini new file mode 100644 index 000000000000..88dfe79dc5d1 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/tox.ini @@ -0,0 +1,16 @@ +[pytest] +xfail_strict=true + +[tox] +envlist = {py27,pypy}-{base,b2g,chrome,firefox,servo} + +[testenv] +deps = + pytest>=2.9 + pytest-cov + -r{toxinidir}/requirements.txt + chrome: -r{toxinidir}/requirements_chrome.txt + firefox: -r{toxinidir}/requirements_firefox.txt + servo: -r{toxinidir}/requirements_servo.txt + +commands = pytest --cov diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner.default.ini b/testing/web-platform/tests/tools/wptrunner/wptrunner.default.ini new file mode 100644 index 000000000000..34d25f8056b0 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner.default.ini @@ -0,0 +1,11 @@ +[products] + +[web-platform-tests] +remote_url = https://github.com/w3c/web-platform-tests.git +branch = master +sync_path = %(pwd)s/sync + +[manifest:default] +tests = %(pwd)s/tests +metadata = %(pwd)s/meta +url_base = / \ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key1_dashinit.mp4 b/testing/web-platform/tests/tools/wptrunner/wptrunner/__init__.py similarity index 100% rename from testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key1_dashinit.mp4 rename to testing/web-platform/tests/tools/wptrunner/wptrunner/__init__.py diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/__init__.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/__init__.py new file mode 100644 index 000000000000..e3606d23cf0c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/__init__.py @@ -0,0 +1,30 @@ +"""Subpackage where each product is defined. Each product is created by adding a +a .py file containing a __wptrunner__ variable in the global scope. This must be +a dictionary with the fields + +"product": Name of the product, assumed to be unique. +"browser": String indicating the Browser implementation used to launch that + product. +"executor": Dictionary with keys as supported test types and values as the name + of the Executor implemantation that will be used to run that test + type. +"browser_kwargs": String naming function that takes product, binary, + prefs_root and the wptrunner.run_tests kwargs dict as arguments + and returns a dictionary of kwargs to use when creating the + Browser class. +"executor_kwargs": String naming a function that takes http server url and + timeout multiplier and returns kwargs to use when creating + the executor class. +"env_options": String naming a funtion of no arguments that returns the + arguments passed to the TestEnvironment. + +All classes and functions named in the above dict must be imported into the +module global scope. +""" + +product_list = ["chrome", + "edge", + "firefox", + "sauce", + "servo", + "servodriver"] diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/b2g_setup/certtest_app.zip b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/b2g_setup/certtest_app.zip new file mode 100644 index 000000000000..f9cbd5300ad6 Binary files /dev/null and b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/b2g_setup/certtest_app.zip differ diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/base.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/base.py new file mode 100644 index 000000000000..583ca0d6cded --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/base.py @@ -0,0 +1,159 @@ +import os +import platform +import socket +from abc import ABCMeta, abstractmethod + +from ..wptcommandline import require_arg + +here = os.path.split(__file__)[0] + + +def cmd_arg(name, value=None): + prefix = "-" if platform.system() == "Windows" else "--" + rv = prefix + name + if value is not None: + rv += "=" + value + return rv + + +def get_free_port(start_port, exclude=None): + """Get the first port number after start_port (inclusive) that is + not currently bound. + + :param start_port: Integer port number at which to start testing. + :param exclude: Set of port numbers to skip""" + port = start_port + while True: + if exclude and port in exclude: + port += 1 + continue + s = socket.socket() + try: + s.bind(("127.0.0.1", port)) + except socket.error: + port += 1 + else: + return port + finally: + s.close() + +def browser_command(binary, args, debug_info): + if debug_info: + if debug_info.requiresEscapedArgs: + args = [item.replace("&", "\\&") for item in args] + debug_args = [debug_info.path] + debug_info.args + else: + debug_args = [] + + command = [binary] + args + + return debug_args, command + + +class BrowserError(Exception): + pass + + +class Browser(object): + __metaclass__ = ABCMeta + + process_cls = None + init_timeout = 30 + + def __init__(self, logger): + """Abstract class serving as the basis for Browser implementations. + + The Browser is used in the TestRunnerManager to start and stop the browser + process, and to check the state of that process. This class also acts as a + context manager, enabling it to do browser-specific setup at the start of + the testrun and cleanup after the run is complete. + + :param logger: Structured logger to use for output. + """ + self.logger = logger + + def __enter__(self): + self.setup() + return self + + def __exit__(self, *args, **kwargs): + self.cleanup() + + def setup(self): + """Used for browser-specific setup that happens at the start of a test run""" + pass + + @abstractmethod + def start(self): + """Launch the browser object and get it into a state where is is ready to run tests""" + pass + + @abstractmethod + def stop(self, force=False): + """Stop the running browser process.""" + pass + + @abstractmethod + def pid(self): + """pid of the browser process or None if there is no pid""" + pass + + @abstractmethod + def is_alive(self): + """Boolean indicating whether the browser process is still running""" + pass + + def setup_ssl(self, hosts): + """Return a certificate to use for tests requiring ssl that will be trusted by the browser""" + raise NotImplementedError("ssl testing not supported") + + def cleanup(self): + """Browser-specific cleanup that is run after the testrun is finished""" + pass + + def executor_browser(self): + """Returns the ExecutorBrowser subclass for this Browser subclass and the keyword arguments + with which it should be instantiated""" + return ExecutorBrowser, {} + + def log_crash(self, process, test): + """Return a list of dictionaries containing information about crashes that happend + in the browser, or an empty list if no crashes occurred""" + self.logger.crash(process, test) + + +class NullBrowser(Browser): + def __init__(self, logger, **kwargs): + super(NullBrowser, self).__init__(logger) + + def start(self): + """No-op browser to use in scenarios where the TestRunnerManager shouldn't + actually own the browser process (e.g. Servo where we start one browser + per test)""" + pass + + def stop(self, force=False): + pass + + def pid(self): + return None + + def is_alive(self): + return True + + def on_output(self, line): + raise NotImplementedError + + +class ExecutorBrowser(object): + def __init__(self, **kwargs): + """View of the Browser used by the Executor object. + This is needed because the Executor runs in a child process and + we can't ship Browser instances between processes on Windows. + + Typically this will have a few product-specific properties set, + but in some cases it may have more elaborate methods for setting + up the browser from the runner process. + """ + for k, v in kwargs.iteritems(): + setattr(self, k, v) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/chrome.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/chrome.py new file mode 100644 index 000000000000..3bd227b32f55 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/chrome.py @@ -0,0 +1,94 @@ +from .base import Browser, ExecutorBrowser, require_arg +from ..webdriver_server import ChromeDriverServer +from ..executors import executor_kwargs as base_executor_kwargs +from ..executors.executorselenium import (SeleniumTestharnessExecutor, + SeleniumRefTestExecutor) + + +__wptrunner__ = {"product": "chrome", + "check_args": "check_args", + "browser": "ChromeBrowser", + "executor": {"testharness": "SeleniumTestharnessExecutor", + "reftest": "SeleniumRefTestExecutor"}, + "browser_kwargs": "browser_kwargs", + "executor_kwargs": "executor_kwargs", + "env_extras": "env_extras", + "env_options": "env_options"} + + +def check_args(**kwargs): + require_arg(kwargs, "webdriver_binary") + + +def browser_kwargs(**kwargs): + return {"binary": kwargs["binary"], + "webdriver_binary": kwargs["webdriver_binary"], + "webdriver_args": kwargs.get("webdriver_args")} + + +def executor_kwargs(test_type, server_config, cache_manager, run_info_data, + **kwargs): + from selenium.webdriver import DesiredCapabilities + + executor_kwargs = base_executor_kwargs(test_type, server_config, + cache_manager, **kwargs) + executor_kwargs["close_after_done"] = True + capabilities = dict(DesiredCapabilities.CHROME.items()) + capabilities.setdefault("chromeOptions", {})["prefs"] = { + "profile": { + "default_content_setting_values": { + "popups": 1 + } + } + } + for (kwarg, capability) in [("binary", "binary"), ("binary_args", "args")]: + if kwargs[kwarg] is not None: + capabilities["chromeOptions"][capability] = kwargs[kwarg] + executor_kwargs["capabilities"] = capabilities + return executor_kwargs + + +def env_extras(**kwargs): + return [] + + +def env_options(): + return {"host": "web-platform.test", + "bind_hostname": "true"} + + +class ChromeBrowser(Browser): + """Chrome is backed by chromedriver, which is supplied through + ``wptrunner.webdriver.ChromeDriverServer``. + """ + + def __init__(self, logger, binary, webdriver_binary="chromedriver", + webdriver_args=None): + """Creates a new representation of Chrome. The `binary` argument gives + the browser binary to use for testing.""" + Browser.__init__(self, logger) + self.binary = binary + self.server = ChromeDriverServer(self.logger, + binary=webdriver_binary, + args=webdriver_args) + + def start(self): + self.server.start(block=False) + + def stop(self, force=False): + self.server.stop(force=force) + + def pid(self): + return self.server.pid + + def is_alive(self): + # TODO(ato): This only indicates the driver is alive, + # and doesn't say anything about whether a browser session + # is active. + return self.server.is_alive() + + def cleanup(self): + self.stop() + + def executor_browser(self): + return ExecutorBrowser, {"webdriver_url": self.server.url} diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/edge.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/edge.py new file mode 100644 index 000000000000..354edb3bab12 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/edge.py @@ -0,0 +1,74 @@ +from .base import Browser, ExecutorBrowser, require_arg +from ..webdriver_server import EdgeDriverServer +from ..executors import executor_kwargs as base_executor_kwargs +from ..executors.executorselenium import (SeleniumTestharnessExecutor, + SeleniumRefTestExecutor) + +__wptrunner__ = {"product": "edge", + "check_args": "check_args", + "browser": "EdgeBrowser", + "executor": {"testharness": "SeleniumTestharnessExecutor", + "reftest": "SeleniumRefTestExecutor"}, + "browser_kwargs": "browser_kwargs", + "executor_kwargs": "executor_kwargs", + "env_extras": "env_extras", + "env_options": "env_options"} + + +def check_args(**kwargs): + require_arg(kwargs, "webdriver_binary") + +def browser_kwargs(**kwargs): + return {"webdriver_binary": kwargs["webdriver_binary"], + "webdriver_args": kwargs.get("webdriver_args")} + +def executor_kwargs(test_type, server_config, cache_manager, run_info_data, + **kwargs): + from selenium.webdriver import DesiredCapabilities + + executor_kwargs = base_executor_kwargs(test_type, server_config, + cache_manager, **kwargs) + executor_kwargs["close_after_done"] = True + executor_kwargs["capabilities"] = dict(DesiredCapabilities.EDGE.items()) + return executor_kwargs + +def env_extras(**kwargs): + return [] + +def env_options(): + return {"host": "web-platform.test", + "bind_hostname": "true", + "supports_debugger": False} + +class EdgeBrowser(Browser): + used_ports = set() + + def __init__(self, logger, webdriver_binary, webdriver_args=None): + Browser.__init__(self, logger) + self.server = EdgeDriverServer(self.logger, + binary=webdriver_binary, + args=webdriver_args) + self.webdriver_host = "localhost" + self.webdriver_port = self.server.port + + def start(self): + print self.server.url + self.server.start() + + def stop(self): + self.server.stop() + + def pid(self): + return self.server.pid + + def is_alive(self): + # TODO(ato): This only indicates the server is alive, + # and doesn't say anything about whether a browser session + # is active. + return self.server.is_alive() + + def cleanup(self): + self.stop() + + def executor_browser(self): + return ExecutorBrowser, {"webdriver_url": self.server.url} diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py new file mode 100644 index 000000000000..7152fd7c1c20 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py @@ -0,0 +1,308 @@ +import os +import platform +import signal +import subprocess +import sys + +import mozinfo +from mozprocess import ProcessHandler +from mozprofile import FirefoxProfile, Preferences +from mozprofile.permissions import ServerLocations +from mozrunner import FirefoxRunner +from mozrunner.utils import get_stack_fixer_function +from mozcrash import mozcrash + +from .base import (get_free_port, + Browser, + ExecutorBrowser, + require_arg, + cmd_arg, + browser_command) +from ..executors import executor_kwargs as base_executor_kwargs +from ..executors.executormarionette import (MarionetteTestharnessExecutor, + MarionetteRefTestExecutor, + MarionetteWdspecExecutor) +from ..environment import hostnames + + +here = os.path.join(os.path.split(__file__)[0]) + +__wptrunner__ = {"product": "firefox", + "check_args": "check_args", + "browser": "FirefoxBrowser", + "executor": {"testharness": "MarionetteTestharnessExecutor", + "reftest": "MarionetteRefTestExecutor", + "wdspec": "MarionetteWdspecExecutor"}, + "browser_kwargs": "browser_kwargs", + "executor_kwargs": "executor_kwargs", + "env_extras": "env_extras", + "env_options": "env_options", + "run_info_extras": "run_info_extras", + "update_properties": "update_properties"} + + +def check_args(**kwargs): + require_arg(kwargs, "binary") + if kwargs["ssl_type"] != "none": + require_arg(kwargs, "certutil_binary") + + +def browser_kwargs(**kwargs): + return {"binary": kwargs["binary"], + "prefs_root": kwargs["prefs_root"], + "extra_prefs": kwargs["extra_prefs"], + "debug_info": kwargs["debug_info"], + "symbols_path": kwargs["symbols_path"], + "stackwalk_binary": kwargs["stackwalk_binary"], + "certutil_binary": kwargs["certutil_binary"], + "ca_certificate_path": kwargs["ssl_env"].ca_cert_path(), + "e10s": kwargs["gecko_e10s"], + "stackfix_dir": kwargs["stackfix_dir"], + "binary_args": kwargs["binary_args"]} + + +def executor_kwargs(test_type, server_config, cache_manager, run_info_data, + **kwargs): + executor_kwargs = base_executor_kwargs(test_type, server_config, + cache_manager, **kwargs) + executor_kwargs["close_after_done"] = test_type != "reftest" + if kwargs["timeout_multiplier"] is None: + if test_type == "reftest": + if run_info_data["debug"] or run_info_data.get("asan"): + executor_kwargs["timeout_multiplier"] = 4 + else: + executor_kwargs["timeout_multiplier"] = 2 + elif run_info_data["debug"] or run_info_data.get("asan"): + executor_kwargs["timeout_multiplier"] = 3 + if test_type == "wdspec": + executor_kwargs["binary"] = kwargs["binary"] + executor_kwargs["webdriver_binary"] = kwargs.get("webdriver_binary") + executor_kwargs["webdriver_args"] = kwargs.get("webdriver_args") + fxOptions = {} + if kwargs["binary"]: + fxOptions["binary"] = kwargs["binary"] + if kwargs["binary_args"]: + fxOptions["args"] = kwargs["binary_args"] + fxOptions["prefs"] = { + "network.dns.localDomains": ",".join(hostnames) + } + capabilities = {"moz:firefoxOptions": fxOptions} + executor_kwargs["capabilities"] = capabilities + return executor_kwargs + + +def env_extras(**kwargs): + return [] + + +def env_options(): + return {"host": "127.0.0.1", + "external_host": "web-platform.test", + "bind_hostname": "false", + "certificate_domain": "web-platform.test", + "supports_debugger": True} + + +def run_info_extras(**kwargs): + return {"e10s": kwargs["gecko_e10s"]} + + +def update_properties(): + return ["debug", "e10s", "os", "version", "processor", "bits"], {"debug", "e10s"} + + +class FirefoxBrowser(Browser): + used_ports = set() + init_timeout = 60 + shutdown_timeout = 60 + + def __init__(self, logger, binary, prefs_root, extra_prefs=None, debug_info=None, + symbols_path=None, stackwalk_binary=None, certutil_binary=None, + ca_certificate_path=None, e10s=False, stackfix_dir=None, + binary_args=None): + Browser.__init__(self, logger) + self.binary = binary + self.prefs_root = prefs_root + self.extra_prefs = extra_prefs + self.marionette_port = None + self.runner = None + self.debug_info = debug_info + self.profile = None + self.symbols_path = symbols_path + self.stackwalk_binary = stackwalk_binary + self.ca_certificate_path = ca_certificate_path + self.certutil_binary = certutil_binary + self.e10s = e10s + self.binary_args = binary_args + if self.symbols_path and stackfix_dir: + self.stack_fixer = get_stack_fixer_function(stackfix_dir, + self.symbols_path) + else: + self.stack_fixer = None + + def start(self): + self.marionette_port = get_free_port(2828, exclude=self.used_ports) + self.used_ports.add(self.marionette_port) + + env = os.environ.copy() + env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" + + locations = ServerLocations(filename=os.path.join(here, "server-locations.txt")) + + preferences = self.load_prefs() + + self.profile = FirefoxProfile(locations=locations, + preferences=preferences) + self.profile.set_preferences({"marionette.enabled": True, + "marionette.port": self.marionette_port, + "dom.disable_open_during_load": False, + "network.dns.localDomains": ",".join(hostnames), + "network.proxy.type": 0, + "places.history.enabled": False}) + if self.e10s: + self.profile.set_preferences({"browser.tabs.remote.autostart": True}) + + # Bug 1262954: winxp + e10s, disable hwaccel + if (self.e10s and platform.system() in ("Windows", "Microsoft") and + '5.1' in platform.version()): + self.profile.set_preferences({"layers.acceleration.disabled": True}) + + if self.ca_certificate_path is not None: + self.setup_ssl() + + debug_args, cmd = browser_command(self.binary, + self.binary_args if self.binary_args else [] + + [cmd_arg("marionette"), "about:blank"], + self.debug_info) + + self.runner = FirefoxRunner(profile=self.profile, + binary=cmd[0], + cmdargs=cmd[1:], + env=env, + process_class=ProcessHandler, + process_args={"processOutputLine": [self.on_output]}) + + self.logger.debug("Starting Firefox") + + self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) + self.logger.debug("Firefox Started") + + def load_prefs(self): + prefs = Preferences() + + prefs_path = os.path.join(self.prefs_root, "prefs_general.js") + if os.path.exists(prefs_path): + prefs.add(Preferences.read_prefs(prefs_path)) + else: + self.logger.warning("Failed to find base prefs file in %s" % prefs_path) + + # Add any custom preferences + prefs.add(self.extra_prefs, cast=True) + + return prefs() + + def stop(self, force=False): + if self.runner is not None and self.runner.is_running(): + try: + # For Firefox we assume that stopping the runner prompts the + # browser to shut down. This allows the leak log to be written + for clean, stop_f in [(True, lambda: self.runner.wait(self.shutdown_timeout)), + (False, lambda: self.runner.stop(signal.SIGTERM)), + (False, lambda: self.runner.stop(signal.SIGKILL))]: + if not force or not clean: + retcode = stop_f() + if retcode is not None: + self.logger.info("Browser exited with return code %s" % retcode) + break + except OSError: + # This can happen on Windows if the process is already dead + pass + + def pid(self): + if self.runner.process_handler is None: + return None + + try: + return self.runner.process_handler.pid + except AttributeError: + return None + + def on_output(self, line): + """Write a line of output from the firefox process to the log""" + data = line.decode("utf8", "replace") + if self.stack_fixer: + data = self.stack_fixer(data) + self.logger.process_output(self.pid(), + data, + command=" ".join(self.runner.command)) + + def is_alive(self): + if self.runner: + return self.runner.is_running() + return False + + def cleanup(self): + self.stop() + + def executor_browser(self): + assert self.marionette_port is not None + return ExecutorBrowser, {"marionette_port": self.marionette_port} + + def log_crash(self, process, test): + dump_dir = os.path.join(self.profile.profile, "minidumps") + + mozcrash.log_crashes(self.logger, + dump_dir, + symbols_path=self.symbols_path, + stackwalk_binary=self.stackwalk_binary, + process=process, + test=test) + + def setup_ssl(self): + """Create a certificate database to use in the test profile. This is configured + to trust the CA Certificate that has signed the web-platform.test server + certificate.""" + + self.logger.info("Setting up ssl") + + # Make sure the certutil libraries from the source tree are loaded when using a + # local copy of certutil + # TODO: Maybe only set this if certutil won't launch? + env = os.environ.copy() + certutil_dir = os.path.dirname(self.binary) + if mozinfo.isMac: + env_var = "DYLD_LIBRARY_PATH" + elif mozinfo.isUnix: + env_var = "LD_LIBRARY_PATH" + else: + env_var = "PATH" + + + env[env_var] = (os.path.pathsep.join([certutil_dir, env[env_var]]) + if env_var in env else certutil_dir).encode( + sys.getfilesystemencoding() or 'utf-8', 'replace') + + def certutil(*args): + cmd = [self.certutil_binary] + list(args) + self.logger.process_output("certutil", + subprocess.check_output(cmd, + env=env, + stderr=subprocess.STDOUT), + " ".join(cmd)) + + pw_path = os.path.join(self.profile.profile, ".crtdbpw") + with open(pw_path, "w") as f: + # Use empty password for certificate db + f.write("\n") + + cert_db_path = self.profile.profile + + # Create a new certificate db + certutil("-N", "-d", cert_db_path, "-f", pw_path) + + # Add the CA certificate to the database and mark as trusted to issue server certs + certutil("-A", "-d", cert_db_path, "-f", pw_path, "-t", "CT,,", + "-n", "web-platform-tests", "-i", self.ca_certificate_path) + + # List all certs in the database + certutil("-L", "-d", cert_db_path) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/sauce.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/sauce.py new file mode 100644 index 000000000000..7300b6afefb8 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/sauce.py @@ -0,0 +1,208 @@ +# 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 glob +import os +import shutil +import subprocess +import tarfile +import tempfile +import time +from cStringIO import StringIO as CStringIO + +import requests + +from .base import Browser, ExecutorBrowser, require_arg +from ..executors import executor_kwargs as base_executor_kwargs +from ..executors.executorselenium import (SeleniumTestharnessExecutor, + SeleniumRefTestExecutor) + +here = os.path.split(__file__)[0] + + +__wptrunner__ = {"product": "sauce", + "check_args": "check_args", + "browser": "SauceBrowser", + "executor": {"testharness": "SeleniumTestharnessExecutor", + "reftest": "SeleniumRefTestExecutor"}, + "browser_kwargs": "browser_kwargs", + "executor_kwargs": "executor_kwargs", + "env_extras": "env_extras", + "env_options": "env_options"} + + +def get_capabilities(**kwargs): + browser_name = kwargs["sauce_browser"] + platform = kwargs["sauce_platform"] + version = kwargs["sauce_version"] + build = kwargs["sauce_build"] + tags = kwargs["sauce_tags"] + tunnel_id = kwargs["sauce_tunnel_id"] + prerun_script = { + "MicrosoftEdge": { + "executable": "sauce-storage:edge-prerun.bat", + "background": False, + }, + "safari": { + "executable": "sauce-storage:safari-prerun.sh", + "background": False, + } + } + capabilities = { + "browserName": browser_name, + "build": build, + "disablePopupHandler": True, + "name": "%s %s on %s" % (browser_name, version, platform), + "platform": platform, + "public": "public", + "selenium-version": "3.3.1", + "tags": tags, + "tunnel-identifier": tunnel_id, + "version": version, + "prerun": prerun_script.get(browser_name) + } + + if browser_name == 'MicrosoftEdge': + capabilities['selenium-version'] = '2.4.8' + + return capabilities + + +def get_sauce_config(**kwargs): + browser_name = kwargs["sauce_browser"] + sauce_user = kwargs["sauce_user"] + sauce_key = kwargs["sauce_key"] + + hub_url = "%s:%s@localhost:4445" % (sauce_user, sauce_key) + data = { + "url": "http://%s/wd/hub" % hub_url, + "browserName": browser_name, + "capabilities": get_capabilities(**kwargs) + } + + return data + + +def check_args(**kwargs): + require_arg(kwargs, "sauce_browser") + require_arg(kwargs, "sauce_platform") + require_arg(kwargs, "sauce_version") + require_arg(kwargs, "sauce_user") + require_arg(kwargs, "sauce_key") + + +def browser_kwargs(**kwargs): + sauce_config = get_sauce_config(**kwargs) + + return {"sauce_config": sauce_config} + + +def executor_kwargs(test_type, server_config, cache_manager, run_info_data, + **kwargs): + executor_kwargs = base_executor_kwargs(test_type, server_config, + cache_manager, **kwargs) + + executor_kwargs["capabilities"] = get_capabilities(**kwargs) + + return executor_kwargs + + +def env_extras(**kwargs): + return [SauceConnect(**kwargs)] + + +def env_options(): + return {"host": "web-platform.test", + "bind_hostname": "true", + "supports_debugger": False} + + +def get_tar(url, dest): + resp = requests.get(url, stream=True) + resp.raise_for_status() + with tarfile.open(fileobj=CStringIO(resp.raw.read())) as f: + f.extractall(path=dest) + + +class SauceConnect(): + + def __init__(self, **kwargs): + self.sauce_user = kwargs["sauce_user"] + self.sauce_key = kwargs["sauce_key"] + self.sauce_tunnel_id = kwargs["sauce_tunnel_id"] + self.sauce_connect_binary = kwargs.get("sauce_connect_binary") + self.sc_process = None + self.temp_dir = None + + def __enter__(self, options): + if not self.sauce_connect_binary: + self.temp_dir = tempfile.mkdtemp() + get_tar("https://saucelabs.com/downloads/sc-latest-linux.tar.gz", self.temp_dir) + self.sauce_connect_binary = glob.glob(os.path.join(self.temp_dir, "sc-*-linux/bin/sc"))[0] + + self.upload_prerun_exec('edge-prerun.bat') + self.upload_prerun_exec('safari-prerun.sh') + + self.sc_process = subprocess.Popen([ + self.sauce_connect_binary, + "--user=%s" % self.sauce_user, + "--api-key=%s" % self.sauce_key, + "--no-remove-colliding-tunnels", + "--tunnel-identifier=%s" % self.sauce_tunnel_id, + "--readyfile=./sauce_is_ready", + "--tunnel-domains", + "web-platform.test", + "*.web-platform.test" + ]) + while not os.path.exists('./sauce_is_ready') and not self.sc_process.poll(): + time.sleep(5) + + if self.sc_process.returncode is not None and self.sc_process.returncode > 0: + raise SauceException("Unable to start Sauce Connect Proxy. Process exited with code %s", self.sc_process.returncode) + + def __exit__(self, *args): + self.sc_process.terminate() + if os.path.exists(self.temp_dir): + try: + shutil.rmtree(self.temp_dir) + except OSError: + pass + + def upload_prerun_exec(self, file_name): + auth = (self.sauce_user, self.sauce_key) + url = "https://saucelabs.com/rest/v1/storage/%s/%s?overwrite=true" % (self.sauce_user, file_name) + + with open(os.path.join(here, 'sauce_setup', file_name), 'rb') as f: + requests.post(url, data=f, auth=auth) + + +class SauceException(Exception): + pass + + +class SauceBrowser(Browser): + init_timeout = 300 + + def __init__(self, logger, sauce_config): + Browser.__init__(self, logger) + self.sauce_config = sauce_config + + def start(self): + pass + + def stop(self, force=False): + pass + + def pid(self): + return None + + def is_alive(self): + # TODO: Should this check something about the connection? + return True + + def cleanup(self): + pass + + def executor_browser(self): + return ExecutorBrowser, {"webdriver_url": self.sauce_config["url"]} diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/sauce_setup/edge-prerun.bat b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/sauce_setup/edge-prerun.bat new file mode 100644 index 000000000000..4554894896b9 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/sauce_setup/edge-prerun.bat @@ -0,0 +1,2 @@ +@echo off +reg add "HKCU\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Storage\microsoft.microsoftedge_8wekyb3d8bbwe\MicrosoftEdge\New Windows" /v "PopupMgr" /t REG_SZ /d no diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/sauce_setup/safari-prerun.sh b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/sauce_setup/safari-prerun.sh new file mode 100644 index 000000000000..85c72e6be6a0 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/sauce_setup/safari-prerun.sh @@ -0,0 +1,2 @@ +#!/bin/bash +defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool true diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/server-locations.txt b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/server-locations.txt new file mode 100644 index 000000000000..5dcaf4bb6a4c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/server-locations.txt @@ -0,0 +1,31 @@ +http://localhost:8000 primary + +http://web-platform.test:8000 +http://www.web-platform.test:8000 +http://www1.web-platform.test:8000 +http://www2.web-platform.test:8000 +http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8000 +http://xn--lve-6lad.web-platform.test:8000 + +http://web-platform.test:8001 +http://www.web-platform.test:8001 +http://www1.web-platform.test:8001 +http://www2.web-platform.test:8001 +http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8001 +http://xn--lve-6lad.web-platform.test:8001 + +https://web-platform.test:8443 +https://www.web-platform.test:8443 +https://www1.web-platform.test:8443 +https://www2.web-platform.test:8443 +https://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8443 +https://xn--lve-6lad.web-platform.test:8443 + +# These are actually ws servers, but until mozprofile is +# fixed we have to pretend that they are http servers +http://web-platform.test:8888 +http://www.web-platform.test:8888 +http://www1.web-platform.test:8888 +http://www2.web-platform.test:8888 +http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8888 +http://xn--lve-6lad.web-platform.test:8888 diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/servo.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/servo.py new file mode 100644 index 000000000000..e24e4dfd9dfe --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/servo.py @@ -0,0 +1,81 @@ +import os + +from .base import NullBrowser, ExecutorBrowser, require_arg +from ..executors import executor_kwargs as base_executor_kwargs +from ..executors.executorservo import ServoTestharnessExecutor, ServoRefTestExecutor, ServoWdspecExecutor + +here = os.path.join(os.path.split(__file__)[0]) + +__wptrunner__ = { + "product": "servo", + "check_args": "check_args", + "browser": "ServoBrowser", + "executor": { + "testharness": "ServoTestharnessExecutor", + "reftest": "ServoRefTestExecutor", + "wdspec": "ServoWdspecExecutor", + }, + "browser_kwargs": "browser_kwargs", + "executor_kwargs": "executor_kwargs", + "env_extras": "env_extras", + "env_options": "env_options", + "update_properties": "update_properties", +} + + +def check_args(**kwargs): + require_arg(kwargs, "binary") + + +def browser_kwargs(**kwargs): + return { + "binary": kwargs["binary"], + "debug_info": kwargs["debug_info"], + "binary_args": kwargs["binary_args"], + "user_stylesheets": kwargs.get("user_stylesheets"), + "ca_certificate_path": kwargs["ssl_env"].ca_cert_path(), + } + + +def executor_kwargs(test_type, server_config, cache_manager, run_info_data, + **kwargs): + rv = base_executor_kwargs(test_type, server_config, + cache_manager, **kwargs) + rv["pause_after_test"] = kwargs["pause_after_test"] + return rv + + +def env_extras(**kwargs): + return [] + + +def env_options(): + return {"host": "127.0.0.1", + "external_host": "web-platform.test", + "bind_hostname": "true", + "testharnessreport": "testharnessreport-servo.js", + "supports_debugger": True} + + +def update_properties(): + return ["debug", "os", "version", "processor", "bits"], None + + +class ServoBrowser(NullBrowser): + def __init__(self, logger, binary, debug_info=None, binary_args=None, + user_stylesheets=None, ca_certificate_path=None): + NullBrowser.__init__(self, logger) + self.binary = binary + self.debug_info = debug_info + self.binary_args = binary_args or [] + self.user_stylesheets = user_stylesheets or [] + self.ca_certificate_path = ca_certificate_path + + def executor_browser(self): + return ExecutorBrowser, { + "binary": self.binary, + "debug_info": self.debug_info, + "binary_args": self.binary_args, + "user_stylesheets": self.user_stylesheets, + "ca_certificate_path": self.ca_certificate_path, + } diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/servodriver.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/servodriver.py new file mode 100644 index 000000000000..9575e0fbff9d --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/servodriver.py @@ -0,0 +1,165 @@ +import os +import subprocess +import tempfile + +from mozprocess import ProcessHandler + +from .base import Browser, require_arg, get_free_port, browser_command, ExecutorBrowser +from ..executors import executor_kwargs as base_executor_kwargs +from ..executors.executorservodriver import (ServoWebDriverTestharnessExecutor, + ServoWebDriverRefTestExecutor) + +here = os.path.join(os.path.split(__file__)[0]) + +__wptrunner__ = { + "product": "servodriver", + "check_args": "check_args", + "browser": "ServoWebDriverBrowser", + "executor": { + "testharness": "ServoWebDriverTestharnessExecutor", + "reftest": "ServoWebDriverRefTestExecutor", + }, + "browser_kwargs": "browser_kwargs", + "executor_kwargs": "executor_kwargs", + "env_extras": "env_extras", + "env_options": "env_options", + "update_properties": "update_properties", +} + +hosts_text = """127.0.0.1 web-platform.test +127.0.0.1 www.web-platform.test +127.0.0.1 www1.web-platform.test +127.0.0.1 www2.web-platform.test +127.0.0.1 xn--n8j6ds53lwwkrqhv28a.web-platform.test +127.0.0.1 xn--lve-6lad.web-platform.test +""" + + +def check_args(**kwargs): + require_arg(kwargs, "binary") + + +def browser_kwargs(**kwargs): + return { + "binary": kwargs["binary"], + "debug_info": kwargs["debug_info"], + "user_stylesheets": kwargs.get("user_stylesheets"), + } + + +def executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs): + rv = base_executor_kwargs(test_type, server_config, + cache_manager, **kwargs) + return rv + + +def env_extras(**kwargs): + return [] + + +def env_options(): + return {"host": "127.0.0.1", + "external_host": "web-platform.test", + "bind_hostname": "true", + "testharnessreport": "testharnessreport-servodriver.js", + "supports_debugger": True} + + +def update_properties(): + return ["debug", "os", "version", "processor", "bits"], None + + +def make_hosts_file(): + hosts_fd, hosts_path = tempfile.mkstemp() + with os.fdopen(hosts_fd, "w") as f: + f.write(hosts_text) + return hosts_path + + +class ServoWebDriverBrowser(Browser): + used_ports = set() + + def __init__(self, logger, binary, debug_info=None, webdriver_host="127.0.0.1", + user_stylesheets=None): + Browser.__init__(self, logger) + self.binary = binary + self.webdriver_host = webdriver_host + self.webdriver_port = None + self.proc = None + self.debug_info = debug_info + self.hosts_path = make_hosts_file() + self.command = None + self.user_stylesheets = user_stylesheets if user_stylesheets else [] + + def start(self): + self.webdriver_port = get_free_port(4444, exclude=self.used_ports) + self.used_ports.add(self.webdriver_port) + + env = os.environ.copy() + env["HOST_FILE"] = self.hosts_path + env["RUST_BACKTRACE"] = "1" + + debug_args, command = browser_command( + self.binary, + [ + "--hard-fail", + "--webdriver", str(self.webdriver_port), + "about:blank", + ], + self.debug_info + ) + + for stylesheet in self.user_stylesheets: + command += ["--user-stylesheet", stylesheet] + + self.command = command + + self.command = debug_args + self.command + + if not self.debug_info or not self.debug_info.interactive: + self.proc = ProcessHandler(self.command, + processOutputLine=[self.on_output], + env=env, + storeOutput=False) + self.proc.run() + else: + self.proc = subprocess.Popen(self.command, env=env) + + self.logger.debug("Servo Started") + + def stop(self, force=False): + self.logger.debug("Stopping browser") + if self.proc is not None: + try: + self.proc.kill() + except OSError: + # This can happen on Windows if the process is already dead + pass + + def pid(self): + if self.proc is None: + return None + + try: + return self.proc.pid + except AttributeError: + return None + + def on_output(self, line): + """Write a line of output from the process to the log""" + self.logger.process_output(self.pid(), + line.decode("utf8", "replace"), + command=" ".join(self.command)) + + def is_alive(self): + if self.runner: + return self.runner.is_running() + return False + + def cleanup(self): + self.stop() + + def executor_browser(self): + assert self.webdriver_port is not None + return ExecutorBrowser, {"webdriver_host": self.webdriver_host, + "webdriver_port": self.webdriver_port} diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/config.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/config.py new file mode 100644 index 000000000000..5bd3f467f3ed --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/config.py @@ -0,0 +1,60 @@ +import ConfigParser +import os +import sys +from collections import OrderedDict + +here = os.path.split(__file__)[0] + +class ConfigDict(dict): + def __init__(self, base_path, *args, **kwargs): + self.base_path = base_path + dict.__init__(self, *args, **kwargs) + + def get_path(self, key, default=None): + if key not in self: + return default + path = self[key] + os.path.expanduser(path) + return os.path.abspath(os.path.join(self.base_path, path)) + +def read(config_path): + config_path = os.path.abspath(config_path) + config_root = os.path.split(config_path)[0] + parser = ConfigParser.SafeConfigParser() + success = parser.read(config_path) + assert config_path in success, success + + subns = {"pwd": os.path.abspath(os.path.curdir)} + + rv = OrderedDict() + for section in parser.sections(): + rv[section] = ConfigDict(config_root) + for key in parser.options(section): + rv[section][key] = parser.get(section, key, False, subns) + + return rv + +def path(argv=None): + if argv is None: + argv = [] + path = None + + for i, arg in enumerate(argv): + if arg == "--config": + if i + 1 < len(argv): + path = argv[i + 1] + elif arg.startswith("--config="): + path = arg.split("=", 1)[1] + if path is not None: + break + + if path is None: + if os.path.exists("wptrunner.ini"): + path = os.path.abspath("wptrunner.ini") + else: + path = os.path.join(here, "..", "wptrunner.default.ini") + + return os.path.abspath(path) + +def load(): + return read(path(sys.argv)) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/environment.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/environment.py new file mode 100644 index 000000000000..60588949088e --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/environment.py @@ -0,0 +1,216 @@ +import json +import os +import multiprocessing +import signal +import socket +import sys +import time + +from mozlog import get_default_logger, handlers + +from wptlogging import LogLevelRewriter + +here = os.path.split(__file__)[0] + +serve = None +sslutils = None + + +hostnames = ["web-platform.test", + "www.web-platform.test", + "www1.web-platform.test", + "www2.web-platform.test", + "xn--n8j6ds53lwwkrqhv28a.web-platform.test", + "xn--lve-6lad.web-platform.test"] + + +def do_delayed_imports(logger, test_paths): + global serve, sslutils + + serve_root = serve_path(test_paths) + sys.path.insert(0, serve_root) + + failed = [] + + try: + from tools.serve import serve + except ImportError: + from wpt_tools.serve import serve + except ImportError: + failed.append("serve") + + try: + import sslutils + except ImportError: + failed.append("sslutils") + + if failed: + logger.critical( + "Failed to import %s. Ensure that tests path %s contains web-platform-tests" % + (", ".join(failed), serve_root)) + sys.exit(1) + + +def serve_path(test_paths): + return test_paths["/"]["tests_path"] + + +def get_ssl_kwargs(**kwargs): + if kwargs["ssl_type"] == "openssl": + args = {"openssl_binary": kwargs["openssl_binary"]} + elif kwargs["ssl_type"] == "pregenerated": + args = {"host_key_path": kwargs["host_key_path"], + "host_cert_path": kwargs["host_cert_path"], + "ca_cert_path": kwargs["ca_cert_path"]} + else: + args = {} + return args + + +def ssl_env(logger, **kwargs): + ssl_env_cls = sslutils.environments[kwargs["ssl_type"]] + return ssl_env_cls(logger, **get_ssl_kwargs(**kwargs)) + + +class TestEnvironmentError(Exception): + pass + + +class TestEnvironment(object): + def __init__(self, test_paths, ssl_env, pause_after_test, debug_info, options, env_extras): + """Context manager that owns the test environment i.e. the http and + websockets servers""" + self.test_paths = test_paths + self.ssl_env = ssl_env + self.server = None + self.config = None + self.external_config = None + self.pause_after_test = pause_after_test + self.test_server_port = options.pop("test_server_port", True) + self.debug_info = debug_info + self.options = options if options is not None else {} + + self.cache_manager = multiprocessing.Manager() + self.stash = serve.stash.StashServer() + self.env_extras = env_extras + + + def __enter__(self): + self.stash.__enter__() + self.ssl_env.__enter__() + self.cache_manager.__enter__() + for cm in self.env_extras: + cm.__enter__(self.options) + self.setup_server_logging() + self.config = self.load_config() + serve.set_computed_defaults(self.config) + self.external_config, self.servers = serve.start(self.config, self.ssl_env, + self.get_routes()) + if self.options.get("supports_debugger") and self.debug_info and self.debug_info.interactive: + self.ignore_interrupts() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.process_interrupts() + + for scheme, servers in self.servers.iteritems(): + for port, server in servers: + server.kill() + for cm in self.env_extras: + cm.__exit__() + self.cache_manager.__exit__(exc_type, exc_val, exc_tb) + self.ssl_env.__exit__(exc_type, exc_val, exc_tb) + self.stash.__exit__() + + def ignore_interrupts(self): + signal.signal(signal.SIGINT, signal.SIG_IGN) + + def process_interrupts(self): + signal.signal(signal.SIGINT, signal.SIG_DFL) + + def load_config(self): + default_config_path = os.path.join(serve_path(self.test_paths), "config.default.json") + local_config_path = os.path.join(here, "config.json") + + with open(default_config_path) as f: + default_config = json.load(f) + + with open(local_config_path) as f: + data = f.read() + local_config = json.loads(data % self.options) + + #TODO: allow non-default configuration for ssl + + local_config["external_host"] = self.options.get("external_host", None) + local_config["ssl"]["encrypt_after_connect"] = self.options.get("encrypt_after_connect", False) + + config = serve.merge_json(default_config, local_config) + config["doc_root"] = serve_path(self.test_paths) + + if not self.ssl_env.ssl_enabled: + config["ports"]["https"] = [None] + + host = self.options.get("certificate_domain", config["host"]) + hosts = [host] + hosts.extend("%s.%s" % (item[0], host) for item in serve.get_subdomains(host).values()) + key_file, certificate = self.ssl_env.host_cert_path(hosts) + + config["key_file"] = key_file + config["certificate"] = certificate + + return config + + def setup_server_logging(self): + server_logger = get_default_logger(component="wptserve") + assert server_logger is not None + log_filter = handlers.LogLevelFilter(lambda x:x, "info") + # Downgrade errors to warnings for the server + log_filter = LogLevelRewriter(log_filter, ["error"], "warning") + server_logger.component_filter = log_filter + + try: + #Set as the default logger for wptserve + serve.set_logger(server_logger) + serve.logger = server_logger + except Exception: + # This happens if logging has already been set up for wptserve + pass + + def get_routes(self): + route_builder = serve.RoutesBuilder() + + for path, format_args, content_type, route in [ + ("testharness_runner.html", {}, "text/html", "/testharness_runner.html"), + (self.options.get("testharnessreport", "testharnessreport.js"), + {"output": self.pause_after_test}, "text/javascript", + "/resources/testharnessreport.js")]: + path = os.path.normpath(os.path.join(here, path)) + route_builder.add_static(path, format_args, content_type, route) + + for url_base, paths in self.test_paths.iteritems(): + if url_base == "/": + continue + route_builder.add_mount_point(url_base, paths["tests_path"]) + + if "/" not in self.test_paths: + del route_builder.mountpoint_routes["/"] + + return route_builder.get_routes() + + def ensure_started(self): + # Pause for a while to ensure that the server has a chance to start + time.sleep(2) + for scheme, servers in self.servers.iteritems(): + for port, server in servers: + if self.test_server_port: + s = socket.socket() + try: + s.connect((self.config["host"], port)) + except socket.error: + raise EnvironmentError( + "%s server on port %d failed to start" % (scheme, port)) + finally: + s.close() + + if not server.is_alive(): + raise EnvironmentError("%s server on port %d failed to start" % (scheme, port)) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/__init__.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/__init__.py new file mode 100644 index 000000000000..24761b838309 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/__init__.py @@ -0,0 +1,4 @@ +from base import (executor_kwargs, + testharness_result_converter, + reftest_result_converter, + TestExecutor) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py new file mode 100644 index 000000000000..a4bda4faafae --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py @@ -0,0 +1,325 @@ +import hashlib +import json +import os +import traceback +import urlparse +from abc import ABCMeta, abstractmethod + +from ..testrunner import Stop + +here = os.path.split(__file__)[0] + + +def executor_kwargs(test_type, server_config, cache_manager, **kwargs): + timeout_multiplier = kwargs["timeout_multiplier"] + if timeout_multiplier is None: + timeout_multiplier = 1 + + executor_kwargs = {"server_config": server_config, + "timeout_multiplier": timeout_multiplier, + "debug_info": kwargs["debug_info"]} + + if test_type == "reftest": + executor_kwargs["screenshot_cache"] = cache_manager.dict() + + return executor_kwargs + + +def strip_server(url): + """Remove the scheme and netloc from a url, leaving only the path and any query + or fragment. + + url - the url to strip + + e.g. http://example.org:8000/tests?id=1#2 becomes /tests?id=1#2""" + + url_parts = list(urlparse.urlsplit(url)) + url_parts[0] = "" + url_parts[1] = "" + return urlparse.urlunsplit(url_parts) + + +class TestharnessResultConverter(object): + harness_codes = {0: "OK", + 1: "ERROR", + 2: "TIMEOUT"} + + test_codes = {0: "PASS", + 1: "FAIL", + 2: "TIMEOUT", + 3: "NOTRUN"} + + def __call__(self, test, result): + """Convert a JSON result into a (TestResult, [SubtestResult]) tuple""" + result_url, status, message, stack, subtest_results = result + assert result_url == test.url, ("Got results from %s, expected %s" % + (result_url, test.url)) + harness_result = test.result_cls(self.harness_codes[status], message) + return (harness_result, + [test.subtest_result_cls(name, self.test_codes[status], message, stack) + for name, status, message, stack in subtest_results]) + + +testharness_result_converter = TestharnessResultConverter() + + +def reftest_result_converter(self, test, result): + return (test.result_cls(result["status"], result["message"], + extra=result.get("extra")), []) + + +def pytest_result_converter(self, test, data): + harness_data, subtest_data = data + + if subtest_data is None: + subtest_data = [] + + harness_result = test.result_cls(*harness_data) + subtest_results = [test.subtest_result_cls(*item) for item in subtest_data] + + return (harness_result, subtest_results) + + +class ExecutorException(Exception): + def __init__(self, status, message): + self.status = status + self.message = message + + +class TestExecutor(object): + __metaclass__ = ABCMeta + + test_type = None + convert_result = None + + def __init__(self, browser, server_config, timeout_multiplier=1, + debug_info=None): + """Abstract Base class for object that actually executes the tests in a + specific browser. Typically there will be a different TestExecutor + subclass for each test type and method of executing tests. + + :param browser: ExecutorBrowser instance providing properties of the + browser that will be tested. + :param server_config: Dictionary of wptserve server configuration of the + form stored in TestEnvironment.external_config + :param timeout_multiplier: Multiplier relative to base timeout to use + when setting test timeout. + """ + self.runner = None + self.browser = browser + self.server_config = server_config + self.timeout_multiplier = timeout_multiplier + self.debug_info = debug_info + self.last_environment = {"protocol": "http", + "prefs": {}} + self.protocol = None # This must be set in subclasses + + @property + def logger(self): + """StructuredLogger for this executor""" + if self.runner is not None: + return self.runner.logger + + def setup(self, runner): + """Run steps needed before tests can be started e.g. connecting to + browser instance + + :param runner: TestRunner instance that is going to run the tests""" + self.runner = runner + if self.protocol is not None: + self.protocol.setup(runner) + + def teardown(self): + """Run cleanup steps after tests have finished""" + if self.protocol is not None: + self.protocol.teardown() + + def run_test(self, test): + """Run a particular test. + + :param test: The test to run""" + if test.environment != self.last_environment: + self.on_environment_change(test.environment) + + try: + result = self.do_test(test) + except Exception as e: + result = self.result_from_exception(test, e) + + if result is Stop: + return result + + # log result of parent test + if result[0].status == "ERROR": + self.logger.debug(result[0].message) + + self.last_environment = test.environment + + self.runner.send_message("test_ended", test, result) + + def server_url(self, protocol): + return "%s://%s:%s" % (protocol, + self.server_config["host"], + self.server_config["ports"][protocol][0]) + + def test_url(self, test): + return urlparse.urljoin(self.server_url(test.environment["protocol"]), test.url) + + @abstractmethod + def do_test(self, test): + """Test-type and protocol specific implementation of running a + specific test. + + :param test: The test to run.""" + pass + + def on_environment_change(self, new_environment): + pass + + def result_from_exception(self, test, e): + if hasattr(e, "status") and e.status in test.result_cls.statuses: + status = e.status + else: + status = "ERROR" + message = unicode(getattr(e, "message", "")) + if message: + message += "\n" + message += traceback.format_exc(e) + return test.result_cls(status, message), [] + + +class TestharnessExecutor(TestExecutor): + convert_result = testharness_result_converter + + +class RefTestExecutor(TestExecutor): + convert_result = reftest_result_converter + + def __init__(self, browser, server_config, timeout_multiplier=1, screenshot_cache=None, + debug_info=None): + TestExecutor.__init__(self, browser, server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + + self.screenshot_cache = screenshot_cache + + +class RefTestImplementation(object): + def __init__(self, executor): + self.timeout_multiplier = executor.timeout_multiplier + self.executor = executor + # Cache of url:(screenshot hash, screenshot). Typically the + # screenshot is None, but we set this value if a test fails + # and the screenshot was taken from the cache so that we may + # retrieve the screenshot from the cache directly in the future + self.screenshot_cache = self.executor.screenshot_cache + self.message = None + + @property + def logger(self): + return self.executor.logger + + def get_hash(self, test, viewport_size, dpi): + timeout = test.timeout * self.timeout_multiplier + key = (test.url, viewport_size, dpi) + + if key not in self.screenshot_cache: + success, data = self.executor.screenshot(test, viewport_size, dpi) + + if not success: + return False, data + + screenshot = data + hash_value = hashlib.sha1(screenshot).hexdigest() + + self.screenshot_cache[key] = (hash_value, None) + + rv = (hash_value, screenshot) + else: + rv = self.screenshot_cache[key] + + self.message.append("%s %s" % (test.url, rv[0])) + return True, rv + + def is_pass(self, lhs_hash, rhs_hash, relation): + assert relation in ("==", "!=") + self.message.append("Testing %s %s %s" % (lhs_hash, relation, rhs_hash)) + return ((relation == "==" and lhs_hash == rhs_hash) or + (relation == "!=" and lhs_hash != rhs_hash)) + + def run_test(self, test): + viewport_size = test.viewport_size + dpi = test.dpi + self.message = [] + + # Depth-first search of reference tree, with the goal + # of reachings a leaf node with only pass results + + stack = list(((test, item[0]), item[1]) for item in reversed(test.references)) + while stack: + hashes = [None, None] + screenshots = [None, None] + + nodes, relation = stack.pop() + + for i, node in enumerate(nodes): + success, data = self.get_hash(node, viewport_size, dpi) + if success is False: + return {"status": data[0], "message": data[1]} + + hashes[i], screenshots[i] = data + + if self.is_pass(hashes[0], hashes[1], relation): + if nodes[1].references: + stack.extend(list(((nodes[1], item[0]), item[1]) for item in reversed(nodes[1].references))) + else: + # We passed + return {"status":"PASS", "message": None} + + # We failed, so construct a failure message + + for i, (node, screenshot) in enumerate(zip(nodes, screenshots)): + if screenshot is None: + success, screenshot = self.retake_screenshot(node, viewport_size, dpi) + if success: + screenshots[i] = screenshot + + log_data = [{"url": nodes[0].url, "screenshot": screenshots[0]}, relation, + {"url": nodes[1].url, "screenshot": screenshots[1]}] + + return {"status": "FAIL", + "message": "\n".join(self.message), + "extra": {"reftest_screenshots": log_data}} + + def retake_screenshot(self, node, viewport_size, dpi): + success, data = self.executor.screenshot(node, viewport_size, dpi) + if not success: + return False, data + + key = (node.url, viewport_size, dpi) + hash_val, _ = self.screenshot_cache[key] + self.screenshot_cache[key] = hash_val, data + return True, data + + +class WdspecExecutor(TestExecutor): + convert_result = pytest_result_converter + + +class Protocol(object): + def __init__(self, executor, browser): + self.executor = executor + self.browser = browser + + @property + def logger(self): + return self.executor.logger + + def setup(self, runner): + pass + + def teardown(self): + pass + + def wait(self): + pass diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py new file mode 100644 index 000000000000..21e6509af167 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py @@ -0,0 +1,618 @@ +import hashlib +import httplib +import os +import socket +import threading +import time +import traceback +import urlparse +import uuid +from collections import defaultdict + +from ..wpttest import WdspecResult, WdspecSubtestResult + +errors = None +marionette = None +pytestrunner = None + +here = os.path.join(os.path.split(__file__)[0]) + +from .base import (ExecutorException, + Protocol, + RefTestExecutor, + RefTestImplementation, + TestExecutor, + TestharnessExecutor, + testharness_result_converter, + reftest_result_converter, + strip_server, + WdspecExecutor) +from ..testrunner import Stop +from ..webdriver_server import GeckoDriverServer + +# Extra timeout to use after internal test timeout at which the harness +# should force a timeout +extra_timeout = 5 # seconds + + +def do_delayed_imports(): + global errors, marionette + + # Marionette client used to be called marionette, recently it changed + # to marionette_driver for unfathomable reasons + try: + import marionette + from marionette import errors + except ImportError: + from marionette_driver import marionette, errors + + +class MarionetteProtocol(Protocol): + def __init__(self, executor, browser): + do_delayed_imports() + + Protocol.__init__(self, executor, browser) + self.marionette = None + self.marionette_port = browser.marionette_port + self.timeout = None + self.runner_handle = None + + def setup(self, runner): + """Connect to browser via Marionette.""" + Protocol.setup(self, runner) + + self.logger.debug("Connecting to Marionette on port %i" % self.marionette_port) + self.marionette = marionette.Marionette(host='localhost', + port=self.marionette_port, + socket_timeout=None) + + # XXX Move this timeout somewhere + self.logger.debug("Waiting for Marionette connection") + while True: + success = self.marionette.wait_for_port(60) + #When running in a debugger wait indefinitely for firefox to start + if success or self.executor.debug_info is None: + break + + session_started = False + if success: + try: + self.logger.debug("Starting Marionette session") + self.marionette.start_session() + except Exception as e: + self.logger.warning("Starting marionette session failed: %s" % e) + else: + self.logger.debug("Marionette session started") + session_started = True + + if not success or not session_started: + self.logger.warning("Failed to connect to Marionette") + self.executor.runner.send_message("init_failed") + else: + try: + self.after_connect() + except Exception: + self.logger.warning("Post-connection steps failed") + self.logger.error(traceback.format_exc()) + self.executor.runner.send_message("init_failed") + else: + self.executor.runner.send_message("init_succeeded") + + def teardown(self): + try: + self.marionette._request_in_app_shutdown() + self.marionette.delete_session(send_request=False, reset_session_id=True) + except Exception: + # This is typically because the session never started + pass + if self.marionette is not None: + del self.marionette + + @property + def is_alive(self): + """Check if the Marionette connection is still active.""" + try: + self.marionette.current_window_handle + except Exception: + return False + return True + + def after_connect(self): + self.load_runner(self.executor.last_environment["protocol"]) + + def set_timeout(self, timeout): + """Set the Marionette script timeout. + + :param timeout: Script timeout in seconds + + """ + self.marionette.timeout.script = timeout + self.timeout = timeout + + def load_runner(self, protocol): + # Check if we previously had a test window open, and if we did make sure it's closed + self.marionette.execute_script("if (window.wrappedJSObject.win) {window.wrappedJSObject.win.close()}") + url = urlparse.urljoin(self.executor.server_url(protocol), "/testharness_runner.html") + self.logger.debug("Loading %s" % url) + self.runner_handle = self.marionette.current_window_handle + try: + self.marionette.navigate(url) + except Exception as e: + self.logger.critical( + "Loading initial page %s failed. Ensure that the " + "there are no other programs bound to this port and " + "that your firewall rules or network setup does not " + "prevent access.\e%s" % (url, traceback.format_exc(e))) + self.marionette.execute_script( + "document.title = '%s'" % threading.current_thread().name.replace("'", '"')) + + def close_old_windows(self, protocol): + handles = self.marionette.window_handles + runner_handle = None + try: + handles.remove(self.runner_handle) + runner_handle = self.runner_handle + except ValueError: + # The runner window probably changed id but we can restore it + # This isn't supposed to happen, but marionette ids are not yet stable + # We assume that the first handle returned corresponds to the runner, + # but it hopefully doesn't matter too much if that assumption is + # wrong since we reload the runner in that tab anyway. + runner_handle = handles.pop(0) + + for handle in handles: + self.marionette.switch_to_window(handle) + self.marionette.close() + + self.marionette.switch_to_window(runner_handle) + if runner_handle != self.runner_handle: + self.load_runner(protocol) + + def wait(self): + socket_timeout = self.marionette.client.sock.gettimeout() + if socket_timeout: + self.marionette.timeout.script = socket_timeout / 2 + + while True: + try: + self.marionette.execute_async_script("") + except errors.ScriptTimeoutException: + self.logger.debug("Script timed out") + pass + except (socket.timeout, IOError): + self.logger.debug("Socket closed") + break + except Exception as e: + self.logger.error(traceback.format_exc(e)) + break + + def on_environment_change(self, old_environment, new_environment): + #Unset all the old prefs + for name in old_environment.get("prefs", {}).iterkeys(): + value = self.executor.original_pref_values[name] + if value is None: + self.clear_user_pref(name) + else: + self.set_pref(name, value) + + for name, value in new_environment.get("prefs", {}).iteritems(): + self.executor.original_pref_values[name] = self.get_pref(name) + self.set_pref(name, value) + + def set_pref(self, name, value): + if value.lower() not in ("true", "false"): + try: + int(value) + except ValueError: + value = "'%s'" % value + else: + value = value.lower() + + self.logger.info("Setting pref %s (%s)" % (name, value)) + + script = """ + let prefInterface = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + let pref = '%s'; + let type = prefInterface.getPrefType(pref); + let value = %s; + switch(type) { + case prefInterface.PREF_STRING: + prefInterface.setCharPref(pref, value); + break; + case prefInterface.PREF_BOOL: + prefInterface.setBoolPref(pref, value); + break; + case prefInterface.PREF_INT: + prefInterface.setIntPref(pref, value); + break; + } + """ % (name, value) + with self.marionette.using_context(self.marionette.CONTEXT_CHROME): + self.marionette.execute_script(script) + + def clear_user_pref(self, name): + self.logger.info("Clearing pref %s" % (name)) + script = """ + let prefInterface = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + let pref = '%s'; + prefInterface.clearUserPref(pref); + """ % name + with self.marionette.using_context(self.marionette.CONTEXT_CHROME): + self.marionette.execute_script(script) + + def get_pref(self, name): + script = """ + let prefInterface = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + let pref = '%s'; + let type = prefInterface.getPrefType(pref); + switch(type) { + case prefInterface.PREF_STRING: + return prefInterface.getCharPref(pref); + case prefInterface.PREF_BOOL: + return prefInterface.getBoolPref(pref); + case prefInterface.PREF_INT: + return prefInterface.getIntPref(pref); + case prefInterface.PREF_INVALID: + return null; + } + """ % name + with self.marionette.using_context(self.marionette.CONTEXT_CHROME): + self.marionette.execute_script(script) + + def clear_origin(self, url): + self.logger.info("Clearing origin %s" % (url)) + script = """ + let url = '%s'; + let uri = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService) + .newURI(url); + let ssm = Components.classes["@mozilla.org/scriptsecuritymanager;1"] + .getService(Ci.nsIScriptSecurityManager); + let principal = ssm.createCodebasePrincipal(uri, {}); + let qms = Components.classes["@mozilla.org/dom/quota-manager-service;1"] + .getService(Components.interfaces.nsIQuotaManagerService); + qms.clearStoragesForPrincipal(principal, "default", true); + """ % url + with self.marionette.using_context(self.marionette.CONTEXT_CHROME): + self.marionette.execute_script(script) + + +class RemoteMarionetteProtocol(Protocol): + def __init__(self, executor, browser): + do_delayed_imports() + Protocol.__init__(self, executor, browser) + self.webdriver_binary = executor.webdriver_binary + self.webdriver_args = executor.webdriver_args + self.capabilities = self.executor.capabilities + self.session_config = None + self.server = None + + def setup(self, runner): + """Connect to browser via the Marionette HTTP server.""" + try: + self.server = GeckoDriverServer( + self.logger, + binary=self.webdriver_binary, + args=self.webdriver_args) + self.server.start(block=False) + self.logger.info( + "WebDriver HTTP server listening at %s" % self.server.url) + self.session_config = {"host": self.server.host, + "port": self.server.port, + "capabilities": self.capabilities} + except Exception: + self.logger.error(traceback.format_exc()) + self.executor.runner.send_message("init_failed") + else: + self.executor.runner.send_message("init_succeeded") + + def teardown(self): + if self.server is not None and self.server.is_alive: + self.server.stop() + + @property + def is_alive(self): + """Test that the Marionette connection is still alive. + + Because the remote communication happens over HTTP we need to + make an explicit request to the remote. It is allowed for + WebDriver spec tests to not have a WebDriver session, since this + may be what is tested. + + An HTTP request to an invalid path that results in a 404 is + proof enough to us that the server is alive and kicking. + """ + conn = httplib.HTTPConnection(self.server.host, self.server.port) + conn.request("HEAD", self.server.base_path + "invalid") + res = conn.getresponse() + return res.status == 404 + + +class ExecuteAsyncScriptRun(object): + def __init__(self, logger, func, protocol, url, timeout): + self.logger = logger + self.result = (None, None) + self.protocol = protocol + self.marionette = protocol.marionette + self.func = func + self.url = url + self.timeout = timeout + self.result_flag = threading.Event() + + def run(self): + index = self.url.rfind("/storage/"); + if index != -1: + # Clear storage + self.protocol.clear_origin(self.url) + + timeout = self.timeout + + try: + if timeout is not None: + if timeout + extra_timeout != self.protocol.timeout: + self.protocol.set_timeout(timeout + extra_timeout) + else: + # We just want it to never time out, really, but marionette doesn't + # make that possible. It also seems to time out immediately if the + # timeout is set too high. This works at least. + self.protocol.set_timeout(2**28 - 1) + except IOError: + self.logger.error("Lost marionette connection before starting test") + return Stop + + executor = threading.Thread(target = self._run) + executor.start() + + if timeout is not None: + wait_timeout = timeout + 2 * extra_timeout + else: + wait_timeout = None + + flag = self.result_flag.wait(wait_timeout) + if self.result[1] is None: + self.logger.debug("Timed out waiting for a result") + self.result = False, ("EXTERNAL-TIMEOUT", None) + return self.result + + def _run(self): + try: + self.result = True, self.func(self.marionette, self.url, self.timeout) + except errors.ScriptTimeoutException: + self.logger.debug("Got a marionette timeout") + self.result = False, ("EXTERNAL-TIMEOUT", None) + except (socket.timeout, IOError): + # This can happen on a crash + # Also, should check after the test if the firefox process is still running + # and otherwise ignore any other result and set it to crash + self.result = False, ("CRASH", None) + except Exception as e: + message = getattr(e, "message", "") + if message: + message += "\n" + message += traceback.format_exc(e) + self.result = False, ("ERROR", e) + + finally: + self.result_flag.set() + + +class MarionetteTestharnessExecutor(TestharnessExecutor): + def __init__(self, browser, server_config, timeout_multiplier=1, + close_after_done=True, debug_info=None, **kwargs): + """Marionette-based executor for testharness.js tests""" + TestharnessExecutor.__init__(self, browser, server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + + self.protocol = MarionetteProtocol(self, browser) + self.script = open(os.path.join(here, "testharness_marionette.js")).read() + self.close_after_done = close_after_done + self.window_id = str(uuid.uuid4()) + + self.original_pref_values = {} + + if marionette is None: + do_delayed_imports() + + def is_alive(self): + return self.protocol.is_alive + + def on_environment_change(self, new_environment): + self.protocol.on_environment_change(self.last_environment, new_environment) + + if new_environment["protocol"] != self.last_environment["protocol"]: + self.protocol.load_runner(new_environment["protocol"]) + + def do_test(self, test): + timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None + else None) + + success, data = ExecuteAsyncScriptRun(self.logger, + self.do_testharness, + self.protocol, + self.test_url(test), + timeout).run() + if success: + return self.convert_result(test, data) + + return (test.result_cls(*data), []) + + def do_testharness(self, marionette, url, timeout): + if self.close_after_done: + marionette.execute_script("if (window.wrappedJSObject.win) {window.wrappedJSObject.win.close()}") + self.protocol.close_old_windows(self.protocol) + + if timeout is not None: + timeout_ms = str(timeout * 1000) + else: + timeout_ms = "null" + + script = self.script % {"abs_url": url, + "url": strip_server(url), + "window_id": self.window_id, + "timeout_multiplier": self.timeout_multiplier, + "timeout": timeout_ms, + "explicit_timeout": timeout is None} + + rv = marionette.execute_async_script(script, new_sandbox=False) + return rv + + +class MarionetteRefTestExecutor(RefTestExecutor): + def __init__(self, browser, server_config, timeout_multiplier=1, + screenshot_cache=None, close_after_done=True, + debug_info=None, **kwargs): + + """Marionette-based executor for reftests""" + RefTestExecutor.__init__(self, + browser, + server_config, + screenshot_cache=screenshot_cache, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.protocol = MarionetteProtocol(self, browser) + self.implementation = RefTestImplementation(self) + self.close_after_done = close_after_done + self.has_window = False + self.original_pref_values = {} + + with open(os.path.join(here, "reftest.js")) as f: + self.script = f.read() + with open(os.path.join(here, "reftest-wait.js")) as f: + self.wait_script = f.read() + + def is_alive(self): + return self.protocol.is_alive + + def on_environment_change(self, new_environment): + self.protocol.on_environment_change(self.last_environment, new_environment) + + def do_test(self, test): + if self.close_after_done and self.has_window: + self.protocol.marionette.close() + self.protocol.marionette.switch_to_window( + self.protocol.marionette.window_handles[-1]) + self.has_window = False + + if not self.has_window: + self.protocol.marionette.execute_script(self.script) + self.protocol.marionette.switch_to_window(self.protocol.marionette.window_handles[-1]) + self.has_window = True + + result = self.implementation.run_test(test) + return self.convert_result(test, result) + + def screenshot(self, test, viewport_size, dpi): + # https://github.com/w3c/wptrunner/issues/166 + assert viewport_size is None + assert dpi is None + + timeout = self.timeout_multiplier * test.timeout if self.debug_info is None else None + + test_url = self.test_url(test) + + return ExecuteAsyncScriptRun(self.logger, + self._screenshot, + self.protocol, + test_url, + timeout).run() + + def _screenshot(self, marionette, url, timeout): + marionette.navigate(url) + + marionette.execute_async_script(self.wait_script) + + screenshot = marionette.screenshot(full=False) + # strip off the data:img/png, part of the url + if screenshot.startswith("data:image/png;base64,"): + screenshot = screenshot.split(",", 1)[1] + + return screenshot + + +class WdspecRun(object): + def __init__(self, func, session, path, timeout): + self.func = func + self.result = (None, None) + self.session = session + self.path = path + self.timeout = timeout + self.result_flag = threading.Event() + + def run(self): + """Runs function in a thread and interrupts it if it exceeds the + given timeout. Returns (True, (Result, [SubtestResult ...])) in + case of success, or (False, (status, extra information)) in the + event of failure. + """ + + executor = threading.Thread(target=self._run) + executor.start() + + flag = self.result_flag.wait(self.timeout) + if self.result[1] is None: + self.result = False, ("EXTERNAL-TIMEOUT", None) + + return self.result + + def _run(self): + try: + self.result = True, self.func(self.session, self.path, self.timeout) + except (socket.timeout, IOError): + self.result = False, ("CRASH", None) + except Exception as e: + message = getattr(e, "message") + if message: + message += "\n" + message += traceback.format_exc(e) + self.result = False, ("ERROR", message) + finally: + self.result_flag.set() + + +class MarionetteWdspecExecutor(WdspecExecutor): + def __init__(self, browser, server_config, webdriver_binary, + timeout_multiplier=1, close_after_done=True, debug_info=None, + capabilities=None, webdriver_args=None, binary=None): + self.do_delayed_imports() + WdspecExecutor.__init__(self, browser, server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.webdriver_binary = webdriver_binary + self.webdriver_args = webdriver_args + ["--binary", binary] + self.capabilities = capabilities + self.protocol = RemoteMarionetteProtocol(self, browser) + + def is_alive(self): + return self.protocol.is_alive + + def on_environment_change(self, new_environment): + pass + + def do_test(self, test): + timeout = test.timeout * self.timeout_multiplier + extra_timeout + + success, data = WdspecRun(self.do_wdspec, + self.protocol.session_config, + test.abs_path, + timeout).run() + + if success: + return self.convert_result(test, data) + + return (test.result_cls(*data), []) + + def do_wdspec(self, session_config, path, timeout): + harness_result = ("OK", None) + subtest_results = pytestrunner.run(path, + self.server_config, + session_config, + timeout=timeout) + return (harness_result, subtest_results) + + def do_delayed_imports(self): + global pytestrunner + from . import pytestrunner diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorselenium.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorselenium.py new file mode 100644 index 000000000000..b5edbec2f6fa --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorselenium.py @@ -0,0 +1,260 @@ +import os +import socket +import sys +import threading +import time +import traceback +import urlparse +import uuid + +from .base import (ExecutorException, + Protocol, + RefTestExecutor, + RefTestImplementation, + TestExecutor, + TestharnessExecutor, + testharness_result_converter, + reftest_result_converter, + strip_server) +from ..testrunner import Stop + +here = os.path.join(os.path.split(__file__)[0]) + +webdriver = None +exceptions = None +RemoteConnection = None + +extra_timeout = 5 + +def do_delayed_imports(): + global webdriver + global exceptions + global RemoteConnection + from selenium import webdriver + from selenium.common import exceptions + from selenium.webdriver.remote.remote_connection import RemoteConnection + +class SeleniumProtocol(Protocol): + def __init__(self, executor, browser, capabilities, **kwargs): + do_delayed_imports() + + Protocol.__init__(self, executor, browser) + self.capabilities = capabilities + self.url = browser.webdriver_url + self.webdriver = None + + def setup(self, runner): + """Connect to browser via Selenium's WebDriver implementation.""" + self.runner = runner + self.logger.debug("Connecting to Selenium on URL: %s" % self.url) + + session_started = False + try: + self.webdriver = webdriver.Remote(command_executor=RemoteConnection(self.url.strip("/"), + resolve_ip=False), + desired_capabilities=self.capabilities) + except: + self.logger.warning( + "Connecting to Selenium failed:\n%s" % traceback.format_exc()) + else: + self.logger.debug("Selenium session started") + session_started = True + + if not session_started: + self.logger.warning("Failed to connect to Selenium") + self.executor.runner.send_message("init_failed") + else: + try: + self.after_connect() + except: + print >> sys.stderr, traceback.format_exc() + self.logger.warning( + "Failed to connect to navigate initial page") + self.executor.runner.send_message("init_failed") + else: + self.executor.runner.send_message("init_succeeded") + + def teardown(self): + self.logger.debug("Hanging up on Selenium session") + try: + self.webdriver.quit() + except: + pass + del self.webdriver + + def is_alive(self): + try: + # Get a simple property over the connection + self.webdriver.current_window_handle + # TODO what exception? + except (socket.timeout, exceptions.ErrorInResponseException): + return False + return True + + def after_connect(self): + self.load_runner("http") + + def load_runner(self, protocol): + url = urlparse.urljoin(self.executor.server_url(protocol), + "/testharness_runner.html") + self.logger.debug("Loading %s" % url) + self.webdriver.get(url) + self.webdriver.execute_script("document.title = '%s'" % + threading.current_thread().name.replace("'", '"')) + + def wait(self): + while True: + try: + self.webdriver.execute_async_script(""); + except exceptions.TimeoutException: + pass + except (socket.timeout, exceptions.NoSuchWindowException, + exceptions.ErrorInResponseException, IOError): + break + except Exception as e: + self.logger.error(traceback.format_exc(e)) + break + + +class SeleniumRun(object): + def __init__(self, func, webdriver, url, timeout): + self.func = func + self.result = None + self.webdriver = webdriver + self.url = url + self.timeout = timeout + self.result_flag = threading.Event() + + def run(self): + timeout = self.timeout + + try: + self.webdriver.set_script_timeout((timeout + extra_timeout) * 1000) + except exceptions.ErrorInResponseException: + self.logger.error("Lost WebDriver connection") + return Stop + + executor = threading.Thread(target=self._run) + executor.start() + + flag = self.result_flag.wait(timeout + 2 * extra_timeout) + if self.result is None: + assert not flag + self.result = False, ("EXTERNAL-TIMEOUT", None) + + return self.result + + def _run(self): + try: + self.result = True, self.func(self.webdriver, self.url, self.timeout) + except exceptions.TimeoutException: + self.result = False, ("EXTERNAL-TIMEOUT", None) + except (socket.timeout, exceptions.ErrorInResponseException): + self.result = False, ("CRASH", None) + except Exception as e: + message = getattr(e, "message", "") + if message: + message += "\n" + message += traceback.format_exc(e) + self.result = False, ("ERROR", e) + finally: + self.result_flag.set() + + +class SeleniumTestharnessExecutor(TestharnessExecutor): + def __init__(self, browser, server_config, timeout_multiplier=1, + close_after_done=True, capabilities=None, debug_info=None): + """Selenium-based executor for testharness.js tests""" + TestharnessExecutor.__init__(self, browser, server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.protocol = SeleniumProtocol(self, browser, capabilities) + with open(os.path.join(here, "testharness_webdriver.js")) as f: + self.script = f.read() + self.close_after_done = close_after_done + self.window_id = str(uuid.uuid4()) + + def is_alive(self): + return self.protocol.is_alive() + + def on_environment_change(self, new_environment): + if new_environment["protocol"] != self.last_environment["protocol"]: + self.protocol.load_runner(new_environment["protocol"]) + + def do_test(self, test): + url = self.test_url(test) + + success, data = SeleniumRun(self.do_testharness, + self.protocol.webdriver, + url, + test.timeout * self.timeout_multiplier).run() + + if success: + return self.convert_result(test, data) + + return (test.result_cls(*data), []) + + def do_testharness(self, webdriver, url, timeout): + return webdriver.execute_async_script( + self.script % {"abs_url": url, + "url": strip_server(url), + "window_id": self.window_id, + "timeout_multiplier": self.timeout_multiplier, + "timeout": timeout * 1000}) + +class SeleniumRefTestExecutor(RefTestExecutor): + def __init__(self, browser, server_config, timeout_multiplier=1, + screenshot_cache=None, close_after_done=True, + debug_info=None, capabilities=None): + """Selenium WebDriver-based executor for reftests""" + RefTestExecutor.__init__(self, + browser, + server_config, + screenshot_cache=screenshot_cache, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.protocol = SeleniumProtocol(self, browser, + capabilities=capabilities) + self.implementation = RefTestImplementation(self) + self.close_after_done = close_after_done + self.has_window = False + + with open(os.path.join(here, "reftest.js")) as f: + self.script = f.read() + with open(os.path.join(here, "reftest-wait_webdriver.js")) as f: + self.wait_script = f.read() + + def is_alive(self): + return self.protocol.is_alive() + + def do_test(self, test): + self.logger.info("Test requires OS-level window focus") + + self.protocol.webdriver.set_window_size(600, 600) + + result = self.implementation.run_test(test) + + return self.convert_result(test, result) + + def screenshot(self, test, viewport_size, dpi): + # https://github.com/w3c/wptrunner/issues/166 + assert viewport_size is None + assert dpi is None + + return SeleniumRun(self._screenshot, + self.protocol.webdriver, + self.test_url(test), + test.timeout).run() + + def _screenshot(self, webdriver, url, timeout): + webdriver.get(url) + + webdriver.execute_async_script(self.wait_script) + + screenshot = webdriver.get_screenshot_as_base64() + + # strip off the data:img/png, part of the url + if screenshot.startswith("data:image/png;base64,"): + screenshot = screenshot.split(",", 1)[1] + + return screenshot diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorservo.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorservo.py new file mode 100644 index 000000000000..f002d93aa5f2 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorservo.py @@ -0,0 +1,368 @@ +import base64 +import hashlib +import httplib +import json +import os +import subprocess +import tempfile +import threading +import traceback +import urlparse +import uuid +from collections import defaultdict + +from mozprocess import ProcessHandler + +from .base import (ExecutorException, + Protocol, + RefTestImplementation, + testharness_result_converter, + reftest_result_converter, + WdspecExecutor) +from .process import ProcessTestExecutor +from ..browsers.base import browser_command +from ..wpttest import WdspecResult, WdspecSubtestResult +from ..webdriver_server import ServoDriverServer +from .executormarionette import WdspecRun + +pytestrunner = None +webdriver = None + +extra_timeout = 5 # seconds + +hosts_text = """127.0.0.1 web-platform.test +127.0.0.1 www.web-platform.test +127.0.0.1 www1.web-platform.test +127.0.0.1 www2.web-platform.test +127.0.0.1 xn--n8j6ds53lwwkrqhv28a.web-platform.test +127.0.0.1 xn--lve-6lad.web-platform.test +""" + +def make_hosts_file(): + hosts_fd, hosts_path = tempfile.mkstemp() + with os.fdopen(hosts_fd, "w") as f: + f.write(hosts_text) + return hosts_path + + +class ServoTestharnessExecutor(ProcessTestExecutor): + convert_result = testharness_result_converter + + def __init__(self, browser, server_config, timeout_multiplier=1, debug_info=None, + pause_after_test=False): + do_delayed_imports() + ProcessTestExecutor.__init__(self, browser, server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.pause_after_test = pause_after_test + self.result_data = None + self.result_flag = None + self.protocol = Protocol(self, browser) + self.hosts_path = make_hosts_file() + + def teardown(self): + try: + os.unlink(self.hosts_path) + except OSError: + pass + ProcessTestExecutor.teardown(self) + + def do_test(self, test): + self.result_data = None + self.result_flag = threading.Event() + + args = [ + "--hard-fail", "-u", "Servo/wptrunner", + "-Z", "replace-surrogates", "-z", self.test_url(test), + ] + for stylesheet in self.browser.user_stylesheets: + args += ["--user-stylesheet", stylesheet] + for pref, value in test.environment.get('prefs', {}).iteritems(): + args += ["--pref", "%s=%s" % (pref, value)] + if self.browser.ca_certificate_path: + args += ["--certificate-path", self.browser.ca_certificate_path] + args += self.browser.binary_args + debug_args, command = browser_command(self.binary, args, self.debug_info) + + self.command = command + + if self.pause_after_test: + self.command.remove("-z") + + self.command = debug_args + self.command + + env = os.environ.copy() + env["HOST_FILE"] = self.hosts_path + env["RUST_BACKTRACE"] = "1" + + + if not self.interactive: + self.proc = ProcessHandler(self.command, + processOutputLine=[self.on_output], + onFinish=self.on_finish, + env=env, + storeOutput=False) + self.proc.run() + else: + self.proc = subprocess.Popen(self.command, env=env) + + try: + timeout = test.timeout * self.timeout_multiplier + + # Now wait to get the output we expect, or until we reach the timeout + if not self.interactive and not self.pause_after_test: + wait_timeout = timeout + 5 + self.result_flag.wait(wait_timeout) + else: + wait_timeout = None + self.proc.wait() + + proc_is_running = True + + if self.result_flag.is_set(): + if self.result_data is not None: + result = self.convert_result(test, self.result_data) + else: + self.proc.wait() + result = (test.result_cls("CRASH", None), []) + proc_is_running = False + else: + result = (test.result_cls("TIMEOUT", None), []) + + + if proc_is_running: + if self.pause_after_test: + self.logger.info("Pausing until the browser exits") + self.proc.wait() + else: + self.proc.kill() + except KeyboardInterrupt: + self.proc.kill() + raise + + return result + + def on_output(self, line): + prefix = "ALERT: RESULT: " + line = line.decode("utf8", "replace") + if line.startswith(prefix): + self.result_data = json.loads(line[len(prefix):]) + self.result_flag.set() + else: + if self.interactive: + print line + else: + self.logger.process_output(self.proc.pid, + line, + " ".join(self.command)) + + def on_finish(self): + self.result_flag.set() + + +class TempFilename(object): + def __init__(self, directory): + self.directory = directory + self.path = None + + def __enter__(self): + self.path = os.path.join(self.directory, str(uuid.uuid4())) + return self.path + + def __exit__(self, *args, **kwargs): + try: + os.unlink(self.path) + except OSError: + pass + + +class ServoRefTestExecutor(ProcessTestExecutor): + convert_result = reftest_result_converter + + def __init__(self, browser, server_config, binary=None, timeout_multiplier=1, + screenshot_cache=None, debug_info=None, pause_after_test=False): + do_delayed_imports() + ProcessTestExecutor.__init__(self, + browser, + server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + + self.protocol = Protocol(self, browser) + self.screenshot_cache = screenshot_cache + self.implementation = RefTestImplementation(self) + self.tempdir = tempfile.mkdtemp() + self.hosts_path = make_hosts_file() + + def teardown(self): + try: + os.unlink(self.hosts_path) + except OSError: + pass + os.rmdir(self.tempdir) + ProcessTestExecutor.teardown(self) + + def screenshot(self, test, viewport_size, dpi): + full_url = self.test_url(test) + + with TempFilename(self.tempdir) as output_path: + debug_args, command = browser_command( + self.binary, + [ + "--hard-fail", "--exit", + "-u", "Servo/wptrunner", + "-Z", "disable-text-aa,load-webfonts-synchronously,replace-surrogates", + "--output=%s" % output_path, full_url + ] + self.browser.binary_args, + self.debug_info) + + for stylesheet in self.browser.user_stylesheets: + command += ["--user-stylesheet", stylesheet] + + for pref, value in test.environment.get('prefs', {}).iteritems(): + command += ["--pref", "%s=%s" % (pref, value)] + + command += ["--resolution", viewport_size or "800x600"] + + if self.browser.ca_certificate_path: + command += ["--certificate-path", self.browser.ca_certificate_path] + + if dpi: + command += ["--device-pixel-ratio", dpi] + + # Run ref tests in headless mode + command += ["-z"] + + self.command = debug_args + command + + env = os.environ.copy() + env["HOST_FILE"] = self.hosts_path + env["RUST_BACKTRACE"] = "1" + + if not self.interactive: + self.proc = ProcessHandler(self.command, + processOutputLine=[self.on_output], + env=env) + + + try: + self.proc.run() + timeout = test.timeout * self.timeout_multiplier + 5 + rv = self.proc.wait(timeout=timeout) + except KeyboardInterrupt: + self.proc.kill() + raise + else: + self.proc = subprocess.Popen(self.command, + env=env) + try: + rv = self.proc.wait() + except KeyboardInterrupt: + self.proc.kill() + raise + + if rv is None: + self.proc.kill() + return False, ("EXTERNAL-TIMEOUT", None) + + if rv != 0 or not os.path.exists(output_path): + return False, ("CRASH", None) + + with open(output_path) as f: + # Might need to strip variable headers or something here + data = f.read() + return True, base64.b64encode(data) + + def do_test(self, test): + result = self.implementation.run_test(test) + + return self.convert_result(test, result) + + def on_output(self, line): + line = line.decode("utf8", "replace") + if self.interactive: + print line + else: + self.logger.process_output(self.proc.pid, + line, + " ".join(self.command)) + +class ServoWdspecProtocol(Protocol): + def __init__(self, executor, browser): + self.do_delayed_imports() + Protocol.__init__(self, executor, browser) + self.session = None + self.server = None + + def setup(self, runner): + try: + self.server = ServoDriverServer(self.logger, binary=self.browser.binary, binary_args=self.browser.binary_args) + self.server.start(block=False) + self.logger.info( + "WebDriver HTTP server listening at %s" % self.server.url) + + self.logger.info( + "Establishing new WebDriver session with %s" % self.server.url) + self.session = webdriver.Session( + self.server.host, self.server.port, self.server.base_path) + except Exception: + self.logger.error(traceback.format_exc()) + self.executor.runner.send_message("init_failed") + else: + self.executor.runner.send_message("init_succeeded") + + def teardown(self): + if self.server is not None: + try: + if self.session.session_id is not None: + self.session.end() + except Exception: + pass + if self.server.is_alive: + self.server.stop() + + @property + def is_alive(self): + conn = httplib.HTTPConnection(self.server.host, self.server.port) + conn.request("HEAD", self.server.base_path + "invalid") + res = conn.getresponse() + return res.status == 404 + + def do_delayed_imports(self): + global pytestrunner, webdriver + from . import pytestrunner + import webdriver + + +class ServoWdspecExecutor(WdspecExecutor): + def __init__(self, browser, server_config, + timeout_multiplier=1, close_after_done=True, debug_info=None, + **kwargs): + WdspecExecutor.__init__(self, browser, server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.protocol = ServoWdspecProtocol(self, browser) + + def is_alive(self): + return self.protocol.is_alive + + def on_environment_change(self, new_environment): + pass + + def do_test(self, test): + timeout = test.timeout * self.timeout_multiplier + extra_timeout + + success, data = WdspecRun(self.do_wdspec, + self.protocol.session, + test.path, + timeout).run() + + if success: + return self.convert_result(test, data) + + return (test.result_cls(*data), []) + + def do_wdspec(self, session, path, timeout): + harness_result = ("OK", None) + subtest_results = pytestrunner.run(path, session, timeout=timeout) + return (harness_result, subtest_results) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorservodriver.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorservodriver.py new file mode 100644 index 000000000000..8dd331c75090 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorservodriver.py @@ -0,0 +1,257 @@ +import json +import os +import socket +import threading +import time +import traceback + +from .base import (Protocol, + RefTestExecutor, + RefTestImplementation, + TestharnessExecutor, + strip_server) +from ..testrunner import Stop + +webdriver = None + +here = os.path.join(os.path.split(__file__)[0]) + +extra_timeout = 5 + + +def do_delayed_imports(): + global webdriver + import webdriver + + +class ServoWebDriverProtocol(Protocol): + def __init__(self, executor, browser, capabilities, **kwargs): + do_delayed_imports() + Protocol.__init__(self, executor, browser) + self.capabilities = capabilities + self.host = browser.webdriver_host + self.port = browser.webdriver_port + self.session = None + + def setup(self, runner): + """Connect to browser via WebDriver.""" + self.runner = runner + + url = "http://%s:%d" % (self.host, self.port) + session_started = False + try: + self.session = webdriver.Session(self.host, self.port, + extension=webdriver.servo.ServoCommandExtensions) + self.session.start() + except: + self.logger.warning( + "Connecting with WebDriver failed:\n%s" % traceback.format_exc()) + else: + self.logger.debug("session started") + session_started = True + + if not session_started: + self.logger.warning("Failed to connect via WebDriver") + self.executor.runner.send_message("init_failed") + else: + self.executor.runner.send_message("init_succeeded") + + def teardown(self): + self.logger.debug("Hanging up on WebDriver session") + try: + self.session.end() + except: + pass + + def is_alive(self): + try: + # Get a simple property over the connection + self.session.window_handle + # TODO what exception? + except Exception: + return False + return True + + def after_connect(self): + pass + + def wait(self): + while True: + try: + self.session.execute_async_script("") + except webdriver.TimeoutException: + pass + except (socket.timeout, IOError): + break + except Exception as e: + self.logger.error(traceback.format_exc(e)) + break + + def on_environment_change(self, old_environment, new_environment): + #Unset all the old prefs + self.session.extension.reset_prefs(*old_environment.get("prefs", {}).keys()) + self.session.extension.set_prefs(new_environment.get("prefs", {})) + + +class ServoWebDriverRun(object): + def __init__(self, func, session, url, timeout, current_timeout=None): + self.func = func + self.result = None + self.session = session + self.url = url + self.timeout = timeout + self.result_flag = threading.Event() + + def run(self): + executor = threading.Thread(target=self._run) + executor.start() + + flag = self.result_flag.wait(self.timeout + extra_timeout) + if self.result is None: + assert not flag + self.result = False, ("EXTERNAL-TIMEOUT", None) + + return self.result + + def _run(self): + try: + self.result = True, self.func(self.session, self.url, self.timeout) + except webdriver.TimeoutException: + self.result = False, ("EXTERNAL-TIMEOUT", None) + except (socket.timeout, IOError): + self.result = False, ("CRASH", None) + except Exception as e: + message = getattr(e, "message", "") + if message: + message += "\n" + message += traceback.format_exc(e) + self.result = False, ("ERROR", e) + finally: + self.result_flag.set() + + +def timeout_func(timeout): + if timeout: + t0 = time.time() + return lambda: time.time() - t0 > timeout + extra_timeout + else: + return lambda: False + + +class ServoWebDriverTestharnessExecutor(TestharnessExecutor): + def __init__(self, browser, server_config, timeout_multiplier=1, + close_after_done=True, capabilities=None, debug_info=None): + TestharnessExecutor.__init__(self, browser, server_config, timeout_multiplier=1, + debug_info=None) + self.protocol = ServoWebDriverProtocol(self, browser, capabilities=capabilities) + with open(os.path.join(here, "testharness_servodriver.js")) as f: + self.script = f.read() + self.timeout = None + + def on_protocol_change(self, new_protocol): + pass + + def is_alive(self): + return self.protocol.is_alive() + + def do_test(self, test): + url = self.test_url(test) + + timeout = test.timeout * self.timeout_multiplier + extra_timeout + + if timeout != self.timeout: + try: + self.protocol.session.timeouts.script = timeout + self.timeout = timeout + except IOError: + self.logger.error("Lost webdriver connection") + return Stop + + success, data = ServoWebDriverRun(self.do_testharness, + self.protocol.session, + url, + timeout).run() + + if success: + return self.convert_result(test, data) + + return (test.result_cls(*data), []) + + def do_testharness(self, session, url, timeout): + session.url = url + result = json.loads( + session.execute_async_script( + self.script % {"abs_url": url, + "url": strip_server(url), + "timeout_multiplier": self.timeout_multiplier, + "timeout": timeout * 1000})) + # Prevent leaking every page in history until Servo develops a more sane + # page cache + session.back() + return result + + +class TimeoutError(Exception): + pass + + +class ServoWebDriverRefTestExecutor(RefTestExecutor): + def __init__(self, browser, server_config, timeout_multiplier=1, + screenshot_cache=None, capabilities=None, debug_info=None): + """Selenium WebDriver-based executor for reftests""" + RefTestExecutor.__init__(self, + browser, + server_config, + screenshot_cache=screenshot_cache, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.protocol = ServoWebDriverProtocol(self, browser, + capabilities=capabilities) + self.implementation = RefTestImplementation(self) + self.timeout = None + with open(os.path.join(here, "reftest-wait_servodriver.js")) as f: + self.wait_script = f.read() + + def is_alive(self): + return self.protocol.is_alive() + + def do_test(self, test): + try: + result = self.implementation.run_test(test) + return self.convert_result(test, result) + except IOError: + return test.result_cls("CRASH", None), [] + except TimeoutError: + return test.result_cls("TIMEOUT", None), [] + except Exception as e: + message = getattr(e, "message", "") + if message: + message += "\n" + message += traceback.format_exc(e) + return test.result_cls("ERROR", message), [] + + def screenshot(self, test, viewport_size, dpi): + # https://github.com/w3c/wptrunner/issues/166 + assert viewport_size is None + assert dpi is None + + timeout = (test.timeout * self.timeout_multiplier + extra_timeout + if self.debug_info is None else None) + + if self.timeout != timeout: + try: + self.protocol.session.timeouts.script = timeout + self.timeout = timeout + except IOError: + self.logger.error("Lost webdriver connection") + return Stop + + return ServoWebDriverRun(self._screenshot, + self.protocol.session, + self.test_url(test), + timeout).run() + + def _screenshot(self, session, url, timeout): + session.url = url + session.execute_async_script(self.wait_script) + return session.screenshot() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/process.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/process.py new file mode 100644 index 000000000000..fb8c17a96ba0 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/process.py @@ -0,0 +1,20 @@ +from .base import TestExecutor + + +class ProcessTestExecutor(TestExecutor): + def __init__(self, *args, **kwargs): + TestExecutor.__init__(self, *args, **kwargs) + self.binary = self.browser.binary + self.interactive = (False if self.debug_info is None + else self.debug_info.interactive) + + def setup(self, runner): + self.runner = runner + self.runner.send_message("init_succeeded") + return True + + def is_alive(self): + return True + + def do_test(self, test): + raise NotImplementedError diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/pytestrunner/__init__.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/pytestrunner/__init__.py new file mode 100644 index 000000000000..a92b3a8151da --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/pytestrunner/__init__.py @@ -0,0 +1 @@ +from .runner import run diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py new file mode 100644 index 000000000000..3a97d40e066a --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py @@ -0,0 +1,115 @@ +"""Provides interface to deal with pytest. + +Usage:: + + session = webdriver.client.Session("127.0.0.1", "4444", "/") + harness_result = ("OK", None) + subtest_results = pytestrunner.run("/path/to/test", session.url) + return (harness_result, subtest_results) +""" + +import errno +import json +import os +import shutil +import tempfile + + +pytest = None + + +def do_delayed_imports(): + global pytest + import pytest + + +def run(path, server_config, session_config, timeout=0): + """Run Python test at ``path`` in pytest. The provided ``session`` + is exposed as a fixture available in the scope of the test functions. + + :param path: Path to the test file. + :param session_config: dictionary of host, port,capabilities parameters + to pass through to the webdriver session + :param timeout: Duration before interrupting potentially hanging + tests. If 0, there is no timeout. + + :returns: List of subtest results, which are tuples of (test id, + status, message, stacktrace). + """ + + if pytest is None: + do_delayed_imports() + + recorder = SubtestResultRecorder() + + os.environ["WD_HOST"] = session_config["host"] + os.environ["WD_PORT"] = str(session_config["port"]) + os.environ["WD_CAPABILITIES"] = json.dumps(session_config["capabilities"]) + os.environ["WD_SERVER_CONFIG"] = json.dumps(server_config) + + plugins = [recorder] + + # TODO(ato): Deal with timeouts + + with TemporaryDirectory() as cache: + pytest.main(["--strict", # turn warnings into errors + "--verbose", # show each individual subtest + "--capture", "no", # enable stdout/stderr from tests + "--basetemp", cache, # temporary directory + path], + plugins=plugins) + + return recorder.results + + +class SubtestResultRecorder(object): + def __init__(self): + self.results = [] + + def pytest_runtest_logreport(self, report): + if report.passed and report.when == "call": + self.record_pass(report) + elif report.failed: + if report.when != "call": + self.record_error(report) + else: + self.record_fail(report) + elif report.skipped: + self.record_skip(report) + + def record_pass(self, report): + self.record(report.nodeid, "PASS") + + def record_fail(self, report): + self.record(report.nodeid, "FAIL", stack=report.longrepr) + + def record_error(self, report): + # error in setup/teardown + if report.when != "call": + message = "%s error" % report.when + self.record(report.nodeid, "ERROR", message, report.longrepr) + + def record_skip(self, report): + self.record(report.nodeid, "ERROR", + "In-test skip decorators are disallowed, " + "please use WPT metadata to ignore tests.") + + def record(self, test, status, message=None, stack=None): + if stack is not None: + stack = str(stack) + new_result = (test, status, message, stack) + self.results.append(new_result) + + +class TemporaryDirectory(object): + def __enter__(self): + self.path = tempfile.mkdtemp(prefix="pytest-") + return self.path + + def __exit__(self, *args): + try: + shutil.rmtree(self.path) + except OSError as e: + # no such file or directory + if e.errno != errno.ENOENT: + raise diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest-wait.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest-wait.js new file mode 100644 index 000000000000..7dd96df78031 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest-wait.js @@ -0,0 +1,18 @@ +function test(x) { + log("classList: " + root.classList); + if (!root.classList.contains("reftest-wait")) { + observer.disconnect(); + marionetteScriptFinished(); + } +} + +var root = document.documentElement; +var observer = new MutationObserver(test); + +observer.observe(root, {attributes: true}); + +if (document.readyState != "complete") { + onload = test +} else { + test(); +} diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest-wait_servodriver.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest-wait_servodriver.js new file mode 100644 index 000000000000..5848433b5409 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest-wait_servodriver.js @@ -0,0 +1,15 @@ +callback = arguments[arguments.length - 1]; + +function check_done() { + if (!document.documentElement.classList.contains('reftest-wait')) { + callback(); + } else { + setTimeout(check_done, 50); + } +} + +if (document.readyState === 'complete') { + check_done(); +} else { + addEventListener("load", check_done); +} diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest-wait_webdriver.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest-wait_webdriver.js new file mode 100644 index 000000000000..c3cc453bd491 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest-wait_webdriver.js @@ -0,0 +1,33 @@ +var callback = arguments[arguments.length - 1]; + +function test(x) { + if (!root.classList.contains("reftest-wait")) { + observer.disconnect(); + + // As of 2017-04-05, the Chromium web browser exhibits a rendering bug + // (https://bugs.chromium.org/p/chromium/issues/detail?id=708757) that + // produces instability during screen capture. The following use of + // `requestAnimationFrame` is intended as a short-term workaround, though + // it is not guaranteed to resolve the issue. + // + // For further detail, see: + // https://github.com/jugglinmike/chrome-screenshot-race/issues/1 + + requestAnimationFrame(function() { + requestAnimationFrame(function() { + callback(); + }); + }); + } +} + +var root = document.documentElement; +var observer = new MutationObserver(test); + +observer.observe(root, {attributes: true}); + +if (document.readyState != "complete") { + onload = test; +} else { + test(); +} diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest.js new file mode 100644 index 000000000000..5bd5c609cbd5 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/reftest.js @@ -0,0 +1 @@ +var win = window.open("about:blank", "test", "width=600,height=600"); diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_marionette.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_marionette.js new file mode 100644 index 000000000000..1cfa85f8949a --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_marionette.js @@ -0,0 +1,32 @@ +window.wrappedJSObject.timeout_multiplier = %(timeout_multiplier)d; +window.wrappedJSObject.explicit_timeout = %(explicit_timeout)d; + +window.wrappedJSObject.addEventListener("message", function listener(event) { + if (event.data.type != "complete") { + return; + } + window.wrappedJSObject.removeEventListener("message", listener); + clearTimeout(timer); + var tests = event.data.tests; + var status = event.data.status; + + var subtest_results = tests.map(function (x) { + return [x.name, x.status, x.message, x.stack] + }); + + marionetteScriptFinished(["%(url)s", + status.status, + status.message, + status.stack, + subtest_results]); +}, false); + +window.wrappedJSObject.win = window.open("%(abs_url)s", "%(window_id)s"); + +var timer = null; +if (%(timeout)s) { + timer = setTimeout(function() { + log("Timeout fired"); + window.wrappedJSObject.win.timeout(); + }, %(timeout)s); +} diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_servodriver.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_servodriver.js new file mode 100644 index 000000000000..d731cc04d701 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_servodriver.js @@ -0,0 +1,2 @@ +window.__wd_results_callback__ = arguments[arguments.length - 1]; +window.__wd_results_timer__ = setTimeout(timeout, %(timeout)s); diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_webdriver.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_webdriver.js new file mode 100644 index 000000000000..f5cbff9ef776 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_webdriver.js @@ -0,0 +1,29 @@ +var callback = arguments[arguments.length - 1]; +window.timeout_multiplier = %(timeout_multiplier)d; + +window.addEventListener("message", function f(event) { + if (event.data.type != "complete") { + return; + } + window.removeEventListener("message", f); + + var tests = event.data.tests; + var status = event.data.status; + + var subtest_results = tests.map(function(x) { + return [x.name, x.status, x.message, x.stack] + }); + clearTimeout(timer); + callback(["%(url)s", + status.status, + status.message, + status.stack, + subtest_results]); +}, false); + +window.win = window.open("%(abs_url)s", "%(window_id)s"); + +var timer = setTimeout(function() { + window.win.timeout(); + window.win.close(); +}, %(timeout)s); diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/expected.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/expected.py new file mode 100644 index 000000000000..f06abb946af1 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/expected.py @@ -0,0 +1,14 @@ +import os + + +def expected_path(metadata_path, test_path): + """Path to the expectation data file for a given test path. + + This is defined as metadata_path + relative_test_path + .ini + + :param metadata_path: Path to the root of the metadata directory + :param test_path: Relative path to the test file from the test root + """ + args = list(test_path.split("/")) + args[-1] += ".ini" + return os.path.join(metadata_path, *args) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/hosts.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/hosts.py new file mode 100644 index 000000000000..915c17f1b311 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/hosts.py @@ -0,0 +1,100 @@ +from __future__ import unicode_literals + + +class HostsLine(object): + def __init__(self, ip_address, canonical_hostname, aliases=None, comment=None): + self.ip_address = ip_address + self.canonical_hostname = canonical_hostname + self.aliases = aliases if aliases is not None else [] + self.comment = comment + if self.ip_address is None: + assert self.canonical_hostname is None + assert not self.aliases + assert self.comment is not None + + @classmethod + def from_string(cls, line): + if not line.strip(): + return + + line = line.strip() + + ip_address = None + canonical_hostname = None + aliases = [] + comment = None + + comment_parts = line.split("#", 1) + if len(comment_parts) > 1: + comment = comment_parts[1] + + data = comment_parts[0].strip() + + if data: + fields = data.split() + if len(fields) < 2: + raise ValueError("Invalid hosts line") + + ip_address = fields[0] + canonical_hostname = fields[1] + aliases = fields[2:] + + return cls(ip_address, canonical_hostname, aliases, comment) + + +class HostsFile(object): + def __init__(self): + self.data = [] + self.by_hostname = {} + + def set_host(self, host): + if host.canonical_hostname is None: + self.data.append(host) + elif host.canonical_hostname in self.by_hostname: + old_host = self.by_hostname[host.canonical_hostname] + old_host.ip_address = host.ip_address + old_host.aliases = host.aliases + old_host.comment = host.comment + else: + self.data.append(host) + self.by_hostname[host.canonical_hostname] = host + + @classmethod + def from_file(cls, f): + rv = cls() + for line in f: + host = HostsLine.from_string(line) + if host is not None: + rv.set_host(host) + return rv + + def to_string(self): + field_widths = [0, 0] + for line in self.data: + if line.ip_address is not None: + field_widths[0] = max(field_widths[0], len(line.ip_address)) + field_widths[1] = max(field_widths[1], len(line.canonical_hostname)) + + lines = [] + + for host in self.data: + line = "" + if host.ip_address is not None: + ip_string = host.ip_address.ljust(field_widths[0]) + hostname_str = host.canonical_hostname + if host.aliases: + hostname_str = "%s %s" % (hostname_str.ljust(field_widths[1]), + " ".join(host.aliases)) + line = "%s %s" % (ip_string, hostname_str) + if host.comment: + if line: + line += " " + line += "#%s" % host.comment + lines.append(line) + + lines.append("") + + return "\n".join(lines) + + def to_file(self, f): + f.write(self.to_string().encode("utf8")) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestexpected.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestexpected.py new file mode 100644 index 000000000000..fb5c1b1e7239 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestexpected.py @@ -0,0 +1,250 @@ +import os +import urlparse + +from wptmanifest.backends import static +from wptmanifest.backends.static import ManifestItem + +import expected + +"""Manifest structure used to store expected results of a test. + +Each manifest file is represented by an ExpectedManifest that +has one or more TestNode children, one per test in the manifest. +Each TestNode has zero or more SubtestNode children, one for each +known subtest of the test. +""" + +def data_cls_getter(output_node, visited_node): + # visited_node is intentionally unused + if output_node is None: + return ExpectedManifest + if isinstance(output_node, ExpectedManifest): + return TestNode + if isinstance(output_node, TestNode): + return SubtestNode + raise ValueError + + +def bool_prop(name, node): + """Boolean property""" + try: + return node.get(name) + except KeyError: + return None + + +def tags(node): + """Set of tags that have been applied to the test""" + try: + value = node.get("tags") + if isinstance(value, (str, unicode)): + return {value} + return set(value) + except KeyError: + return set() + + +def prefs(node): + def value(ini_value): + if isinstance(ini_value, (str, unicode)): + return tuple(ini_value.split(":", 1)) + else: + return (ini_value, None) + + try: + node_prefs = node.get("prefs") + if type(node_prefs) in (str, unicode): + prefs = {value(node_prefs)} + rv = dict(value(item) for item in node_prefs) + except KeyError: + rv = {} + return rv + + +class ExpectedManifest(ManifestItem): + def __init__(self, name, test_path, url_base): + """Object representing all the tests in a particular manifest + + :param name: Name of the AST Node associated with this object. + Should always be None since this should always be associated with + the root node of the AST. + :param test_path: Path of the test file associated with this manifest. + :param url_base: Base url for serving the tests in this manifest + """ + if name is not None: + raise ValueError("ExpectedManifest should represent the root node") + if test_path is None: + raise ValueError("ExpectedManifest requires a test path") + if url_base is None: + raise ValueError("ExpectedManifest requires a base url") + ManifestItem.__init__(self, name) + self.child_map = {} + self.test_path = test_path + self.url_base = url_base + + def append(self, child): + """Add a test to the manifest""" + ManifestItem.append(self, child) + self.child_map[child.id] = child + + def _remove_child(self, child): + del self.child_map[child.id] + ManifestItem.remove_child(self, child) + assert len(self.child_map) == len(self.children) + + def get_test(self, test_id): + """Get a test from the manifest by ID + + :param test_id: ID of the test to return.""" + return self.child_map.get(test_id) + + @property + def url(self): + return urlparse.urljoin(self.url_base, + "/".join(self.test_path.split(os.path.sep))) + + @property + def disabled(self): + return bool_prop("disabled", self) + + @property + def restart_after(self): + return bool_prop("restart-after", self) + + @property + def tags(self): + return tags(self) + + @property + def prefs(self): + return prefs(self) + + +class DirectoryManifest(ManifestItem): + @property + def disabled(self): + return bool_prop("disabled", self) + + @property + def restart_after(self): + return bool_prop("restart-after", self) + + @property + def tags(self): + return tags(self) + + @property + def prefs(self): + return prefs(self) + + +class TestNode(ManifestItem): + def __init__(self, name): + """Tree node associated with a particular test in a manifest + + :param name: name of the test""" + assert name is not None + ManifestItem.__init__(self, name) + self.updated_expected = [] + self.new_expected = [] + self.subtests = {} + self.default_status = None + self._from_file = True + + @property + def is_empty(self): + required_keys = set(["type"]) + if set(self._data.keys()) != required_keys: + return False + return all(child.is_empty for child in self.children) + + @property + def test_type(self): + return self.get("type") + + @property + def id(self): + return urlparse.urljoin(self.parent.url, self.name) + + @property + def disabled(self): + return bool_prop("disabled", self) + + @property + def restart_after(self): + return bool_prop("restart-after", self) + + @property + def tags(self): + return tags(self) + + @property + def prefs(self): + return prefs(self) + + def append(self, node): + """Add a subtest to the current test + + :param node: AST Node associated with the subtest""" + child = ManifestItem.append(self, node) + self.subtests[child.name] = child + + def get_subtest(self, name): + """Get the SubtestNode corresponding to a particular subtest, by name + + :param name: Name of the node to return""" + if name in self.subtests: + return self.subtests[name] + return None + + +class SubtestNode(TestNode): + def __init__(self, name): + """Tree node associated with a particular subtest in a manifest + + :param name: name of the subtest""" + TestNode.__init__(self, name) + + @property + def is_empty(self): + if self._data: + return False + return True + + +def get_manifest(metadata_root, test_path, url_base, run_info): + """Get the ExpectedManifest for a particular test path, or None if there is no + metadata stored for that test path. + + :param metadata_root: Absolute path to the root of the metadata directory + :param test_path: Path to the test(s) relative to the test root + :param url_base: Base url for serving the tests in this manifest + :param run_info: Dictionary of properties of the test run for which the expectation + values should be computed. + """ + manifest_path = expected.expected_path(metadata_root, test_path) + try: + with open(manifest_path) as f: + return static.compile(f, + run_info, + data_cls_getter=data_cls_getter, + test_path=test_path, + url_base=url_base) + except IOError: + return None + +def get_dir_manifest(path, run_info): + """Get the ExpectedManifest for a particular test path, or None if there is no + metadata stored for that test path. + + :param path: Full path to the ini file + :param run_info: Dictionary of properties of the test run for which the expectation + values should be computed. + """ + try: + with open(path) as f: + return static.compile(f, + run_info, + data_cls_getter=lambda x,y: DirectoryManifest) + except IOError: + return None diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestinclude.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestinclude.py new file mode 100644 index 000000000000..f7229d504f13 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestinclude.py @@ -0,0 +1,149 @@ +"""Manifest structure used to store paths that should be included in a test run. + +The manifest is represented by a tree of IncludeManifest objects, the root +representing the file and each subnode representing a subdirectory that should +be included or excluded. +""" +import glob +import os +import urlparse + +from wptmanifest.node import DataNode +from wptmanifest.backends import conditional +from wptmanifest.backends.conditional import ManifestItem + + +class IncludeManifest(ManifestItem): + def __init__(self, node): + """Node in a tree structure representing the paths + that should be included or excluded from the test run. + + :param node: AST Node corresponding to this Node. + """ + ManifestItem.__init__(self, node) + self.child_map = {} + + @classmethod + def create(cls): + """Create an empty IncludeManifest tree""" + node = DataNode(None) + return cls(node) + + def append(self, child): + ManifestItem.append(self, child) + self.child_map[child.name] = child + assert len(self.child_map) == len(self.children) + + def include(self, test): + """Return a boolean indicating whether a particular test should be + included in a test run, based on the IncludeManifest tree rooted on + this object. + + :param test: The test object""" + path_components = self._get_components(test.url) + return self._include(test, path_components) + + def _include(self, test, path_components): + if path_components: + next_path_part = path_components.pop() + if next_path_part in self.child_map: + return self.child_map[next_path_part]._include(test, path_components) + + node = self + while node: + try: + skip_value = self.get("skip", {"test_type": test.item_type}).lower() + assert skip_value in ("true", "false") + return skip_value != "true" + except KeyError: + if node.parent is not None: + node = node.parent + else: + # Include by default + return True + + def _get_components(self, url): + rv = [] + url_parts = urlparse.urlsplit(url) + variant = "" + if url_parts.query: + variant += "?" + url_parts.query + if url_parts.fragment: + variant += "#" + url_parts.fragment + if variant: + rv.append(variant) + rv.extend([item for item in reversed(url_parts.path.split("/")) if item]) + return rv + + def _add_rule(self, test_manifests, url, direction): + maybe_path = os.path.join(os.path.abspath(os.curdir), url) + rest, last = os.path.split(maybe_path) + fragment = query = None + if "#" in last: + last, fragment = last.rsplit("#", 1) + if "?" in last: + last, query = last.rsplit("?", 1) + + maybe_path = os.path.join(rest, last) + paths = glob.glob(maybe_path) + + if paths: + urls = [] + for path in paths: + for manifest, data in test_manifests.iteritems(): + found = False + rel_path = os.path.relpath(path, data["tests_path"]) + for test in manifest.iterpath(rel_path): + if not hasattr(test, "url"): + continue + url = test.url + if query or fragment: + parsed = urlparse.urlparse(url) + if ((query and query != parsed.query) or + (fragment and fragment != parsed.fragment)): + continue + urls.append(url) + found = True + if found: + break + else: + urls = [url] + + assert direction in ("include", "exclude") + + for url in urls: + components = self._get_components(url) + + node = self + while components: + component = components.pop() + if component not in node.child_map: + new_node = IncludeManifest(DataNode(component)) + node.append(new_node) + new_node.set("skip", node.get("skip", {})) + + node = node.child_map[component] + + skip = False if direction == "include" else True + node.set("skip", str(skip)) + + def add_include(self, test_manifests, url_prefix): + """Add a rule indicating that tests under a url path + should be included in test runs + + :param url_prefix: The url prefix to include + """ + return self._add_rule(test_manifests, url_prefix, "include") + + def add_exclude(self, test_manifests, url_prefix): + """Add a rule indicating that tests under a url path + should be excluded from test runs + + :param url_prefix: The url prefix to exclude + """ + return self._add_rule(test_manifests, url_prefix, "exclude") + + +def get_manifest(manifest_path): + with open(manifest_path) as f: + return conditional.compile(f, data_cls_getter=lambda x, y: IncludeManifest) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py new file mode 100644 index 000000000000..07e623c5d1bb --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py @@ -0,0 +1,460 @@ +import os +import urlparse +from collections import namedtuple, defaultdict + +from wptmanifest.node import (DataNode, ConditionalNode, BinaryExpressionNode, + BinaryOperatorNode, VariableNode, StringNode, NumberNode, + UnaryExpressionNode, UnaryOperatorNode, KeyValueNode) +from wptmanifest.backends import conditional +from wptmanifest.backends.conditional import ManifestItem + +import expected + +"""Manifest structure used to update the expected results of a test + +Each manifest file is represented by an ExpectedManifest that has one +or more TestNode children, one per test in the manifest. Each +TestNode has zero or more SubtestNode children, one for each known +subtest of the test. + +In these representations, conditionals expressions in the manifest are +not evaluated upfront but stored as python functions to be evaluated +at runtime. + +When a result for a test is to be updated set_result on the +[Sub]TestNode is called to store the new result, alongside the +existing conditional that result's run info matched, if any. Once all +new results are known, coalesce_expected is called to compute the new +set of results and conditionals. The AST of the underlying parsed manifest +is updated with the changes, and the result is serialised to a file. +""" + +class ConditionError(Exception): + pass + +Result = namedtuple("Result", ["run_info", "status"]) + + +def data_cls_getter(output_node, visited_node): + # visited_node is intentionally unused + if output_node is None: + return ExpectedManifest + elif isinstance(output_node, ExpectedManifest): + return TestNode + elif isinstance(output_node, TestNode): + return SubtestNode + else: + raise ValueError + + +class ExpectedManifest(ManifestItem): + def __init__(self, node, test_path=None, url_base=None, property_order=None, + boolean_properties=None): + """Object representing all the tests in a particular manifest + + :param node: AST Node associated with this object. If this is None, + a new AST is created to associate with this manifest. + :param test_path: Path of the test file associated with this manifest. + :param url_base: Base url for serving the tests in this manifest. + :param property_order: List of properties to use in expectation metadata + from most to least significant. + :param boolean_properties: Set of properties in property_order that should + be treated as boolean. + """ + if node is None: + node = DataNode(None) + ManifestItem.__init__(self, node) + self.child_map = {} + self.test_path = test_path + self.url_base = url_base + assert self.url_base is not None + self.modified = False + self.boolean_properties = boolean_properties + self.property_order = property_order + + def append(self, child): + ManifestItem.append(self, child) + if child.id in self.child_map: + print "Warning: Duplicate heading %s" % child.id + self.child_map[child.id] = child + + def _remove_child(self, child): + del self.child_map[child.id] + ManifestItem._remove_child(self, child) + + def get_test(self, test_id): + """Return a TestNode by test id, or None if no test matches + + :param test_id: The id of the test to look up""" + + return self.child_map[test_id] + + def has_test(self, test_id): + """Boolean indicating whether the current test has a known child test + with id test id + + :param test_id: The id of the test to look up""" + + return test_id in self.child_map + + @property + def url(self): + return urlparse.urljoin(self.url_base, + "/".join(self.test_path.split(os.path.sep))) + +class TestNode(ManifestItem): + def __init__(self, node): + """Tree node associated with a particular test in a manifest + + :param node: AST node associated with the test""" + + ManifestItem.__init__(self, node) + self.updated_expected = [] + self.new_expected = [] + self.subtests = {} + self.default_status = None + self._from_file = True + + @classmethod + def create(cls, test_type, test_id): + """Create a TestNode corresponding to a given test + + :param test_type: The type of the test + :param test_id: The id of the test""" + + url = test_id + name = url.split("/")[-1] + node = DataNode(name) + self = cls(node) + + self.set("type", test_type) + self._from_file = False + return self + + @property + def is_empty(self): + required_keys = set(["type"]) + if set(self._data.keys()) != required_keys: + return False + return all(child.is_empty for child in self.children) + + @property + def test_type(self): + """The type of the test represented by this TestNode""" + + return self.get("type", None) + + @property + def id(self): + """The id of the test represented by this TestNode""" + return urlparse.urljoin(self.parent.url, self.name) + + def disabled(self, run_info): + """Boolean indicating whether this test is disabled when run in an + environment with the given run_info + + :param run_info: Dictionary of run_info parameters""" + + return self.get("disabled", run_info) is not None + + def set_result(self, run_info, result): + """Set the result of the test in a particular run + + :param run_info: Dictionary of run_info parameters corresponding + to this run + :param result: Status of the test in this run""" + + if self.default_status is not None: + assert self.default_status == result.default_expected + else: + self.default_status = result.default_expected + + # Add this result to the list of results satisfying + # any condition in the list of updated results it matches + for (cond, values) in self.updated_expected: + if cond(run_info): + values.append(Result(run_info, result.status)) + if result.status != cond.value: + self.root.modified = True + break + else: + # We didn't find a previous value for this + self.new_expected.append(Result(run_info, result.status)) + self.root.modified = True + + def coalesce_expected(self): + """Update the underlying manifest AST for this test based on all the + added results. + + This will update existing conditionals if they got the same result in + all matching runs in the updated results, will delete existing conditionals + that get more than one different result in the updated run, and add new + conditionals for anything that doesn't match an existing conditional. + + Conditionals not matched by any added result are not changed.""" + + final_conditionals = [] + + try: + unconditional_status = self.get("expected") + except KeyError: + unconditional_status = self.default_status + + for conditional_value, results in self.updated_expected: + if not results: + # The conditional didn't match anything in these runs so leave it alone + final_conditionals.append(conditional_value) + elif all(results[0].status == result.status for result in results): + # All the new values for this conditional matched, so update the node + result = results[0] + if (result.status == unconditional_status and + conditional_value.condition_node is not None): + if "expected" in self: + self.remove_value("expected", conditional_value) + else: + conditional_value.value = result.status + final_conditionals.append(conditional_value) + elif conditional_value.condition_node is not None: + # Blow away the existing condition and rebuild from scratch + # This isn't sure to work if we have a conditional later that matches + # these values too, but we can hope, verify that we get the results + # we expect, and if not let a human sort it out + self.remove_value("expected", conditional_value) + self.new_expected.extend(results) + elif conditional_value.condition_node is None: + self.new_expected.extend(result for result in results + if result.status != unconditional_status) + + # It is an invariant that nothing in new_expected matches an existing + # condition except for the default condition + + if self.new_expected: + if all(self.new_expected[0].status == result.status + for result in self.new_expected) and not self.updated_expected: + status = self.new_expected[0].status + if status != self.default_status: + self.set("expected", status, condition=None) + final_conditionals.append(self._data["expected"][-1]) + else: + try: + conditionals = group_conditionals( + self.new_expected, + property_order=self.root.property_order, + boolean_properties=self.root.boolean_properties) + except ConditionError: + print "Conflicting test results for %s, cannot update" % self.root.test_path + return + for conditional_node, status in conditionals: + if status != unconditional_status: + self.set("expected", status, condition=conditional_node.children[0]) + final_conditionals.append(self._data["expected"][-1]) + + if ("expected" in self._data and + len(self._data["expected"]) > 0 and + self._data["expected"][-1].condition_node is None and + self._data["expected"][-1].value == self.default_status): + + self.remove_value("expected", self._data["expected"][-1]) + + if ("expected" in self._data and + len(self._data["expected"]) == 0): + for child in self.node.children: + if (isinstance(child, KeyValueNode) and + child.data == "expected"): + child.remove() + break + + def _add_key_value(self, node, values): + ManifestItem._add_key_value(self, node, values) + if node.data == "expected": + self.updated_expected = [] + for value in values: + self.updated_expected.append((value, [])) + + def clear_expected(self): + """Clear all the expected data for this test and all of its subtests""" + + self.updated_expected = [] + if "expected" in self._data: + for child in self.node.children: + if (isinstance(child, KeyValueNode) and + child.data == "expected"): + child.remove() + del self._data["expected"] + break + + for subtest in self.subtests.itervalues(): + subtest.clear_expected() + + def append(self, node): + child = ManifestItem.append(self, node) + self.subtests[child.name] = child + + def get_subtest(self, name): + """Return a SubtestNode corresponding to a particular subtest of + the current test, creating a new one if no subtest with that name + already exists. + + :param name: Name of the subtest""" + + if name in self.subtests: + return self.subtests[name] + else: + subtest = SubtestNode.create(name) + self.append(subtest) + return subtest + + +class SubtestNode(TestNode): + def __init__(self, node): + assert isinstance(node, DataNode) + TestNode.__init__(self, node) + + @classmethod + def create(cls, name): + node = DataNode(name) + self = cls(node) + return self + + @property + def is_empty(self): + if self._data: + return False + return True + + +def group_conditionals(values, property_order=None, boolean_properties=None): + """Given a list of Result objects, return a list of + (conditional_node, status) pairs representing the conditional + expressions that are required to match each status + + :param values: List of Results + :param property_order: List of properties to use in expectation metadata + from most to least significant. + :param boolean_properties: Set of properties in property_order that should + be treated as boolean.""" + + by_property = defaultdict(set) + for run_info, status in values: + for prop_name, prop_value in run_info.iteritems(): + by_property[(prop_name, prop_value)].add(status) + + if property_order is None: + property_order = ["debug", "os", "version", "processor", "bits"] + + if boolean_properties is None: + boolean_properties = set(["debug"]) + else: + boolean_properties = set(boolean_properties) + + # If we have more than one value, remove any properties that are common + # for all the values + if len(values) > 1: + for key, statuses in by_property.copy().iteritems(): + if len(statuses) == len(values): + del by_property[key] + if not by_property: + raise ConditionError + + properties = set(item[0] for item in by_property.iterkeys()) + include_props = [] + + for prop in property_order: + if prop in properties: + include_props.append(prop) + + conditions = {} + + for run_info, status in values: + prop_set = tuple((prop, run_info[prop]) for prop in include_props) + if prop_set in conditions: + continue + + expr = make_expr(prop_set, status, boolean_properties=boolean_properties) + conditions[prop_set] = (expr, status) + + return conditions.values() + + +def make_expr(prop_set, status, boolean_properties=None): + """Create an AST that returns the value ``status`` given all the + properties in prop_set match. + + :param prop_set: tuple of (property name, value) pairs for each + property in this expression and the value it must match + :param status: Status on RHS when all the given properties match + :param boolean_properties: Set of properties in property_order that should + be treated as boolean. + """ + root = ConditionalNode() + + assert len(prop_set) > 0 + + expressions = [] + for prop, value in prop_set: + number_types = (int, float, long) + value_cls = (NumberNode + if type(value) in number_types + else StringNode) + if prop not in boolean_properties: + expressions.append( + BinaryExpressionNode( + BinaryOperatorNode("=="), + VariableNode(prop), + value_cls(unicode(value)) + )) + else: + if value: + expressions.append(VariableNode(prop)) + else: + expressions.append( + UnaryExpressionNode( + UnaryOperatorNode("not"), + VariableNode(prop) + )) + if len(expressions) > 1: + prev = expressions[-1] + for curr in reversed(expressions[:-1]): + node = BinaryExpressionNode( + BinaryOperatorNode("and"), + curr, + prev) + prev = node + else: + node = expressions[0] + + root.append(node) + root.append(StringNode(status)) + + return root + + +def get_manifest(metadata_root, test_path, url_base, property_order=None, + boolean_properties=None): + """Get the ExpectedManifest for a particular test path, or None if there is no + metadata stored for that test path. + + :param metadata_root: Absolute path to the root of the metadata directory + :param test_path: Path to the test(s) relative to the test root + :param url_base: Base url for serving the tests in this manifest + :param property_order: List of properties to use in expectation metadata + from most to least significant. + :param boolean_properties: Set of properties in property_order that should + be treated as boolean.""" + manifest_path = expected.expected_path(metadata_root, test_path) + try: + with open(manifest_path) as f: + return compile(f, test_path, url_base, property_order=property_order, + boolean_properties=boolean_properties) + except IOError: + return None + + +def compile(manifest_file, test_path, url_base, property_order=None, + boolean_properties=None): + return conditional.compile(manifest_file, + data_cls_getter=data_cls_getter, + test_path=test_path, + url_base=url_base, + property_order=property_order, + boolean_properties=boolean_properties) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/metadata.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/metadata.py new file mode 100644 index 000000000000..7f0e29b2190c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/metadata.py @@ -0,0 +1,351 @@ +import os +import shutil +import sys +import tempfile +import types +import uuid +from collections import defaultdict + +from mozlog import reader +from mozlog import structuredlog + +import expected +import manifestupdate +import testloader +import wptmanifest +import wpttest +from vcs import git +manifest = None # Module that will be imported relative to test_root +manifestitem = None + +logger = structuredlog.StructuredLogger("web-platform-tests") + + +def load_test_manifests(serve_root, test_paths): + do_delayed_imports(serve_root) + manifest_loader = testloader.ManifestLoader(test_paths, False) + return manifest_loader.load() + + +def update_expected(test_paths, serve_root, log_file_names, + rev_old=None, rev_new="HEAD", ignore_existing=False, + sync_root=None, property_order=None, boolean_properties=None): + """Update the metadata files for web-platform-tests based on + the results obtained in a previous run""" + + manifests = load_test_manifests(serve_root, test_paths) + + change_data = {} + + if sync_root is not None: + if rev_old is not None: + rev_old = git("rev-parse", rev_old, repo=sync_root).strip() + rev_new = git("rev-parse", rev_new, repo=sync_root).strip() + + if rev_old is not None: + change_data = load_change_data(rev_old, rev_new, repo=sync_root) + + + expected_map_by_manifest = update_from_logs(manifests, + *log_file_names, + ignore_existing=ignore_existing, + property_order=property_order, + boolean_properties=boolean_properties) + + for test_manifest, expected_map in expected_map_by_manifest.iteritems(): + url_base = manifests[test_manifest]["url_base"] + metadata_path = test_paths[url_base]["metadata_path"] + write_changes(metadata_path, expected_map) + + results_changed = [item.test_path for item in expected_map.itervalues() if item.modified] + + return unexpected_changes(manifests, change_data, results_changed) + + +def do_delayed_imports(serve_root): + global manifest, manifestitem + from manifest import manifest, item as manifestitem + + +def files_in_repo(repo_root): + return git("ls-tree", "-r", "--name-only", "HEAD").split("\n") + + +def rev_range(rev_old, rev_new, symmetric=False): + joiner = ".." if not symmetric else "..." + return "".join([rev_old, joiner, rev_new]) + + +def paths_changed(rev_old, rev_new, repo): + data = git("diff", "--name-status", rev_range(rev_old, rev_new), repo=repo) + lines = [tuple(item.strip() for item in line.strip().split("\t", 1)) + for line in data.split("\n") if line.strip()] + output = set(lines) + return output + + +def load_change_data(rev_old, rev_new, repo): + changes = paths_changed(rev_old, rev_new, repo) + rv = {} + status_keys = {"M": "modified", + "A": "new", + "D": "deleted"} + # TODO: deal with renames + for item in changes: + rv[item[1]] = status_keys[item[0]] + return rv + + +def unexpected_changes(manifests, change_data, files_changed): + files_changed = set(files_changed) + + root_manifest = None + for manifest, paths in manifests.iteritems(): + if paths["url_base"] == "/": + root_manifest = manifest + break + else: + return [] + + rv = [] + + return [fn for _, fn, _ in root_manifest if fn in files_changed and change_data.get(fn) != "M"] + +# For each testrun +# Load all files and scan for the suite_start entry +# Build a hash of filename: properties +# For each different set of properties, gather all chunks +# For each chunk in the set of chunks, go through all tests +# for each test, make a map of {conditionals: [(platform, new_value)]} +# Repeat for each platform +# For each test in the list of tests: +# for each conditional: +# If all the new values match (or there aren't any) retain that conditional +# If any new values mismatch mark the test as needing human attention +# Check if all the RHS values are the same; if so collapse the conditionals + + +def update_from_logs(manifests, *log_filenames, **kwargs): + ignore_existing = kwargs.get("ignore_existing", False) + property_order = kwargs.get("property_order") + boolean_properties = kwargs.get("boolean_properties") + + expected_map = {} + id_test_map = {} + + for test_manifest, paths in manifests.iteritems(): + expected_map_manifest, id_path_map_manifest = create_test_tree( + paths["metadata_path"], + test_manifest, + property_order=property_order, + boolean_properties=boolean_properties) + expected_map[test_manifest] = expected_map_manifest + id_test_map.update(id_path_map_manifest) + + updater = ExpectedUpdater(manifests, expected_map, id_test_map, + ignore_existing=ignore_existing) + for log_filename in log_filenames: + with open(log_filename) as f: + updater.update_from_log(f) + + for manifest_expected in expected_map.itervalues(): + for tree in manifest_expected.itervalues(): + for test in tree.iterchildren(): + for subtest in test.iterchildren(): + subtest.coalesce_expected() + test.coalesce_expected() + + return expected_map + +def directory_manifests(metadata_path): + rv = [] + for dirpath, dirname, filenames in os.walk(metadata_path): + if "__dir__.ini" in filenames: + rel_path = os.path.relpath(dirpath, metadata_path) + rv.append(os.path.join(rel_path, "__dir__.ini")) + return rv + +def write_changes(metadata_path, expected_map): + # First write the new manifest files to a temporary directory + temp_path = tempfile.mkdtemp(dir=os.path.split(metadata_path)[0]) + write_new_expected(temp_path, expected_map) + + # Keep all __dir__.ini files (these are not in expected_map because they + # aren't associated with a specific test) + keep_files = directory_manifests(metadata_path) + + # Copy all files in the root to the temporary location since + # these cannot be ini files + keep_files.extend(item for item in os.listdir(metadata_path) if + not os.path.isdir(os.path.join(metadata_path, item))) + + for item in keep_files: + dest_dir = os.path.dirname(os.path.join(temp_path, item)) + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + shutil.copyfile(os.path.join(metadata_path, item), + os.path.join(temp_path, item)) + + # Then move the old manifest files to a new location + temp_path_2 = metadata_path + str(uuid.uuid4()) + os.rename(metadata_path, temp_path_2) + # Move the new files to the destination location and remove the old files + os.rename(temp_path, metadata_path) + shutil.rmtree(temp_path_2) + + +def write_new_expected(metadata_path, expected_map): + # Serialize the data back to a file + for tree in expected_map.itervalues(): + if not tree.is_empty: + manifest_str = wptmanifest.serialize(tree.node, skip_empty_data=True) + assert manifest_str != "" + path = expected.expected_path(metadata_path, tree.test_path) + dir = os.path.split(path)[0] + if not os.path.exists(dir): + os.makedirs(dir) + with open(path, "w") as f: + f.write(manifest_str) + + +class ExpectedUpdater(object): + def __init__(self, test_manifests, expected_tree, id_path_map, ignore_existing=False): + self.test_manifests = test_manifests + self.expected_tree = expected_tree + self.id_path_map = id_path_map + self.ignore_existing = ignore_existing + self.run_info = None + self.action_map = {"suite_start": self.suite_start, + "test_start": self.test_start, + "test_status": self.test_status, + "test_end": self.test_end} + self.tests_visited = {} + + self.test_cache = {} + + def update_from_log(self, log_file): + self.run_info = None + log_reader = reader.read(log_file) + reader.each_log(log_reader, self.action_map) + + def suite_start(self, data): + self.run_info = data["run_info"] + + def test_id(self, id): + if type(id) in types.StringTypes: + return id + else: + return tuple(id) + + def test_start(self, data): + test_id = self.test_id(data["test"]) + try: + test_manifest, test = self.id_path_map[test_id] + expected_node = self.expected_tree[test_manifest][test].get_test(test_id) + except KeyError: + print "Test not found %s, skipping" % test_id + return + self.test_cache[test_id] = expected_node + + if test_id not in self.tests_visited: + if self.ignore_existing: + expected_node.clear_expected() + self.tests_visited[test_id] = set() + + def test_status(self, data): + test_id = self.test_id(data["test"]) + test = self.test_cache.get(test_id) + if test is None: + return + test_cls = wpttest.manifest_test_cls[test.test_type] + + subtest = test.get_subtest(data["subtest"]) + + self.tests_visited[test.id].add(data["subtest"]) + + result = test_cls.subtest_result_cls( + data["subtest"], + data["status"], + data.get("message")) + + subtest.set_result(self.run_info, result) + + def test_end(self, data): + test_id = self.test_id(data["test"]) + test = self.test_cache.get(test_id) + if test is None: + return + test_cls = wpttest.manifest_test_cls[test.test_type] + + if data["status"] == "SKIP": + return + + result = test_cls.result_cls( + data["status"], + data.get("message")) + + test.set_result(self.run_info, result) + del self.test_cache[test_id] + + +def create_test_tree(metadata_path, test_manifest, property_order=None, + boolean_properties=None): + expected_map = {} + id_test_map = {} + exclude_types = frozenset(["stub", "helper", "manual", "support", "conformancechecker"]) + all_types = [item.item_type for item in manifestitem.__dict__.itervalues() + if type(item) == type and + issubclass(item, manifestitem.ManifestItem) and + item.item_type is not None] + include_types = set(all_types) - exclude_types + for _, test_path, tests in test_manifest.itertypes(*include_types): + expected_data = load_expected(test_manifest, metadata_path, test_path, tests, + property_order=property_order, + boolean_properties=boolean_properties) + if expected_data is None: + expected_data = create_expected(test_manifest, + test_path, + tests, + property_order=property_order, + boolean_properties=boolean_properties) + + for test in tests: + id_test_map[test.id] = (test_manifest, test) + expected_map[test] = expected_data + + return expected_map, id_test_map + + +def create_expected(test_manifest, test_path, tests, property_order=None, + boolean_properties=None): + expected = manifestupdate.ExpectedManifest(None, test_path, test_manifest.url_base, + property_order=property_order, + boolean_properties=boolean_properties) + for test in tests: + expected.append(manifestupdate.TestNode.create(test.item_type, test.id)) + return expected + + +def load_expected(test_manifest, metadata_path, test_path, tests, property_order=None, + boolean_properties=None): + expected_manifest = manifestupdate.get_manifest(metadata_path, + test_path, + test_manifest.url_base, + property_order=property_order, + boolean_properties=boolean_properties) + if expected_manifest is None: + return + + tests_by_id = {item.id: item for item in tests} + + # Remove expected data for tests that no longer exist + for test in expected_manifest.iterchildren(): + if not test.id in tests_by_id: + test.remove() + + # Add tests that don't have expected data + for test in tests: + if not expected_manifest.has_test(test.id): + expected_manifest.append(manifestupdate.TestNode.create(test.item_type, test.id)) + + return expected_manifest diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/products.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/products.py new file mode 100644 index 000000000000..c077f95dfd95 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/products.py @@ -0,0 +1,69 @@ +import os +import importlib +import imp + +from .browsers import product_list + +def products_enabled(config): + names = config.get("products", {}).keys() + if not names: + return product_list + else: + return names + +def product_module(config, product): + here = os.path.join(os.path.split(__file__)[0]) + product_dir = os.path.join(here, "browsers") + + if product not in products_enabled(config): + raise ValueError("Unknown product %s" % product) + + path = config.get("products", {}).get(product, None) + if path: + module = imp.load_source('wptrunner.browsers.' + product, path) + else: + module = importlib.import_module("wptrunner.browsers." + product) + + if not hasattr(module, "__wptrunner__"): + raise ValueError("Product module does not define __wptrunner__ variable") + + return module + + +def load_product(config, product): + module = product_module(config, product) + data = module.__wptrunner__ + + check_args = getattr(module, data["check_args"]) + browser_cls = getattr(module, data["browser"]) + browser_kwargs = getattr(module, data["browser_kwargs"]) + executor_kwargs = getattr(module, data["executor_kwargs"]) + env_options = getattr(module, data["env_options"])() + env_extras = getattr(module, data["env_extras"]) + run_info_extras = (getattr(module, data["run_info_extras"]) + if "run_info_extras" in data else lambda **kwargs:{}) + + executor_classes = {} + for test_type, cls_name in data["executor"].iteritems(): + cls = getattr(module, cls_name) + executor_classes[test_type] = cls + + return (check_args, + browser_cls, browser_kwargs, + executor_classes, executor_kwargs, + env_options, env_extras, run_info_extras) + + +def load_product_update(config, product): + """Return tuple of (property_order, boolean_properties) indicating the + run_info properties to use when constructing the expectation data for + this product. None for either key indicates that the default keys + appropriate for distinguishing based on platform will be used.""" + + module = product_module(config, product) + data = module.__wptrunner__ + + update_properties = (getattr(module, data["update_properties"])() + if "update_properties" in data else (None, None)) + + return update_properties diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/reduce.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/reduce.py new file mode 100644 index 000000000000..d245ee3602b9 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/reduce.py @@ -0,0 +1,193 @@ +import sys +import tempfile +from cStringIO import StringIO +from collections import defaultdict + +import wptrunner +import wpttest + +from mozlog import commandline, reader + +logger = None + + +def setup_logging(args, defaults): + global logger + logger = commandline.setup_logging("web-platform-tests-unstable", args, defaults) + wptrunner.setup_stdlib_logger() + + for name in args.keys(): + if name.startswith("log_"): + args.pop(name) + + return logger + + +def group(items, size): + rv = [] + i = 0 + while i < len(items): + rv.append(items[i:i + size]) + i += size + + return rv + + +def next_power_of_two(num): + rv = 1 + while rv < num: + rv = rv << 1 + return rv + + +class Reducer(object): + def __init__(self, target, **kwargs): + self.target = target + + self.test_type = kwargs["test_types"][0] + run_info = wpttest.get_run_info(kwargs["metadata_root"], + kwargs["product"], + debug=False) + test_filter = wptrunner.TestFilter(include=kwargs["include"]) + self.test_loader = wptrunner.TestLoader(kwargs["tests_root"], + kwargs["metadata_root"], + [self.test_type], + run_info, + manifest_filer=test_filter) + if kwargs["repeat"] == 1: + logger.critical("Need to specify --repeat with more than one repetition") + sys.exit(1) + self.kwargs = kwargs + + def run(self): + all_tests = self.get_initial_tests() + + tests = all_tests[:-1] + target_test = [all_tests[-1]] + + if self.unstable(target_test): + return target_test + + if not self.unstable(all_tests): + return [] + + chunk_size = next_power_of_two(int(len(tests) / 2)) + logger.debug("Using chunk size %i" % chunk_size) + + while chunk_size >= 1: + logger.debug("%i tests remain" % len(tests)) + chunks = group(tests, chunk_size) + chunk_results = [None] * len(chunks) + + for i, chunk in enumerate(chunks): + logger.debug("Running chunk %i/%i of size %i" % (i + 1, len(chunks), chunk_size)) + trial_tests = [] + chunk_str = "" + for j, inc_chunk in enumerate(chunks): + if i != j and chunk_results[j] in (None, False): + chunk_str += "+" + trial_tests.extend(inc_chunk) + else: + chunk_str += "-" + logger.debug("Using chunks %s" % chunk_str) + trial_tests.extend(target_test) + + chunk_results[i] = self.unstable(trial_tests) + + # if i == len(chunks) - 2 and all(item is False for item in chunk_results[:-1]): + # Dangerous? optimisation that if you got stability for 0..N-1 chunks + # it must be unstable with the Nth chunk + # chunk_results[i+1] = True + # continue + + new_tests = [] + keep_str = "" + for result, chunk in zip(chunk_results, chunks): + if not result: + keep_str += "+" + new_tests.extend(chunk) + else: + keep_str += "-" + + logger.debug("Keeping chunks %s" % keep_str) + + tests = new_tests + + chunk_size = int(chunk_size / 2) + + return tests + target_test + + def unstable(self, tests): + logger.debug("Running with %i tests" % len(tests)) + + self.test_loader.tests = {self.test_type: tests} + + stdout, stderr = sys.stdout, sys.stderr + sys.stdout = StringIO() + sys.stderr = StringIO() + + with tempfile.NamedTemporaryFile() as f: + args = self.kwargs.copy() + args["log_raw"] = [f] + args["capture_stdio"] = False + wptrunner.setup_logging(args, {}) + wptrunner.run_tests(test_loader=self.test_loader, **args) + wptrunner.logger.remove_handler(wptrunner.logger.handlers[0]) + is_unstable = self.log_is_unstable(f) + + sys.stdout, sys.stderr = stdout, stderr + + logger.debug("Result was unstable with chunk removed" + if is_unstable else "stable") + + return is_unstable + + def log_is_unstable(self, log_f): + log_f.seek(0) + + statuses = defaultdict(set) + + def handle_status(item): + if item["test"] == self.target: + statuses[item["subtest"]].add(item["status"]) + + def handle_end(item): + if item["test"] == self.target: + statuses[None].add(item["status"]) + + reader.each_log(reader.read(log_f), + {"test_status": handle_status, + "test_end": handle_end}) + + logger.debug(str(statuses)) + + if not statuses: + logger.error("Didn't get any useful output from wptrunner") + log_f.seek(0) + for item in reader.read(log_f): + logger.debug(item) + return None + + return any(len(item) > 1 for item in statuses.itervalues()) + + def get_initial_tests(self): + # Need to pass in arguments + + all_tests = self.test_loader.tests[self.test_type] + tests = [] + for item in all_tests: + tests.append(item) + if item.url == self.target: + break + + logger.debug("Starting with tests: %s" % ("\n".join(item.id for item in tests))) + + return tests + + +def do_reduce(**kwargs): + target = kwargs.pop("target") + reducer = Reducer(target, **kwargs) + + unstable_set = reducer.run() + return unstable_set diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/testharnessreport-servo.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/testharnessreport-servo.js new file mode 100644 index 000000000000..b672aea9a254 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testharnessreport-servo.js @@ -0,0 +1,17 @@ +var props = {output:%(output)d}; +var start_loc = document.createElement('a'); +start_loc.href = location.href; +setup(props); + +add_completion_callback(function (tests, harness_status) { + var id = start_loc.pathname + start_loc.search + start_loc.hash; + console.log("ALERT: RESULT: " + JSON.stringify([ + id, + harness_status.status, + harness_status.message, + harness_status.stack, + tests.map(function(t) { + return [t.name, t.status, t.message, t.stack] + }), + ])); +}); diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/testharnessreport-servodriver.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/testharnessreport-servodriver.js new file mode 100644 index 000000000000..c88841360470 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testharnessreport-servodriver.js @@ -0,0 +1,23 @@ +setup({output:%(output)d}); + +add_completion_callback(function() { + add_completion_callback(function (tests, status) { + var subtest_results = tests.map(function(x) { + return [x.name, x.status, x.message, x.stack] + }); + var id = location.pathname + location.search + location.hash; + var results = JSON.stringify([id, + status.status, + status.message, + status.stack, + subtest_results]); + (function done() { + if (window.__wd_results_callback__) { + clearTimeout(__wd_results_timer__); + __wd_results_callback__(results) + } else { + setTimeout(done, 20); + } + })() + }) +}); diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/testharnessreport.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/testharnessreport.js new file mode 100644 index 000000000000..62ddaffb443c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testharnessreport.js @@ -0,0 +1,13 @@ +var props = {output:%(output)d, + explicit_timeout: true, + message_events: ["completion"]}; + +if (window.opener && "timeout_multiplier" in window.opener) { + props["timeout_multiplier"] = window.opener.timeout_multiplier; +} + +if (window.opener && window.opener.explicit_timeout) { + props["explicit_timeout"] = window.opener.explicit_timeout; +} + +setup(props); diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/testloader.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/testloader.py new file mode 100644 index 000000000000..74dce4aafe33 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testloader.py @@ -0,0 +1,638 @@ +import hashlib +import json +import os +import urlparse +from abc import ABCMeta, abstractmethod +from Queue import Empty +from collections import defaultdict, OrderedDict, deque +from multiprocessing import Queue + +import manifestinclude +import manifestexpected +import wpttest +from mozlog import structured + +manifest = None +manifest_update = None + +def do_delayed_imports(): + # This relies on an already loaded module having set the sys.path correctly :( + global manifest, manifest_update + from manifest import manifest + from manifest import update as manifest_update + +class TestChunker(object): + def __init__(self, total_chunks, chunk_number): + self.total_chunks = total_chunks + self.chunk_number = chunk_number + assert self.chunk_number <= self.total_chunks + self.logger = structured.get_default_logger() + assert self.logger + + def __call__(self, manifest): + raise NotImplementedError + + +class Unchunked(TestChunker): + def __init__(self, *args, **kwargs): + TestChunker.__init__(self, *args, **kwargs) + assert self.total_chunks == 1 + + def __call__(self, manifest): + for item in manifest: + yield item + + +class HashChunker(TestChunker): + def __call__(self, manifest): + chunk_index = self.chunk_number - 1 + for test_type, test_path, tests in manifest: + h = int(hashlib.md5(test_path).hexdigest(), 16) + if h % self.total_chunks == chunk_index: + yield test_type, test_path, tests + + +class DirectoryHashChunker(TestChunker): + """Like HashChunker except the directory is hashed. + + This ensures that all tests in the same directory end up in the same + chunk. + """ + def __call__(self, manifest): + chunk_index = self.chunk_number - 1 + for test_type, test_path, tests in manifest: + h = int(hashlib.md5(os.path.dirname(test_path)).hexdigest(), 16) + if h % self.total_chunks == chunk_index: + yield test_type, test_path, tests + + +class EqualTimeChunker(TestChunker): + def _group_by_directory(self, manifest_items): + """Split the list of manifest items into a ordered dict that groups tests in + so that anything in the same subdirectory beyond a depth of 3 is in the same + group. So all tests in a/b/c, a/b/c/d and a/b/c/e will be grouped together + and separate to tests in a/b/f + + Returns: tuple (ordered dict of {test_dir: PathData}, total estimated runtime) + """ + + class PathData(object): + def __init__(self, path): + self.path = path + self.time = 0 + self.tests = [] + + by_dir = OrderedDict() + total_time = 0 + + for i, (test_type, test_path, tests) in enumerate(manifest_items): + test_dir = tuple(os.path.split(test_path)[0].split(os.path.sep)[:3]) + + if not test_dir in by_dir: + by_dir[test_dir] = PathData(test_dir) + + data = by_dir[test_dir] + time = sum(wpttest.DEFAULT_TIMEOUT if test.timeout != + "long" else wpttest.LONG_TIMEOUT for test in tests) + data.time += time + total_time += time + data.tests.append((test_type, test_path, tests)) + + return by_dir, total_time + + def _maybe_remove(self, chunks, i, direction): + """Trial removing a chunk from one chunk to an adjacent one. + + :param chunks: - the list of all chunks + :param i: - the chunk index in the list of chunks to try removing from + :param direction: either "next" if we are going to move from the end to + the subsequent chunk, or "prev" if we are going to move + from the start into the previous chunk. + + :returns bool: Did a chunk get moved?""" + source_chunk = chunks[i] + if direction == "next": + target_chunk = chunks[i+1] + path_index = -1 + move_func = lambda: target_chunk.appendleft(source_chunk.pop()) + elif direction == "prev": + target_chunk = chunks[i-1] + path_index = 0 + move_func = lambda: target_chunk.append(source_chunk.popleft()) + else: + raise ValueError("Unexpected move direction %s" % direction) + + return self._maybe_move(source_chunk, target_chunk, path_index, move_func) + + def _maybe_add(self, chunks, i, direction): + """Trial adding a chunk from one chunk to an adjacent one. + + :param chunks: - the list of all chunks + :param i: - the chunk index in the list of chunks to try adding to + :param direction: either "next" if we are going to remove from the + the subsequent chunk, or "prev" if we are going to remove + from the the previous chunk. + + :returns bool: Did a chunk get moved?""" + target_chunk = chunks[i] + if direction == "next": + source_chunk = chunks[i+1] + path_index = 0 + move_func = lambda: target_chunk.append(source_chunk.popleft()) + elif direction == "prev": + source_chunk = chunks[i-1] + path_index = -1 + move_func = lambda: target_chunk.appendleft(source_chunk.pop()) + else: + raise ValueError("Unexpected move direction %s" % direction) + + return self._maybe_move(source_chunk, target_chunk, path_index, move_func) + + def _maybe_move(self, source_chunk, target_chunk, path_index, move_func): + """Move from one chunk to another, assess the change in badness, + and keep the move iff it decreases the badness score. + + :param source_chunk: chunk to move from + :param target_chunk: chunk to move to + :param path_index: 0 if we are moving from the start or -1 if we are moving from the + end + :param move_func: Function that actually moves between chunks""" + if len(source_chunk.paths) <= 1: + return False + + move_time = source_chunk.paths[path_index].time + + new_source_badness = self._badness(source_chunk.time - move_time) + new_target_badness = self._badness(target_chunk.time + move_time) + + delta_badness = ((new_source_badness + new_target_badness) - + (source_chunk.badness + target_chunk.badness)) + if delta_badness < 0: + move_func() + return True + + return False + + def _badness(self, time): + """Metric of badness for a specific chunk + + :param time: the time for a specific chunk""" + return (time - self.expected_time)**2 + + def _get_chunk(self, manifest_items): + by_dir, total_time = self._group_by_directory(manifest_items) + + if len(by_dir) < self.total_chunks: + raise ValueError("Tried to split into %i chunks, but only %i subdirectories included" % ( + self.total_chunks, len(by_dir))) + + self.expected_time = float(total_time) / self.total_chunks + + chunks = self._create_initial_chunks(by_dir) + + while True: + # Move a test from one chunk to the next until doing so no longer + # reduces the badness + got_improvement = self._update_chunks(chunks) + if not got_improvement: + break + + self.logger.debug(self.expected_time) + for i, chunk in chunks.iteritems(): + self.logger.debug("%i: %i, %i" % (i + 1, chunk.time, chunk.badness)) + + assert self._all_tests(by_dir) == self._chunked_tests(chunks) + + return self._get_tests(chunks) + + @staticmethod + def _all_tests(by_dir): + """Return a set of all tests in the manifest from a grouping by directory""" + return set(x[0] for item in by_dir.itervalues() + for x in item.tests) + + @staticmethod + def _chunked_tests(chunks): + """Return a set of all tests in the manifest from the chunk list""" + return set(x[0] for chunk in chunks.itervalues() + for path in chunk.paths + for x in path.tests) + + + def _create_initial_chunks(self, by_dir): + """Create an initial unbalanced list of chunks. + + :param by_dir: All tests in the manifest grouped by subdirectory + :returns list: A list of Chunk objects""" + + class Chunk(object): + def __init__(self, paths, index): + """List of PathData objects that together form a single chunk of + tests""" + self.paths = deque(paths) + self.time = sum(item.time for item in paths) + self.index = index + + def appendleft(self, path): + """Add a PathData object to the start of the chunk""" + self.paths.appendleft(path) + self.time += path.time + + def append(self, path): + """Add a PathData object to the end of the chunk""" + self.paths.append(path) + self.time += path.time + + def pop(self): + """Remove PathData object from the end of the chunk""" + assert len(self.paths) > 1 + self.time -= self.paths[-1].time + return self.paths.pop() + + def popleft(self): + """Remove PathData object from the start of the chunk""" + assert len(self.paths) > 1 + self.time -= self.paths[0].time + return self.paths.popleft() + + @property + def badness(self_): + """Badness metric for this chunk""" + return self._badness(self_.time) + + initial_size = len(by_dir) / self.total_chunks + chunk_boundaries = [initial_size * i + for i in xrange(self.total_chunks)] + [len(by_dir)] + + chunks = OrderedDict() + for i, lower in enumerate(chunk_boundaries[:-1]): + upper = chunk_boundaries[i + 1] + paths = by_dir.values()[lower:upper] + chunks[i] = Chunk(paths, i) + + assert self._all_tests(by_dir) == self._chunked_tests(chunks) + + return chunks + + def _update_chunks(self, chunks): + """Run a single iteration of the chunk update algorithm. + + :param chunks: - List of chunks + """ + #TODO: consider replacing this with a heap + sorted_chunks = sorted(chunks.values(), key=lambda x:-x.badness) + got_improvement = False + for chunk in sorted_chunks: + if chunk.time < self.expected_time: + f = self._maybe_add + else: + f = self._maybe_remove + + if chunk.index == 0: + order = ["next"] + elif chunk.index == self.total_chunks - 1: + order = ["prev"] + else: + if chunk.time < self.expected_time: + # First try to add a test from the neighboring chunk with the + # greatest total time + if chunks[chunk.index + 1].time > chunks[chunk.index - 1].time: + order = ["next", "prev"] + else: + order = ["prev", "next"] + else: + # First try to remove a test and add to the neighboring chunk with the + # lowest total time + if chunks[chunk.index + 1].time > chunks[chunk.index - 1].time: + order = ["prev", "next"] + else: + order = ["next", "prev"] + + for direction in order: + if f(chunks, chunk.index, direction): + got_improvement = True + break + + if got_improvement: + break + + return got_improvement + + def _get_tests(self, chunks): + """Return the list of tests corresponding to the chunk number we are running. + + :param chunks: List of chunks""" + tests = [] + for path in chunks[self.chunk_number - 1].paths: + tests.extend(path.tests) + + return tests + + def __call__(self, manifest_iter): + manifest = list(manifest_iter) + tests = self._get_chunk(manifest) + for item in tests: + yield item + + +class TestFilter(object): + def __init__(self, test_manifests, include=None, exclude=None, manifest_path=None): + if manifest_path is not None and include is None: + self.manifest = manifestinclude.get_manifest(manifest_path) + else: + self.manifest = manifestinclude.IncludeManifest.create() + + if include: + self.manifest.set("skip", "true") + for item in include: + self.manifest.add_include(test_manifests, item) + + if exclude: + for item in exclude: + self.manifest.add_exclude(test_manifests, item) + + def __call__(self, manifest_iter): + for test_type, test_path, tests in manifest_iter: + include_tests = set() + for test in tests: + if self.manifest.include(test): + include_tests.add(test) + + if include_tests: + yield test_type, test_path, include_tests + +class TagFilter(object): + def __init__(self, tags): + self.tags = set(tags) + + def __call__(self, test_iter): + for test in test_iter: + if test.tags & self.tags: + yield test + +class ManifestLoader(object): + def __init__(self, test_paths, force_manifest_update=False): + do_delayed_imports() + self.test_paths = test_paths + self.force_manifest_update = force_manifest_update + self.logger = structured.get_default_logger() + if self.logger is None: + self.logger = structured.structuredlog.StructuredLogger("ManifestLoader") + + def load(self): + rv = {} + for url_base, paths in self.test_paths.iteritems(): + manifest_file = self.load_manifest(url_base=url_base, + **paths) + path_data = {"url_base": url_base} + path_data.update(paths) + rv[manifest_file] = path_data + return rv + + def create_manifest(self, manifest_path, tests_path, url_base="/"): + self.update_manifest(manifest_path, tests_path, url_base, recreate=True) + + def update_manifest(self, manifest_path, tests_path, url_base="/", + recreate=False): + self.logger.info("Updating test manifest %s" % manifest_path) + + json_data = None + if not recreate: + try: + with open(manifest_path) as f: + json_data = json.load(f) + except IOError: + #If the existing file doesn't exist just create one from scratch + pass + + if not json_data: + manifest_file = manifest.Manifest(url_base) + else: + try: + manifest_file = manifest.Manifest.from_json(tests_path, json_data) + except manifest.ManifestVersionMismatch: + manifest_file = manifest.Manifest(url_base) + + manifest_update.update(tests_path, manifest_file, True) + + manifest.write(manifest_file, manifest_path) + + def load_manifest(self, tests_path, metadata_path, url_base="/"): + manifest_path = os.path.join(metadata_path, "MANIFEST.json") + if (not os.path.exists(manifest_path) or + self.force_manifest_update): + self.update_manifest(manifest_path, tests_path, url_base) + manifest_file = manifest.load(tests_path, manifest_path) + if manifest_file.url_base != url_base: + self.logger.info("Updating url_base in manifest from %s to %s" % (manifest_file.url_base, + url_base)) + manifest_file.url_base = url_base + manifest.write(manifest_file, manifest_path) + + return manifest_file + +def iterfilter(filters, iter): + for f in filters: + iter = f(iter) + for item in iter: + yield item + +class TestLoader(object): + def __init__(self, + test_manifests, + test_types, + run_info, + manifest_filters=None, + meta_filters=None, + chunk_type="none", + total_chunks=1, + chunk_number=1, + include_https=True): + + self.test_types = test_types + self.run_info = run_info + + self.manifest_filters = manifest_filters if manifest_filters is not None else [] + self.meta_filters = meta_filters if meta_filters is not None else [] + + self.manifests = test_manifests + self.tests = None + self.disabled_tests = None + self.include_https = include_https + + self.chunk_type = chunk_type + self.total_chunks = total_chunks + self.chunk_number = chunk_number + + self.chunker = {"none": Unchunked, + "hash": HashChunker, + "dir_hash": DirectoryHashChunker, + "equal_time": EqualTimeChunker}[chunk_type](total_chunks, + chunk_number) + + self._test_ids = None + + self.directory_manifests = {} + + self._load_tests() + + @property + def test_ids(self): + if self._test_ids is None: + self._test_ids = [] + for test_dict in [self.disabled_tests, self.tests]: + for test_type in self.test_types: + self._test_ids += [item.id for item in test_dict[test_type]] + return self._test_ids + + def get_test(self, manifest_test, inherit_metadata, test_metadata): + if test_metadata is not None: + inherit_metadata.append(test_metadata) + test_metadata = test_metadata.get_test(manifest_test.id) + + return wpttest.from_manifest(manifest_test, inherit_metadata, test_metadata) + + def load_dir_metadata(self, test_manifest, metadata_path, test_path): + rv = [] + path_parts = os.path.dirname(test_path).split(os.path.sep) + for i in xrange(1,len(path_parts) + 1): + path = os.path.join(metadata_path, os.path.sep.join(path_parts[:i]), "__dir__.ini") + if path not in self.directory_manifests: + self.directory_manifests[path] = manifestexpected.get_dir_manifest(path, + self.run_info) + manifest = self.directory_manifests[path] + if manifest is not None: + rv.append(manifest) + return rv + + def load_metadata(self, test_manifest, metadata_path, test_path): + inherit_metadata = self.load_dir_metadata(test_manifest, metadata_path, test_path) + test_metadata = manifestexpected.get_manifest( + metadata_path, test_path, test_manifest.url_base, self.run_info) + return inherit_metadata, test_metadata + + def iter_tests(self): + manifest_items = [] + + for manifest in sorted(self.manifests.keys(), key=lambda x:x.url_base): + manifest_iter = iterfilter(self.manifest_filters, + manifest.itertypes(*self.test_types)) + manifest_items.extend(manifest_iter) + + if self.chunker is not None: + manifest_items = self.chunker(manifest_items) + + for test_type, test_path, tests in manifest_items: + manifest_file = iter(tests).next().manifest + metadata_path = self.manifests[manifest_file]["metadata_path"] + inherit_metadata, test_metadata = self.load_metadata(manifest_file, metadata_path, test_path) + + for test in iterfilter(self.meta_filters, + self.iter_wpttest(inherit_metadata, test_metadata, tests)): + yield test_path, test_type, test + + def iter_wpttest(self, inherit_metadata, test_metadata, tests): + for manifest_test in tests: + yield self.get_test(manifest_test, inherit_metadata, test_metadata) + + def _load_tests(self): + """Read in the tests from the manifest file and add them to a queue""" + tests = {"enabled":defaultdict(list), + "disabled":defaultdict(list)} + + for test_path, test_type, test in self.iter_tests(): + enabled = not test.disabled() + if not self.include_https and test.environment["protocol"] == "https": + enabled = False + key = "enabled" if enabled else "disabled" + tests[key][test_type].append(test) + + self.tests = tests["enabled"] + self.disabled_tests = tests["disabled"] + + def groups(self, test_types, chunk_type="none", total_chunks=1, chunk_number=1): + groups = set() + + for test_type in test_types: + for test in self.tests[test_type]: + group = test.url.split("/")[1] + groups.add(group) + + return groups + + +class TestSource(object): + __metaclass__ = ABCMeta + + @abstractmethod + def queue_tests(self, test_queue): + pass + + @abstractmethod + def requeue_test(self, test): + pass + + def __enter__(self): + return self + + def __exit__(self, *args, **kwargs): + pass + + +class SingleTestSource(TestSource): + def __init__(self, test_queue): + self.test_queue = test_queue + + @classmethod + def queue_tests(cls, test_queue, test_type, tests): + for test in tests[test_type]: + test_queue.put(test) + + def get_queue(self): + if self.test_queue.empty(): + return None + return self.test_queue + + def requeue_test(self, test): + self.test_queue.put(test) + +class PathGroupedSource(TestSource): + def __init__(self, test_queue): + self.test_queue = test_queue + self.current_queue = None + + @classmethod + def queue_tests(cls, test_queue, test_type, tests, depth=None): + if depth is True: + depth = None + + prev_path = None + group = None + + for test in tests[test_type]: + path = urlparse.urlsplit(test.url).path.split("/")[1:-1][:depth] + if path != prev_path: + group = [] + test_queue.put(group) + prev_path = path + + group.append(test) + + def get_queue(self): + if not self.current_queue or self.current_queue.empty(): + try: + data = self.test_queue.get(block=True, timeout=1) + self.current_queue = Queue() + for item in data: + self.current_queue.put(item) + except Empty: + return None + + return self.current_queue + + def requeue_test(self, test): + self.current_queue.put(test) + + def __exit__(self, *args, **kwargs): + if self.current_queue: + self.current_queue.close() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py new file mode 100644 index 000000000000..e422cfefec61 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py @@ -0,0 +1,766 @@ +from __future__ import unicode_literals + +import multiprocessing +import sys +import threading +import traceback +from Queue import Empty +from collections import namedtuple +from multiprocessing import Process, current_process, Queue + +from mozlog import structuredlog + +# Special value used as a sentinal in various commands +Stop = object() + + +class MessageLogger(object): + def __init__(self, message_func): + self.send_message = message_func + + def _log_data(self, action, **kwargs): + self.send_message("log", action, kwargs) + + def process_output(self, process, data, command): + self._log_data("process_output", process=process, data=data, command=command) + + +def _log_func(level_name): + def log(self, message): + self._log_data(level_name.lower(), message=message) + log.__doc__ = """Log a message with level %s + +:param message: The string message to log +""" % level_name + log.__name__ = str(level_name).lower() + return log + +# Create all the methods on StructuredLog for debug levels +for level_name in structuredlog.log_levels: + setattr(MessageLogger, level_name.lower(), _log_func(level_name)) + + +class TestRunner(object): + def __init__(self, command_queue, result_queue, executor): + """Class implementing the main loop for running tests. + + This class delegates the job of actually running a test to the executor + that is passed in. + + :param command_queue: subprocess.Queue used to send commands to the + process + :param result_queue: subprocess.Queue used to send results to the + parent TestManager process + :param executor: TestExecutor object that will actually run a test. + """ + self.command_queue = command_queue + self.result_queue = result_queue + + self.executor = executor + self.name = current_process().name + self.logger = MessageLogger(self.send_message) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.teardown() + + def setup(self): + self.logger.debug("Executor setup") + self.executor.setup(self) + self.logger.debug("Executor setup done") + + def teardown(self): + self.executor.teardown() + self.send_message("runner_teardown") + self.result_queue = None + self.command_queue = None + self.browser = None + + def run(self): + """Main loop accepting commands over the pipe and triggering + the associated methods""" + self.setup() + commands = {"run_test": self.run_test, + "stop": self.stop, + "wait": self.wait} + while True: + command, args = self.command_queue.get() + try: + rv = commands[command](*args) + except Exception: + self.send_message("error", + "Error running command %s with arguments %r:\n%s" % + (command, args, traceback.format_exc())) + else: + if rv is Stop: + break + + def stop(self): + return Stop + + def run_test(self, test): + try: + return self.executor.run_test(test) + except Exception: + self.logger.critical(traceback.format_exc()) + raise + + def wait(self): + self.executor.protocol.wait() + self.send_message("wait_finished") + + def send_message(self, command, *args): + self.result_queue.put((command, args)) + + +def start_runner(runner_command_queue, runner_result_queue, + executor_cls, executor_kwargs, + executor_browser_cls, executor_browser_kwargs, + stop_flag): + """Launch a TestRunner in a new process""" + try: + browser = executor_browser_cls(**executor_browser_kwargs) + executor = executor_cls(browser, **executor_kwargs) + with TestRunner(runner_command_queue, runner_result_queue, executor) as runner: + try: + runner.run() + except KeyboardInterrupt: + stop_flag.set() + except Exception: + runner_result_queue.put(("log", ("critical", {"message": traceback.format_exc()}))) + print >> sys.stderr, traceback.format_exc() + stop_flag.set() + finally: + runner_command_queue = None + runner_result_queue = None + + +manager_count = 0 + + +def next_manager_number(): + global manager_count + local = manager_count = manager_count + 1 + return local + + +class BrowserManager(object): + init_lock = threading.Lock() + + def __init__(self, logger, browser, command_queue, no_timeout=False): + self.logger = logger + self.browser = browser + self.no_timeout = no_timeout + + self.started = False + + self.init_timer = None + + def init(self): + """Launch the browser that is being tested, + and the TestRunner process that will run the tests.""" + # It seems that this lock is helpful to prevent some race that otherwise + # sometimes stops the spawned processes initalising correctly, and + # leaves this thread hung + if self.init_timer is not None: + self.init_timer.cancel() + + self.logger.debug("Init called, starting browser and runner") + + with self.init_lock: + # Guard against problems initialising the browser or the browser + # remote control method + if not self.no_timeout: + self.init_timer = threading.Timer(self.browser.init_timeout, + self.init_timeout) + try: + if self.init_timer is not None: + self.init_timer.start() + self.browser.start() + self.browser_pid = self.browser.pid() + except: + self.logger.warning("Failure during init %s" % traceback.format_exc()) + if self.init_timer is not None: + self.init_timer.cancel() + self.logger.error(traceback.format_exc()) + succeeded = False + else: + succeeded = True + self.started = True + + return succeeded + + def send_message(self, command, *args): + self.command_queue.put((command, args)) + + def init_timeout(self): + # This is called from a seperate thread, so we send a message to the + # main loop so we get back onto the manager thread + self.logger.debug("init_failed called from timer") + self.send_message("init_failed") + + def after_init(self): + """Callback when we have started the browser, started the remote + control connection, and we are ready to start testing.""" + if self.init_timer is not None: + self.init_timer.cancel() + + def stop(self, force=False): + self.browser.stop(force=force) + self.started = False + + def cleanup(self): + if self.init_timer is not None: + self.init_timer.cancel() + self.browser.cleanup() + + def log_crash(self, test_id): + self.browser.log_crash(process=self.browser_pid, test=test_id) + + def is_alive(self): + return self.browser.is_alive() + + +class _RunnerManagerState(object): + before_init = namedtuple("before_init", []) + initalizing = namedtuple("initalizing_browser", + ["test", "test_queue", "failure_count"]) + running = namedtuple("running", ["test", "test_queue"]) + restarting = namedtuple("restarting", ["test", "test_queue"]) + error = namedtuple("error", []) + stop = namedtuple("stop", []) + + +RunnerManagerState = _RunnerManagerState() + + +class TestRunnerManager(threading.Thread): + init_lock = threading.Lock() + + def __init__(self, suite_name, tests, test_source_cls, browser_cls, browser_kwargs, + executor_cls, executor_kwargs, stop_flag, pause_after_test=False, + pause_on_unexpected=False, restart_on_unexpected=True, debug_info=None): + """Thread that owns a single TestRunner process and any processes required + by the TestRunner (e.g. the Firefox binary). + + TestRunnerManagers are responsible for launching the browser process and the + runner process, and for logging the test progress. The actual test running + is done by the TestRunner. In particular they: + + * Start the binary of the program under test + * Start the TestRunner + * Tell the TestRunner to start a test, if any + * Log that the test started + * Log the test results + * Take any remedial action required e.g. restart crashed or hung + processes + """ + self.suite_name = suite_name + + self.tests = tests + self.test_source_cls = test_source_cls + self.test_queue = None + + self.browser_cls = browser_cls + self.browser_kwargs = browser_kwargs + + self.executor_cls = executor_cls + self.executor_kwargs = executor_kwargs + + self.test_source = None + + # Flags used to shut down this thread if we get a sigint + self.parent_stop_flag = stop_flag + self.child_stop_flag = multiprocessing.Event() + + self.pause_after_test = pause_after_test + self.pause_on_unexpected = pause_on_unexpected + self.restart_on_unexpected = restart_on_unexpected + self.debug_info = debug_info + + self.manager_number = next_manager_number() + + self.command_queue = Queue() + self.remote_queue = Queue() + + self.test_runner_proc = None + + threading.Thread.__init__(self, name="Thread-TestrunnerManager-%i" % self.manager_number) + # This is started in the actual new thread + self.logger = None + + self.unexpected_count = 0 + + # This may not really be what we want + self.daemon = True + + self.max_restarts = 5 + + self.browser = None + + def run(self): + """Main loop for the TestManager. + + TestManagers generally receive commands from their + TestRunner updating them on the status of a test. They + may also have a stop flag set by the main thread indicating + that the manager should shut down the next time the event loop + spins.""" + self.logger = structuredlog.StructuredLogger(self.suite_name) + with self.browser_cls(self.logger, **self.browser_kwargs) as browser, self.test_source_cls(self.tests) as test_source: + self.browser = BrowserManager(self.logger, + browser, + self.command_queue, + no_timeout=self.debug_info is not None) + self.test_source = test_source + dispatch = { + RunnerManagerState.before_init: self.start_init, + RunnerManagerState.initalizing: self.init, + RunnerManagerState.running: self.run_test, + RunnerManagerState.restarting: self.restart_runner + } + + self.state = RunnerManagerState.before_init() + end_states = (RunnerManagerState.stop, + RunnerManagerState.error) + + try: + while not isinstance(self.state, end_states): + f = dispatch.get(self.state.__class__) + while f: + self.logger.debug("Dispatch %s" % f.__name__) + if self.should_stop(): + return + new_state = f() + if new_state is None: + break + self.state = new_state + self.logger.debug("new state: %s" % self.state.__class__.__name__) + if isinstance(self.state, end_states): + return + f = dispatch.get(self.state.__class__) + + new_state = None + while new_state is None: + new_state = self.wait_event() + if self.should_stop(): + return + self.state = new_state + self.logger.debug("new state: %s" % self.state.__class__.__name__) + except Exception as e: + self.logger.error(traceback.format_exc(e)) + raise + finally: + self.logger.debug("TestRunnerManager main loop terminating, starting cleanup") + clean = isinstance(self.state, RunnerManagerState.stop) + self.stop_runner(force=not clean) + self.teardown() + self.logger.debug("TestRunnerManager main loop terminated") + + def wait_event(self): + dispatch = { + RunnerManagerState.before_init: {}, + RunnerManagerState.initalizing: + { + "init_succeeded": self.init_succeeded, + "init_failed": self.init_failed, + }, + RunnerManagerState.running: + { + "test_ended": self.test_ended, + "wait_finished": self.wait_finished, + }, + RunnerManagerState.restarting: {}, + RunnerManagerState.error: {}, + RunnerManagerState.stop: {}, + None: { + "runner_teardown": self.runner_teardown, + "log": self.log, + "error": self.error + } + } + try: + command, data = self.command_queue.get(True, 1) + except IOError: + self.logger.error("Got IOError from poll") + return RunnerManagerState.restarting(0) + except Empty: + if (self.debug_info and self.debug_info.interactive and + self.browser.started and not self.browser.is_alive()): + self.logger.debug("Debugger exited") + return RunnerManagerState.stop() + + if (isinstance(self.state, RunnerManagerState.running) and + not self.test_runner_proc.is_alive()): + if not self.command_queue.empty(): + # We got a new message so process that + return + + # If we got to here the runner presumably shut down + # unexpectedly + self.logger.info("Test runner process shut down") + + if self.state.test is not None: + # This could happen if the test runner crashed for some other + # reason + # Need to consider the unlikely case where one test causes the + # runner process to repeatedly die + self.logger.critical("Last test did not complete") + return RunnerManagerState.error() + self.logger.warning("More tests found, but runner process died, restarting") + return RunnerManagerState.restarting(0) + else: + f = (dispatch.get(self.state.__class__, {}).get(command) or + dispatch.get(None, {}).get(command)) + if not f: + self.logger.warning("Got command %s in state %s" % + (command, self.state.__class__.__name__)) + return + return f(*data) + + + def should_stop(self): + return self.child_stop_flag.is_set() or self.parent_stop_flag.is_set() + + def start_init(self): + test, test_queue = self.get_next_test() + if test is None: + return RunnerManagerState.stop() + else: + return RunnerManagerState.initalizing(test, test_queue, 0) + + def init(self): + assert isinstance(self.state, RunnerManagerState.initalizing) + if self.state.failure_count > self.max_restarts: + self.logger.error("Max restarts exceeded") + return RunnerManagerState.error() + + result = self.browser.init() + if result is Stop: + return RunnerManagerState.error() + elif not result: + return RunnerManagerState.initalizing(self.state.test, + self.state.test_queue, + self.state.failure_count + 1) + else: + self.start_test_runner() + + def start_test_runner(self): + # Note that we need to be careful to start the browser before the + # test runner to ensure that any state set when the browser is started + # can be passed in to the test runner. + assert isinstance(self.state, RunnerManagerState.initalizing) + assert self.command_queue is not None + assert self.remote_queue is not None + self.logger.info("Starting runner") + executor_browser_cls, executor_browser_kwargs = self.browser.browser.executor_browser() + + args = (self.remote_queue, + self.command_queue, + self.executor_cls, + self.executor_kwargs, + executor_browser_cls, + executor_browser_kwargs, + self.child_stop_flag) + self.test_runner_proc = Process(target=start_runner, + args=args, + name="Thread-TestRunner-%i" % self.manager_number) + self.test_runner_proc.start() + self.logger.debug("Test runner started") + # Now we wait for either an init_succeeded event or an init_failed event + + def init_succeeded(self): + assert isinstance(self.state, RunnerManagerState.initalizing) + self.browser.after_init() + return RunnerManagerState.running(self.state.test, + self.state.test_queue) + + def init_failed(self): + assert isinstance(self.state, RunnerManagerState.initalizing) + self.browser.after_init() + self.stop_runner(force=True) + return RunnerManagerState.initalizing(self.state.test, + self.state.test_queue, + self.state.failure_count + 1) + + def get_next_test(self, test_queue=None): + test = None + while test is None: + if test_queue is None: + test_queue = self.test_source.get_queue() + if test_queue is None: + self.logger.info("No more tests") + return None, None + try: + # Need to block here just to allow for contention with other processes + test = test_queue.get(block=True, timeout=1) + except Empty: + pass + return test, test_queue + + def run_test(self): + assert isinstance(self.state, RunnerManagerState.running) + assert self.state.test is not None + + self.logger.test_start(self.state.test.id) + self.send_message("run_test", self.state.test) + + def test_ended(self, test, results): + """Handle the end of a test. + + Output the result of each subtest, and the result of the overall + harness to the logs. + """ + assert isinstance(self.state, RunnerManagerState.running) + assert test == self.state.test + # Write the result of each subtest + file_result, test_results = results + subtest_unexpected = False + for result in test_results: + if test.disabled(result.name): + continue + expected = test.expected(result.name) + is_unexpected = expected != result.status + + if is_unexpected: + self.unexpected_count += 1 + self.logger.debug("Unexpected count in this thread %i" % self.unexpected_count) + subtest_unexpected = True + self.logger.test_status(test.id, + result.name, + result.status, + message=result.message, + expected=expected, + stack=result.stack) + + # TODO: consider changing result if there is a crash dump file + + # Write the result of the test harness + expected = test.expected() + status = file_result.status if file_result.status != "EXTERNAL-TIMEOUT" else "TIMEOUT" + is_unexpected = expected != status + if is_unexpected: + self.unexpected_count += 1 + self.logger.debug("Unexpected count in this thread %i" % self.unexpected_count) + if status == "CRASH": + self.browser.log_crash(test.id) + + self.logger.test_end(test.id, + status, + message=file_result.message, + expected=expected, + extra=file_result.extra) + + restart_before_next = (test.restart_after or + file_result.status in ("CRASH", "EXTERNAL-TIMEOUT") or + ((subtest_unexpected or is_unexpected) + and self.restart_on_unexpected)) + + if (self.pause_after_test or + (self.pause_on_unexpected and (subtest_unexpected or is_unexpected))): + self.logger.info("Pausing until the browser exits") + self.send_message("wait") + else: + return self.after_test_end(restart_before_next) + + def wait_finished(self): + assert isinstance(self.state, RunnerManagerState.running) + # The browser should be stopped already, but this ensures we do any post-stop + # processing + self.logger.debug("Wait finished") + + return self.after_test_end(True) + + def after_test_end(self, restart): + assert isinstance(self.state, RunnerManagerState.running) + test, test_queue = self.get_next_test() + if test is None: + return RunnerManagerState.stop() + if test_queue != self.state.test_queue: + # We are starting a new group of tests, so force a restart + restart = True + if restart: + return RunnerManagerState.restarting(test, test_queue) + else: + return RunnerManagerState.running(test, test_queue) + + def restart_runner(self): + """Stop and restart the TestRunner""" + assert isinstance(self.state, RunnerManagerState.restarting) + self.stop_runner() + return RunnerManagerState.initalizing(self.state.test, self.state.test_queue, 0) + + def log(self, action, kwargs): + getattr(self.logger, action)(**kwargs) + + def error(self, message): + self.logger.error(message) + self.restart_runner() + + def stop_runner(self, force=False): + """Stop the TestRunner and the browser binary.""" + if self.test_runner_proc is None: + return + + if self.test_runner_proc.is_alive(): + self.send_message("stop") + try: + self.browser.stop(force=force) + self.ensure_runner_stopped() + finally: + self.cleanup() + + def teardown(self): + self.logger.debug("teardown in testrunnermanager") + self.test_runner_proc = None + self.command_queue.close() + self.remote_queue.close() + self.command_queue = None + self.remote_queue = None + + def ensure_runner_stopped(self): + self.logger.debug("ensure_runner_stopped") + if self.test_runner_proc is None: + return + + self.logger.debug("waiting for runner process to end") + self.test_runner_proc.join(10) + self.logger.debug("After join") + if self.test_runner_proc.is_alive(): + # This might leak a file handle from the queue + self.logger.warning("Forcibly terminating runner process") + self.test_runner_proc.terminate() + self.test_runner_proc.join(10) + else: + self.logger.debug("Testrunner exited with code %i" % self.test_runner_proc.exitcode) + + def runner_teardown(self): + self.ensure_runner_stopped() + return RunnerManagerState.stop() + + def send_message(self, command, *args): + self.remote_queue.put((command, args)) + + def cleanup(self): + self.logger.debug("TestManager cleanup") + if self.browser: + self.browser.cleanup() + while True: + try: + self.logger.warning(" ".join(map(repr, self.command_queue.get_nowait()))) + except Empty: + break + +class TestQueue(object): + def __init__(self, test_source_cls, test_type, tests, **kwargs): + self.queue = None + self.test_source_cls = test_source_cls + self.test_type = test_type + self.tests = tests + self.kwargs = kwargs + + def __enter__(self): + if not self.tests[self.test_type]: + return None + + self.queue = Queue() + has_tests = self.test_source_cls.queue_tests(self.queue, + self.test_type, + self.tests, + **self.kwargs) + # There is a race condition that means sometimes we continue + # before the tests have been written to the underlying pipe. + # Polling the pipe for data here avoids that + self.queue._reader.poll(10) + assert not self.queue.empty() + return self.queue + + def __exit__(self, *args, **kwargs): + if self.queue is not None: + self.queue.close() + self.queue = None + + +class ManagerGroup(object): + def __init__(self, suite_name, size, test_source_cls, test_source_kwargs, + browser_cls, browser_kwargs, + executor_cls, executor_kwargs, + pause_after_test=False, + pause_on_unexpected=False, + restart_on_unexpected=True, + debug_info=None): + """Main thread object that owns all the TestManager threads.""" + self.suite_name = suite_name + self.size = size + self.test_source_cls = test_source_cls + self.test_source_kwargs = test_source_kwargs + self.browser_cls = browser_cls + self.browser_kwargs = browser_kwargs + self.executor_cls = executor_cls + self.executor_kwargs = executor_kwargs + self.pause_after_test = pause_after_test + self.pause_on_unexpected = pause_on_unexpected + self.restart_on_unexpected = restart_on_unexpected + self.debug_info = debug_info + + self.pool = set() + # Event that is polled by threads so that they can gracefully exit in the face + # of sigint + self.stop_flag = threading.Event() + self.logger = structuredlog.StructuredLogger(suite_name) + self.test_queue = None + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.stop() + + def run(self, test_type, tests): + """Start all managers in the group""" + self.logger.debug("Using %i processes" % self.size) + + self.test_queue = TestQueue(self.test_source_cls, + test_type, + tests, + **self.test_source_kwargs) + with self.test_queue as test_queue: + if test_queue is None: + self.logger.info("No %s tests to run" % test_type) + return + for _ in range(self.size): + manager = TestRunnerManager(self.suite_name, + test_queue, + self.test_source_cls, + self.browser_cls, + self.browser_kwargs, + self.executor_cls, + self.executor_kwargs, + self.stop_flag, + self.pause_after_test, + self.pause_on_unexpected, + self.restart_on_unexpected, + self.debug_info) + manager.start() + self.pool.add(manager) + self.wait() + + def is_alive(self): + """Boolean indicating whether any manager in the group is still alive""" + return any(manager.is_alive() for manager in self.pool) + + def wait(self): + """Wait for all the managers in the group to finish""" + for item in self.pool: + item.join() + + def stop(self): + """Set the stop flag so that all managers in the group stop as soon + as possible""" + self.stop_flag.set() + self.logger.debug("Stop flag set in ManagerGroup") + + def unexpected_count(self): + return sum(item.unexpected_count for item in self.pool) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/__init__.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_chunker.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_chunker.py new file mode 100644 index 000000000000..4968940feb8b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_chunker.py @@ -0,0 +1,89 @@ +import unittest +import sys +from os.path import join, dirname +from mozlog import structured + +import pytest + +sys.path.insert(0, join(dirname(__file__), "..", "..")) + +from wptrunner.testloader import EqualTimeChunker + +structured.set_default_logger(structured.structuredlog.StructuredLogger("TestChunker")) + +class MockTest(object): + def __init__(self, id, timeout=10): + self.id = id + self.item_type = "testharness" + self.timeout = timeout + + +def make_mock_manifest(*items): + rv = [] + for test_type, dir_path, num_tests in items: + for i in range(num_tests): + rv.append((test_type, + dir_path + "/%i.test" % i, + set([MockTest(i)]))) + return rv + + +class TestEqualTimeChunker(unittest.TestCase): + + def test_include_all(self): + tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10), + ("test", "c", 10)) + + chunk_1 = list(EqualTimeChunker(3, 1)(tests)) + chunk_2 = list(EqualTimeChunker(3, 2)(tests)) + chunk_3 = list(EqualTimeChunker(3, 3)(tests)) + + self.assertEquals(tests[:10], chunk_1) + self.assertEquals(tests[10:20], chunk_2) + self.assertEquals(tests[20:], chunk_3) + + def test_include_all_1(self): + tests = make_mock_manifest(("test", "a", 5), ("test", "a/b", 5), + ("test", "c", 10), ("test", "d", 10)) + + chunk_1 = list(EqualTimeChunker(3, 1)(tests)) + chunk_2 = list(EqualTimeChunker(3, 2)(tests)) + chunk_3 = list(EqualTimeChunker(3, 3)(tests)) + + self.assertEquals(tests[:10], chunk_1) + self.assertEquals(tests[10:20], chunk_2) + self.assertEquals(tests[20:], chunk_3) + + def test_long(self): + tests = make_mock_manifest(("test", "a", 100), ("test", "a/b", 1), + ("test", "c", 1)) + + chunk_1 = list(EqualTimeChunker(3, 1)(tests)) + chunk_2 = list(EqualTimeChunker(3, 2)(tests)) + chunk_3 = list(EqualTimeChunker(3, 3)(tests)) + + self.assertEquals(tests[:100], chunk_1) + self.assertEquals(tests[100:101], chunk_2) + self.assertEquals(tests[101:102], chunk_3) + + def test_long_1(self): + tests = make_mock_manifest(("test", "a", 1), ("test", "a/b", 100), + ("test", "c", 1)) + + chunk_1 = list(EqualTimeChunker(3, 1)(tests)) + chunk_2 = list(EqualTimeChunker(3, 2)(tests)) + chunk_3 = list(EqualTimeChunker(3, 3)(tests)) + + self.assertEquals(tests[:1], chunk_1) + self.assertEquals(tests[1:101], chunk_2) + self.assertEquals(tests[101:102], chunk_3) + + def test_too_few_dirs(self): + with self.assertRaises(ValueError): + tests = make_mock_manifest(("test", "a", 1), ("test", "a/b", 100), + ("test", "c", 1)) + list(EqualTimeChunker(4, 1)(tests)) + + +if __name__ == "__main__": + unittest.main() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_hosts.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_hosts.py new file mode 100644 index 000000000000..808b81606aeb --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_hosts.py @@ -0,0 +1,56 @@ +import unittest +import sys +from os.path import join, dirname +from cStringIO import StringIO + +sys.path.insert(0, join(dirname(__file__), "..", "..")) + +from wptrunner import hosts + + +class HostsTest(unittest.TestCase): + def do_test(self, input, expected): + host_file = hosts.HostsFile.from_file(StringIO(input)) + self.assertEquals(host_file.to_string(), expected) + + def test_simple(self): + self.do_test("""127.0.0.1 \tlocalhost alias # comment +# Another comment""", + """127.0.0.1 localhost alias # comment +# Another comment +""") + + def test_blank_lines(self): + self.do_test("""127.0.0.1 \tlocalhost alias # comment + +\r + \t +# Another comment""", + """127.0.0.1 localhost alias # comment +# Another comment +""") + + def test_whitespace(self): + self.do_test(""" \t127.0.0.1 \tlocalhost alias # comment \r + \t# Another comment""", + """127.0.0.1 localhost alias # comment +# Another comment +""") + + def test_alignment(self): + self.do_test("""127.0.0.1 \tlocalhost alias +192.168.1.1 another_host another_alias +""","""127.0.0.1 localhost alias +192.168.1.1 another_host another_alias +""" +) + + def test_multiple_same_name(self): + # The semantics are that we overwrite earlier entries with the same name + self.do_test("""127.0.0.1 \tlocalhost alias +192.168.1.1 localhost another_alias""","""192.168.1.1 localhost another_alias +""" +) + +if __name__ == "__main__": + unittest.main() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_testloader.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_testloader.py new file mode 100644 index 000000000000..0d967b051fda --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_testloader.py @@ -0,0 +1,29 @@ +from __future__ import unicode_literals + +import os +import sys +import tempfile + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) + +from mozlog import structured +from wptrunner.testloader import TestFilter as Filter +from .test_chunker import make_mock_manifest + +structured.set_default_logger(structured.structuredlog.StructuredLogger("TestLoader")) + +include_ini = """\ +skip: true +[test_\u53F0] + skip: false +""" + +def test_filter_unicode(): + tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10), + ("test", "c", 10)) + + with tempfile.NamedTemporaryFile("wb", suffix=".ini") as f: + f.write(include_ini.encode('utf-8')) + f.flush() + + Filter(manifest_path=f.name, test_manifests=tests) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_update.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_update.py new file mode 100644 index 000000000000..e5eb4cf49c7f --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_update.py @@ -0,0 +1,328 @@ +import unittest +import StringIO + +import pytest + +from .. import metadata, manifestupdate +from mozlog import structuredlog, handlers, formatters + + +class TestExpectedUpdater(unittest.TestCase): + def create_manifest(self, data, test_path="path/to/test.ini"): + f = StringIO.StringIO(data) + return manifestupdate.compile(f, test_path) + + def create_updater(self, data, **kwargs): + expected_tree = {} + id_path_map = {} + for test_path, test_ids, manifest_str in data: + if isinstance(test_ids, (str, unicode)): + test_ids = [test_ids] + expected_tree[test_path] = self.create_manifest(manifest_str, test_path) + for test_id in test_ids: + id_path_map[test_id] = test_path + + return metadata.ExpectedUpdater(expected_tree, id_path_map, **kwargs) + + def create_log(self, *args, **kwargs): + logger = structuredlog.StructuredLogger("expected_test") + data = StringIO.StringIO() + handler = handlers.StreamHandler(data, formatters.JSONFormatter()) + logger.add_handler(handler) + + log_entries = ([("suite_start", {"tests": [], "run_info": kwargs.get("run_info", {})})] + + list(args) + + [("suite_end", {})]) + + for item in log_entries: + action, kwargs = item + getattr(logger, action)(**kwargs) + logger.remove_handler(handler) + data.seek(0) + return data + + + def coalesce_results(self, trees): + for tree in trees: + for test in tree.iterchildren(): + for subtest in test.iterchildren(): + subtest.coalesce_expected() + test.coalesce_expected() + + @pytest.mark.xfail + def test_update_0(self): + prev_data = [("path/to/test.htm.ini", ["/path/to/test.htm"], """[test.htm] + type: testharness + [test1] + expected: FAIL""")] + + new_data = self.create_log(("test_start", {"test": "/path/to/test.htm"}), + ("test_status", {"test": "/path/to/test.htm", + "subtest": "test1", + "status": "PASS", + "expected": "FAIL"}), + ("test_end", {"test": "/path/to/test.htm", + "status": "OK"})) + updater = self.create_updater(prev_data) + updater.update_from_log(new_data) + + new_manifest = updater.expected_tree["path/to/test.htm.ini"] + self.coalesce_results([new_manifest]) + self.assertTrue(new_manifest.is_empty) + + @pytest.mark.xfail + def test_update_1(self): + test_id = "/path/to/test.htm" + prev_data = [("path/to/test.htm.ini", [test_id], """[test.htm] + type: testharness + [test1] + expected: ERROR""")] + + new_data = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "FAIL", + "expected": "ERROR"}), + ("test_end", {"test": test_id, + "status": "OK"})) + updater = self.create_updater(prev_data) + updater.update_from_log(new_data) + + new_manifest = updater.expected_tree["path/to/test.htm.ini"] + self.coalesce_results([new_manifest]) + self.assertFalse(new_manifest.is_empty) + self.assertEquals(new_manifest.get_test(test_id).children[0].get("expected"), "FAIL") + + @pytest.mark.xfail + def test_new_subtest(self): + test_id = "/path/to/test.htm" + prev_data = [("path/to/test.htm.ini", [test_id], """[test.htm] + type: testharness + [test1] + expected: FAIL""")] + + new_data = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "FAIL", + "expected": "FAIL"}), + ("test_status", {"test": test_id, + "subtest": "test2", + "status": "FAIL", + "expected": "PASS"}), + ("test_end", {"test": test_id, + "status": "OK"})) + updater = self.create_updater(prev_data) + updater.update_from_log(new_data) + + new_manifest = updater.expected_tree["path/to/test.htm.ini"] + self.coalesce_results([new_manifest]) + self.assertFalse(new_manifest.is_empty) + self.assertEquals(new_manifest.get_test(test_id).children[0].get("expected"), "FAIL") + self.assertEquals(new_manifest.get_test(test_id).children[1].get("expected"), "FAIL") + + @pytest.mark.xfail + def test_update_multiple_0(self): + test_id = "/path/to/test.htm" + prev_data = [("path/to/test.htm.ini", [test_id], """[test.htm] + type: testharness + [test1] + expected: FAIL""")] + + new_data_0 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "FAIL", + "expected": "FAIL"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": False, "os": "osx"}) + + new_data_1 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "TIMEOUT", + "expected": "FAIL"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": False, "os": "linux"}) + updater = self.create_updater(prev_data) + + updater.update_from_log(new_data_0) + updater.update_from_log(new_data_1) + + new_manifest = updater.expected_tree["path/to/test.htm.ini"] + + self.coalesce_results([new_manifest]) + + self.assertFalse(new_manifest.is_empty) + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": False, "os": "osx"}), "FAIL") + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": False, "os": "linux"}), "TIMEOUT") + + @pytest.mark.xfail + def test_update_multiple_1(self): + test_id = "/path/to/test.htm" + prev_data = [("path/to/test.htm.ini", [test_id], """[test.htm] + type: testharness + [test1] + expected: FAIL""")] + + new_data_0 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "FAIL", + "expected": "FAIL"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": False, "os": "osx"}) + + new_data_1 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "TIMEOUT", + "expected": "FAIL"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": False, "os": "linux"}) + updater = self.create_updater(prev_data) + + updater.update_from_log(new_data_0) + updater.update_from_log(new_data_1) + + new_manifest = updater.expected_tree["path/to/test.htm.ini"] + + self.coalesce_results([new_manifest]) + + self.assertFalse(new_manifest.is_empty) + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": False, "os": "osx"}), "FAIL") + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": False, "os": "linux"}), "TIMEOUT") + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": False, "os": "windows"}), "FAIL") + + @pytest.mark.xfail + def test_update_multiple_2(self): + test_id = "/path/to/test.htm" + prev_data = [("path/to/test.htm.ini", [test_id], """[test.htm] + type: testharness + [test1] + expected: FAIL""")] + + new_data_0 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "FAIL", + "expected": "FAIL"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": False, "os": "osx"}) + + new_data_1 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "TIMEOUT", + "expected": "FAIL"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": True, "os": "osx"}) + updater = self.create_updater(prev_data) + + updater.update_from_log(new_data_0) + updater.update_from_log(new_data_1) + + new_manifest = updater.expected_tree["path/to/test.htm.ini"] + + self.coalesce_results([new_manifest]) + + self.assertFalse(new_manifest.is_empty) + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": False, "os": "osx"}), "FAIL") + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": True, "os": "osx"}), "TIMEOUT") + + @pytest.mark.xfail + def test_update_multiple_3(self): + test_id = "/path/to/test.htm" + prev_data = [("path/to/test.htm.ini", [test_id], """[test.htm] + type: testharness + [test1] + expected: + if debug: FAIL + if not debug and os == "osx": TIMEOUT""")] + + new_data_0 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "FAIL", + "expected": "FAIL"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": False, "os": "osx"}) + + new_data_1 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "TIMEOUT", + "expected": "FAIL"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": True, "os": "osx"}) + updater = self.create_updater(prev_data) + + updater.update_from_log(new_data_0) + updater.update_from_log(new_data_1) + + new_manifest = updater.expected_tree["path/to/test.htm.ini"] + + self.coalesce_results([new_manifest]) + + self.assertFalse(new_manifest.is_empty) + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": False, "os": "osx"}), "FAIL") + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": True, "os": "osx"}), "TIMEOUT") + + @pytest.mark.xfail + def test_update_ignore_existing(self): + test_id = "/path/to/test.htm" + prev_data = [("path/to/test.htm.ini", [test_id], """[test.htm] + type: testharness + [test1] + expected: + if debug: TIMEOUT + if not debug and os == "osx": NOTRUN""")] + + new_data_0 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "FAIL", + "expected": "PASS"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": False, "os": "linux"}) + + new_data_1 = self.create_log(("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "FAIL", + "expected": "PASS"}), + ("test_end", {"test": test_id, + "status": "OK"}), + run_info={"debug": True, "os": "windows"}) + updater = self.create_updater(prev_data, ignore_existing=True) + + updater.update_from_log(new_data_0) + updater.update_from_log(new_data_1) + + new_manifest = updater.expected_tree["path/to/test.htm.ini"] + + self.coalesce_results([new_manifest]) + + self.assertFalse(new_manifest.is_empty) + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": True, "os": "osx"}), "FAIL") + self.assertEquals(new_manifest.get_test(test_id).children[0].get( + "expected", {"debug": False, "os": "osx"}), "FAIL") diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/update/__init__.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/__init__.py new file mode 100644 index 000000000000..497cb34ad0cb --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/__init__.py @@ -0,0 +1,47 @@ +import os +import sys + +from mozlog.structured import structuredlog, commandline + +from .. import wptcommandline + +from update import WPTUpdate + +def remove_logging_args(args): + """Take logging args out of the dictionary of command line arguments so + they are not passed in as kwargs to the update code. This is particularly + necessary here because the arguments are often of type file, which cannot + be serialized. + + :param args: Dictionary of command line arguments. + """ + for name in args.keys(): + if name.startswith("log_"): + args.pop(name) + + +def setup_logging(args, defaults): + """Use the command line arguments to set up the logger. + + :param args: Dictionary of command line arguments. + :param defaults: Dictionary of {formatter_name: stream} to use if + no command line logging is specified""" + logger = commandline.setup_logging("web-platform-tests-update", args, defaults) + + remove_logging_args(args) + + return logger + + +def run_update(logger, **kwargs): + updater = WPTUpdate(logger, **kwargs) + return updater.run() + + +def main(): + args = wptcommandline.parse_args_update() + logger = setup_logging(args, {"mach": sys.stdout}) + assert structuredlog.get_default_logger() is not None + success = run_update(logger, **args) + sys.exit(0 if success else 1) + diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/update/base.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/base.py new file mode 100644 index 000000000000..547808e52933 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/base.py @@ -0,0 +1,65 @@ +exit_unclean = object() +exit_clean = object() + + +class Step(object): + provides = [] + + def __init__(self, logger): + self.logger = logger + + def run(self, step_index, state): + """Base class for state-creating steps. + + When a Step is run() the current state is checked to see + if the state from this step has already been created. If it + has the restore() method is invoked. Otherwise the create() + method is invoked with the state object. This is expected to + add items with all the keys in __class__.provides to the state + object. + """ + + name = self.__class__.__name__ + + try: + stored_step = state.steps[step_index] + except IndexError: + stored_step = None + + if stored_step == name: + self.restore(state) + elif stored_step is None: + self.create(state) + assert set(self.provides).issubset(set(state.keys())) + state.steps = state.steps + [name] + else: + raise ValueError("Expected a %s step, got a %s step" % (name, stored_step)) + + def create(self, data): + raise NotImplementedError + + def restore(self, state): + self.logger.debug("Step %s using stored state" % (self.__class__.__name__,)) + for key in self.provides: + assert key in state + + +class StepRunner(object): + steps = [] + + def __init__(self, logger, state): + """Class that runs a specified series of Steps with a common State""" + self.state = state + self.logger = logger + if "steps" not in state: + state.steps = [] + + def run(self): + rv = None + for step_index, step in enumerate(self.steps): + self.logger.debug("Starting step %s" % step.__name__) + rv = step(self.logger).run(step_index, self.state) + if rv in (exit_clean, exit_unclean): + break + + return rv diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/update/metadata.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/metadata.py new file mode 100644 index 000000000000..f596766578c9 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/metadata.py @@ -0,0 +1,71 @@ +import os + +from .. import metadata, products + +from base import Step, StepRunner + +class GetUpdatePropertyList(Step): + provides = ["property_order", "boolean_properties"] + + + def create(self, state): + property_order, boolean_properties = products.load_product_update( + state.config, state.product) + state.property_order = property_order + state.boolean_properties = boolean_properties + + +class UpdateExpected(Step): + """Do the metadata update on the local checkout""" + + provides = ["needs_human"] + + def create(self, state): + if state.sync_tree is not None: + sync_root = state.sync_tree.root + else: + sync_root = None + + state.needs_human = metadata.update_expected(state.paths, + state.serve_root, + state.run_log, + rev_old=None, + ignore_existing=state.ignore_existing, + sync_root=sync_root, + property_order=state.property_order, + boolean_properties=state.boolean_properties) + + +class CreateMetadataPatch(Step): + """Create a patch/commit for the metadata checkout""" + + def create(self, state): + if state.no_patch: + return + + local_tree = state.local_tree + sync_tree = state.sync_tree + + if sync_tree is not None: + name = "web-platform-tests_update_%s_metadata" % sync_tree.rev + message = "Update %s expected data to revision %s" % (state.suite_name, sync_tree.rev) + else: + name = "web-platform-tests_update_metadata" + message = "Update %s expected data" % state.suite_name + + local_tree.create_patch(name, message) + + if not local_tree.is_clean: + metadata_paths = [manifest_path["metadata_path"] + for manifest_path in state.paths.itervalues()] + for path in metadata_paths: + local_tree.add_new(os.path.relpath(path, local_tree.root)) + local_tree.update_patch(include=metadata_paths) + local_tree.commit_patch() + + +class MetadataUpdateRunner(StepRunner): + """(Sub)Runner for updating metadata""" + steps = [GetUpdatePropertyList, + UpdateExpected, + CreateMetadataPatch] diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/update/state.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/state.py new file mode 100644 index 000000000000..9454414e640b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/state.py @@ -0,0 +1,133 @@ +import os +import cPickle as pickle + +here = os.path.abspath(os.path.split(__file__)[0]) + +class State(object): + filename = os.path.join(here, ".wpt-update.lock") + + def __new__(cls, logger): + rv = cls.load(logger) + if rv is not None: + logger.debug("Existing state found") + return rv + + logger.debug("No existing state found") + return object.__new__(cls, logger) + + def __init__(self, logger): + """Object containing state variables created when running Steps. + + On write the state is serialized to disk, such that it can be restored in + the event that the program is interrupted before all steps are complete. + Note that this only works well if the values are immutable; mutating an + existing value will not cause the data to be serialized. + + Variables are set and get as attributes e.g. state_obj.spam = "eggs". + + :param parent: Parent State object or None if this is the root object. + """ + + if hasattr(self, "_data"): + return + + self._data = [{}] + self._logger = logger + self._index = 0 + + def __getstate__(self): + rv = self.__dict__.copy() + del rv["_logger"] + return rv + + @classmethod + def load(cls, logger): + """Load saved state from a file""" + try: + with open(cls.filename) as f: + try: + rv = pickle.load(f) + logger.debug("Loading data %r" % (rv._data,)) + rv._logger = logger + rv._index = 0 + return rv + except EOFError: + logger.warning("Found empty state file") + except IOError: + logger.debug("IOError loading stored state") + + def push(self, init_values): + """Push a new clean state dictionary + + :param init_values: List of variable names in the current state dict to copy + into the new state dict.""" + + return StateContext(self, init_values) + + def save(self): + """Write the state to disk""" + with open(self.filename, "w") as f: + pickle.dump(self, f) + + def is_empty(self): + return len(self._data) == 1 and self._data[0] == {} + + def clear(self): + """Remove all state and delete the stored copy.""" + try: + os.unlink(self.filename) + except OSError: + pass + self._data = [{}] + + + def __setattr__(self, key, value): + if key.startswith("_"): + object.__setattr__(self, key, value) + else: + self._data[self._index][key] = value + self.save() + + def __getattr__(self, key): + if key.startswith("_"): + raise AttributeError + try: + return self._data[self._index][key] + except KeyError: + raise AttributeError + + def __contains__(self, key): + return key in self._data[self._index] + + def update(self, items): + """Add a dictionary of {name: value} pairs to the state""" + self._data[self._index].update(items) + self.save() + + def keys(self): + return self._data[self._index].keys() + +class StateContext(object): + def __init__(self, state, init_values): + self.state = state + self.init_values = init_values + + def __enter__(self): + if len(self.state._data) == self.state._index + 1: + # This is the case where there is no stored state + new_state = {} + for key in self.init_values: + new_state[key] = self.state._data[self.state._index][key] + self.state._data.append(new_state) + self.state._index += 1 + self.state._logger.debug("Incremented index to %s" % self.state._index) + + def __exit__(self, *args, **kwargs): + if len(self.state._data) > 1: + assert self.state._index == len(self.state._data) - 1 + self.state._data.pop() + self.state._index -= 1 + self.state._logger.debug("Decremented index to %s" % self.state._index) + assert self.state._index >= 0 + else: + raise ValueError("Tried to pop the top state") diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/update/sync.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/sync.py new file mode 100644 index 000000000000..3f6092a046a0 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/sync.py @@ -0,0 +1,177 @@ +import os +import shutil +import sys +import uuid + +from .. import testloader + +from base import Step, StepRunner +from tree import Commit + +here = os.path.abspath(os.path.split(__file__)[0]) + +bsd_license = """W3C 3-clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of works must retain the original copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the original copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of the W3C nor the names of its contributors may be + used to endorse or promote products derived from this work without + specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + + +def copy_wpt_tree(tree, dest): + """Copy the working copy of a Tree to a destination directory. + + :param tree: The Tree to copy. + :param dest: The destination directory""" + if os.path.exists(dest): + assert os.path.isdir(dest) + + shutil.rmtree(dest) + os.mkdir(dest) + + for tree_path in tree.paths(): + source_path = os.path.join(tree.root, tree_path) + dest_path = os.path.join(dest, tree_path) + + dest_dir = os.path.split(dest_path)[0] + if not os.path.isdir(source_path): + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + shutil.copy2(source_path, dest_path) + + for source, destination in [("testharness_runner.html", ""), + ("testharnessreport.js", "resources/")]: + source_path = os.path.join(here, os.pardir, source) + dest_path = os.path.join(dest, destination, os.path.split(source)[1]) + shutil.copy2(source_path, dest_path) + + add_license(dest) + + +def add_license(dest): + """Write the bsd license string to a LICENSE file. + + :param dest: Directory in which to place the LICENSE file.""" + with open(os.path.join(dest, "LICENSE"), "w") as f: + f.write(bsd_license) + +class UpdateCheckout(Step): + """Pull changes from upstream into the local sync tree.""" + + provides = ["local_branch"] + + def create(self, state): + sync_tree = state.sync_tree + state.local_branch = uuid.uuid4().hex + sync_tree.update(state.sync["remote_url"], + state.sync["branch"], + state.local_branch) + sync_path = os.path.abspath(sync_tree.root) + if not sync_path in sys.path: + from update import setup_paths + setup_paths(sync_path) + + def restore(self, state): + assert os.path.abspath(state.sync_tree.root) in sys.path + Step.restore(self, state) + + +class GetSyncTargetCommit(Step): + """Find the commit that we will sync to.""" + + provides = ["sync_commit"] + + def create(self, state): + if state.target_rev is None: + #Use upstream branch HEAD as the base commit + state.sync_commit = state.sync_tree.get_remote_sha1(state.sync["remote_url"], + state.sync["branch"]) + else: + state.sync_commit = Commit(state.sync_tree, state.rev) + + state.sync_tree.checkout(state.sync_commit.sha1, state.local_branch, force=True) + self.logger.debug("New base commit is %s" % state.sync_commit.sha1) + + +class LoadManifest(Step): + """Load the test manifest""" + + provides = ["manifest_path", "test_manifest"] + + def create(self, state): + from manifest import manifest + state.manifest_path = os.path.join(state.metadata_path, "MANIFEST.json") + state.test_manifest = manifest.Manifest("/") + + +class UpdateManifest(Step): + """Update the manifest to match the tests in the sync tree checkout""" + + def create(self, state): + from manifest import manifest, update + update.update(state.sync["path"], state.test_manifest) + manifest.write(state.test_manifest, state.manifest_path) + + +class CopyWorkTree(Step): + """Copy the sync tree over to the destination in the local tree""" + + def create(self, state): + copy_wpt_tree(state.sync_tree, + state.tests_path) + + +class CreateSyncPatch(Step): + """Add the updated test files to a commit/patch in the local tree.""" + + def create(self, state): + if state.no_patch: + return + + local_tree = state.local_tree + sync_tree = state.sync_tree + + local_tree.create_patch("web-platform-tests_update_%s" % sync_tree.rev, + "Update %s to revision %s" % (state.suite_name, sync_tree.rev)) + local_tree.add_new(os.path.relpath(state.tests_path, + local_tree.root)) + updated = local_tree.update_patch(include=[state.tests_path, + state.metadata_path]) + local_tree.commit_patch() + + if not updated: + self.logger.info("Nothing to sync") + + +class SyncFromUpstreamRunner(StepRunner): + """(Sub)Runner for doing an upstream sync""" + steps = [UpdateCheckout, + GetSyncTargetCommit, + LoadManifest, + UpdateManifest, + CopyWorkTree, + CreateSyncPatch] diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/update/tree.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/tree.py new file mode 100644 index 000000000000..a15df907aa41 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/tree.py @@ -0,0 +1,383 @@ +import os +import re +import subprocess + +from .. import vcs +from ..vcs import bind_to_repo, git, hg + + +def get_unique_name(existing, initial): + """Get a name either equal to initial or of the form initial_N, for some + integer N, that is not in the set existing. + + + :param existing: Set of names that must not be chosen. + :param initial: Name, or name prefix, to use""" + if initial not in existing: + return initial + for i in xrange(len(existing) + 1): + test = "%s_%s" % (initial, i + 1) + if test not in existing: + return test + assert False + +class NoVCSTree(object): + name = "non-vcs" + + def __init__(self, root=None): + if root is None: + root = os.path.abspath(os.curdir) + self.root = root + + @classmethod + def is_type(cls, path=None): + return True + + @property + def is_clean(self): + return True + + def add_new(self, prefix=None): + pass + + def create_patch(self, patch_name, message): + pass + + def update_patch(self, include=None): + pass + + def commit_patch(self): + pass + + +class HgTree(object): + name = "mercurial" + + def __init__(self, root=None): + if root is None: + root = hg("root").strip() + self.root = root + self.hg = vcs.bind_to_repo(hg, self.root) + + def __getstate__(self): + rv = self.__dict__.copy() + del rv['hg'] + return rv + + def __setstate__(self, dict): + self.__dict__.update(dict) + self.hg = vcs.bind_to_repo(vcs.hg, self.root) + + @classmethod + def is_type(cls, path=None): + kwargs = {"log_error": False} + if path is not None: + kwargs["repo"] = path + try: + hg("root", **kwargs) + except: + return False + return True + + @property + def is_clean(self): + return self.hg("status").strip() == "" + + def add_new(self, prefix=None): + if prefix is not None: + args = ("-I", prefix) + else: + args = () + self.hg("add", *args) + + def create_patch(self, patch_name, message): + try: + self.hg("qinit", log_error=False) + except subprocess.CalledProcessError: + pass + + patch_names = [item.strip() for item in self.hg("qseries").split("\n") if item.strip()] + + suffix = 0 + test_name = patch_name + while test_name in patch_names: + suffix += 1 + test_name = "%s-%i" % (patch_name, suffix) + + self.hg("qnew", test_name, "-X", self.root, "-m", message) + + def update_patch(self, include=None): + if include is not None: + args = [] + for item in include: + args.extend(["-I", item]) + else: + args = () + + self.hg("qrefresh", *args) + return True + + def commit_patch(self): + self.hg("qfinish") + + def contains_commit(self, commit): + try: + self.hg("identify", "-r", commit.sha1) + return True + except subprocess.CalledProcessError: + return False + + +class GitTree(object): + name = "git" + + def __init__(self, root=None): + if root is None: + root = git("rev-parse", "--show-toplevel").strip() + self.root = root + self.git = vcs.bind_to_repo(git, self.root) + self.message = None + self.commit_cls = Commit + + def __getstate__(self): + rv = self.__dict__.copy() + del rv['git'] + return rv + + def __setstate__(self, dict): + self.__dict__.update(dict) + self.git = vcs.bind_to_repo(vcs.git, self.root) + + @classmethod + def is_type(cls, path=None): + kwargs = {"log_error": False} + if path is not None: + kwargs["repo"] = path + try: + git("rev-parse", "--show-toplevel", **kwargs) + except: + return False + return True + + @property + def rev(self): + """Current HEAD revision""" + if vcs.is_git_root(self.root): + return self.git("rev-parse", "HEAD").strip() + else: + return None + + @property + def is_clean(self): + return self.git("status").strip() == "" + + def add_new(self, prefix=None): + """Add files to the staging area. + + :param prefix: None to include all files or a path prefix to + add all files under that path. + """ + if prefix is None: + args = ("-a",) + else: + args = ("--no-ignore-removal", prefix) + self.git("add", *args) + + def list_refs(self, ref_filter=None): + """Get a list of sha1, name tuples for references in a repository. + + :param ref_filter: Pattern that reference name must match (from the end, + matching whole /-delimited segments only + """ + args = [] + if ref_filter is not None: + args.append(ref_filter) + data = self.git("show-ref", *args) + rv = [] + for line in data.split("\n"): + if not line.strip(): + continue + sha1, ref = line.split() + rv.append((sha1, ref)) + return rv + + def list_remote(self, remote, ref_filter=None): + """Return a list of (sha1, name) tupes for references in a remote. + + :param remote: URL of the remote to list. + :param ref_filter: Pattern that the reference name must match. + """ + args = [] + if ref_filter is not None: + args.append(ref_filter) + data = self.git("ls-remote", remote, *args) + rv = [] + for line in data.split("\n"): + if not line.strip(): + continue + sha1, ref = line.split() + rv.append((sha1, ref)) + return rv + + def get_remote_sha1(self, remote, branch): + """Return the SHA1 of a particular branch in a remote. + + :param remote: the remote URL + :param branch: the branch name""" + for sha1, ref in self.list_remote(remote, branch): + if ref == "refs/heads/%s" % branch: + return self.commit_cls(self, sha1) + assert False + + def create_patch(self, patch_name, message): + # In git a patch is actually a commit + self.message = message + + def update_patch(self, include=None): + """Commit the staged changes, or changes to listed files. + + :param include: Either None, to commit staged changes, or a list + of filenames (which must already be in the repo) + to commit + """ + if include is not None: + args = tuple(include) + else: + args = () + + if self.git("status", "-uno", "-z", *args).strip(): + self.git("add", *args) + return True + return False + + def commit_patch(self): + assert self.message is not None + + if self.git("diff", "--name-only", "--staged", "-z").strip(): + self.git("commit", "-m", self.message) + return True + + return False + + def init(self): + self.git("init") + assert vcs.is_git_root(self.root) + + def checkout(self, rev, branch=None, force=False): + """Checkout a particular revision, optionally into a named branch. + + :param rev: Revision identifier (e.g. SHA1) to checkout + :param branch: Branch name to use + :param force: Force-checkout + """ + assert rev is not None + + args = [] + if branch: + branches = [ref[len("refs/heads/"):] for sha1, ref in self.list_refs() + if ref.startswith("refs/heads/")] + branch = get_unique_name(branches, branch) + + args += ["-b", branch] + + if force: + args.append("-f") + args.append(rev) + self.git("checkout", *args) + + def update(self, remote, remote_branch, local_branch): + """Fetch from the remote and checkout into a local branch. + + :param remote: URL to the remote repository + :param remote_branch: Branch on the remote repository to check out + :param local_branch: Local branch name to check out into + """ + if not vcs.is_git_root(self.root): + self.init() + self.git("clean", "-xdf") + self.git("fetch", remote, "%s:%s" % (remote_branch, local_branch)) + self.checkout(local_branch) + self.git("submodule", "update", "--init", "--recursive") + + def clean(self): + self.git("checkout", self.rev) + self.git("branch", "-D", self.local_branch) + + def paths(self): + """List paths in the tree""" + repo_paths = [self.root] + [os.path.join(self.root, path) + for path in self.submodules()] + + rv = [] + + for repo_path in repo_paths: + paths = vcs.git("ls-tree", "-r", "--name-only", "HEAD", repo=repo_path).split("\n") + rel_path = os.path.relpath(repo_path, self.root) + rv.extend(os.path.join(rel_path, item.strip()) for item in paths if item.strip()) + + return rv + + def submodules(self): + """List submodule directories""" + output = self.git("submodule", "status", "--recursive") + rv = [] + for line in output.split("\n"): + line = line.strip() + if not line: + continue + parts = line.split(" ") + rv.append(parts[1]) + return rv + + def contains_commit(self, commit): + try: + self.git("rev-parse", "--verify", commit.sha1) + return True + except subprocess.CalledProcessError: + return False + + +class CommitMessage(object): + def __init__(self, text): + self.text = text + self._parse_message() + + def __str__(self): + return self.text + + def _parse_message(self): + lines = self.text.splitlines() + self.full_summary = lines[0] + self.body = "\n".join(lines[1:]) + + +class Commit(object): + msg_cls = CommitMessage + + _sha1_re = re.compile("^[0-9a-f]{40}$") + + def __init__(self, tree, sha1): + """Object representing a commit in a specific GitTree. + + :param tree: GitTree to which this commit belongs. + :param sha1: Full sha1 string for the commit + """ + assert self._sha1_re.match(sha1) + + self.tree = tree + self.git = tree.git + self.sha1 = sha1 + self.author, self.email, self.message = self._get_meta() + + def __getstate__(self): + rv = self.__dict__.copy() + del rv['git'] + return rv + + def __setstate__(self, dict): + self.__dict__.update(dict) + self.git = self.tree.git + + def _get_meta(self): + author, email, message = self.git("show", "-s", "--format=format:%an\n%ae\n%B", self.sha1).split("\n", 2) + return author, email, self.msg_cls(message) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/update/update.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/update.py new file mode 100644 index 000000000000..4a5e7ab73d4b --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/update.py @@ -0,0 +1,157 @@ +import os +import sys + +from metadata import MetadataUpdateRunner +from sync import SyncFromUpstreamRunner +from tree import GitTree, HgTree, NoVCSTree + +from .. import environment as env +from base import Step, StepRunner, exit_clean, exit_unclean +from state import State + +def setup_paths(sync_path): + sys.path.insert(0, os.path.abspath(sync_path)) + try: + from tools import localpaths + except ImportError: + from wpt_tools import localpaths + +class LoadConfig(Step): + """Step for loading configuration from the ini file and kwargs.""" + + provides = ["sync", "paths", "metadata_path", "tests_path"] + + def create(self, state): + state.sync = {"remote_url": state.kwargs["remote_url"], + "branch": state.kwargs["branch"], + "path": state.kwargs["sync_path"]} + + state.paths = state.kwargs["test_paths"] + state.tests_path = state.paths["/"]["tests_path"] + state.metadata_path = state.paths["/"]["metadata_path"] + + assert state.tests_path.startswith("/") + + +class LoadTrees(Step): + """Step for creating a Tree for the local copy and a GitTree for the + upstream sync.""" + + provides = ["local_tree", "sync_tree"] + + def create(self, state): + if os.path.exists(state.sync["path"]): + sync_tree = GitTree(root=state.sync["path"]) + else: + sync_tree = None + + if GitTree.is_type(): + local_tree = GitTree() + elif HgTree.is_type(): + local_tree = HgTree() + else: + local_tree = NoVCSTree() + + state.update({"local_tree": local_tree, + "sync_tree": sync_tree}) + + +class SyncFromUpstream(Step): + """Step that synchronises a local copy of the code with upstream.""" + + def create(self, state): + if not state.kwargs["sync"]: + return + + if not state.sync_tree: + os.mkdir(state.sync["path"]) + state.sync_tree = GitTree(root=state.sync["path"]) + + kwargs = state.kwargs + with state.push(["sync", "paths", "metadata_path", "tests_path", "local_tree", + "sync_tree"]): + state.target_rev = kwargs["rev"] + state.no_patch = kwargs["no_patch"] + state.suite_name = kwargs["suite_name"] + runner = SyncFromUpstreamRunner(self.logger, state) + runner.run() + + +class UpdateMetadata(Step): + """Update the expectation metadata from a set of run logs""" + + def create(self, state): + if not state.kwargs["run_log"]: + return + + kwargs = state.kwargs + with state.push(["local_tree", "sync_tree", "paths", "serve_root"]): + state.run_log = kwargs["run_log"] + state.ignore_existing = kwargs["ignore_existing"] + state.no_patch = kwargs["no_patch"] + state.suite_name = kwargs["suite_name"] + state.product = kwargs["product"] + state.config = kwargs["config"] + runner = MetadataUpdateRunner(self.logger, state) + runner.run() + + +class UpdateRunner(StepRunner): + """Runner for doing an overall update.""" + steps = [LoadConfig, + LoadTrees, + SyncFromUpstream, + UpdateMetadata] + + +class WPTUpdate(object): + def __init__(self, logger, runner_cls=UpdateRunner, **kwargs): + """Object that controls the running of a whole wptupdate. + + :param runner_cls: Runner subclass holding the overall list of + steps to run. + :param kwargs: Command line arguments + """ + self.runner_cls = runner_cls + self.serve_root = kwargs["test_paths"]["/"]["tests_path"] + + if not kwargs["sync"]: + setup_paths(self.serve_root) + else: + if os.path.exists(kwargs["sync_path"]): + # If the sync path doesn't exist we defer this until it does + setup_paths(kwargs["sync_path"]) + + self.state = State(logger) + self.kwargs = kwargs + self.logger = logger + + def run(self, **kwargs): + if self.kwargs["abort"]: + self.abort() + return exit_clean + + if not self.kwargs["continue"] and not self.state.is_empty(): + self.logger.error("Found existing state. Run with --continue to resume or --abort to clear state") + return exit_unclean + + if self.kwargs["continue"]: + if self.state.is_empty(): + self.logger.error("No sync in progress?") + return exit_clean + + self.kwargs = self.state.kwargs + else: + self.state.kwargs = self.kwargs + + self.state.serve_root = self.serve_root + + update_runner = self.runner_cls(self.logger, self.state) + rv = update_runner.run() + if rv in (exit_clean, None): + self.state.clear() + + return rv + + def abort(self): + self.state.clear() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/vcs.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/vcs.py new file mode 100644 index 000000000000..16d53afc8be6 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/vcs.py @@ -0,0 +1,49 @@ +import subprocess +from functools import partial + +from mozlog import get_default_logger + +logger = None + +def vcs(bin_name): + def inner(command, *args, **kwargs): + global logger + + if logger is None: + logger = get_default_logger("vcs") + + repo = kwargs.pop("repo", None) + log_error = kwargs.pop("log_error", True) + if kwargs: + raise TypeError, kwargs + + args = list(args) + + proc_kwargs = {} + if repo is not None: + proc_kwargs["cwd"] = repo + + command_line = [bin_name, command] + args + logger.debug(" ".join(command_line)) + try: + return subprocess.check_output(command_line, stderr=subprocess.STDOUT, **proc_kwargs) + except subprocess.CalledProcessError as e: + if log_error: + logger.error(e.output) + raise + return inner + +git = vcs("git") +hg = vcs("hg") + + +def bind_to_repo(vcs_func, repo): + return partial(vcs_func, repo=repo) + + +def is_git_root(path): + try: + rv = git("rev-parse", "--show-cdup", repo=path) + except subprocess.CalledProcessError: + return False + return rv == "\n" diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/webdriver_server.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/webdriver_server.py new file mode 100644 index 000000000000..49d9c73b52e5 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/webdriver_server.py @@ -0,0 +1,233 @@ +import abc +import errno +import os +import platform +import socket +import threading +import time +import traceback +import urlparse + +import mozprocess + + +__all__ = ["SeleniumServer", "ChromeDriverServer", + "GeckoDriverServer", "ServoDriverServer", + "WebDriverServer"] + + +class WebDriverServer(object): + __metaclass__ = abc.ABCMeta + + default_base_path = "/" + _used_ports = set() + + def __init__(self, logger, binary, host="127.0.0.1", port=None, + base_path="", env=None, args=None): + if binary is None: + raise ValueError("WebDriver server binary must be given " + "to --webdriver-binary argument") + + self.logger = logger + self.binary = binary + self.host = host + if base_path == "": + self.base_path = self.default_base_path + else: + self.base_path = base_path + self.env = os.environ.copy() if env is None else env + + self._port = port + self._cmd = None + self._args = args if args is not None else [] + self._proc = None + + @abc.abstractmethod + def make_command(self): + """Returns the full command for starting the server process as a list.""" + + def start(self, block=False): + try: + self._run(block) + except KeyboardInterrupt: + self.stop() + + def _run(self, block): + self._cmd = self.make_command() + self._proc = mozprocess.ProcessHandler( + self._cmd, + processOutputLine=self.on_output, + env=self.env, + storeOutput=False) + + try: + self._proc.run() + except OSError as e: + if e.errno == errno.ENOENT: + raise IOError( + "WebDriver HTTP server executable not found: %s" % self.binary) + raise + + self.logger.debug( + "Waiting for server to become accessible: %s" % self.url) + try: + wait_for_service((self.host, self.port)) + except: + self.logger.error( + "WebDriver HTTP server was not accessible " + "within the timeout:\n%s" % traceback.format_exc()) + raise + + if block: + self._proc.wait() + + def stop(self, force=False): + if self.is_alive: + return self._proc.kill() + return not self.is_alive + + @property + def is_alive(self): + return hasattr(self._proc, "proc") and self._proc.poll() is None + + def on_output(self, line): + self.logger.process_output(self.pid, + line.decode("utf8", "replace"), + command=" ".join(self._cmd)) + + @property + def pid(self): + if self._proc is not None: + return self._proc.pid + + @property + def url(self): + return "http://%s:%i%s" % (self.host, self.port, self.base_path) + + @property + def port(self): + if self._port is None: + self._port = self._find_next_free_port() + return self._port + + @staticmethod + def _find_next_free_port(): + port = get_free_port(4444, exclude=WebDriverServer._used_ports) + WebDriverServer._used_ports.add(port) + return port + + +class SeleniumServer(WebDriverServer): + default_base_path = "/wd/hub" + + def make_command(self): + return ["java", "-jar", self.binary, "-port", str(self.port)] + self._args + + +class ChromeDriverServer(WebDriverServer): + default_base_path = "/wd/hub" + + def __init__(self, logger, binary="chromedriver", port=None, + base_path="", args=None): + WebDriverServer.__init__( + self, logger, binary, port=port, base_path=base_path, args=args) + + def make_command(self): + return [self.binary, + cmd_arg("port", str(self.port)), + cmd_arg("url-base", self.base_path) if self.base_path else ""] + self._args + + +class EdgeDriverServer(WebDriverServer): + def __init__(self, logger, binary="MicrosoftWebDriver.exe", port=None, + base_path="", host="localhost", args=None): + WebDriverServer.__init__( + self, logger, binary, host=host, port=port, args=args) + + def make_command(self): + return [self.binary, + "--port=%s" % str(self.port)] + self._args + + +class GeckoDriverServer(WebDriverServer): + def __init__(self, logger, marionette_port=2828, binary="geckodriver", + host="127.0.0.1", port=None, args=None): + env = os.environ.copy() + env["RUST_BACKTRACE"] = "1" + WebDriverServer.__init__(self, logger, binary, host=host, port=port, env=env, args=args) + self.marionette_port = marionette_port + + def make_command(self): + return [self.binary, + "--marionette-port", str(self.marionette_port), + "--host", self.host, + "--port", str(self.port)] + self._args + + +class ServoDriverServer(WebDriverServer): + def __init__(self, logger, binary="servo", binary_args=None, host="127.0.0.1", port=None): + env = os.environ.copy() + env["RUST_BACKTRACE"] = "1" + WebDriverServer.__init__(self, logger, binary, host=host, port=port, env=env) + self.binary_args = binary_args + + def make_command(self): + command = [self.binary, + "--webdriver", str(self.port), + "--hard-fail", + "--headless"] + self._args + if self.binary_args: + command += self.binary_args + return command + + +def cmd_arg(name, value=None): + prefix = "-" if platform.system() == "Windows" else "--" + rv = prefix + name + if value is not None: + rv += "=" + value + return rv + + +def get_free_port(start_port, exclude=None): + """Get the first port number after start_port (inclusive) that is + not currently bound. + + :param start_port: Integer port number at which to start testing. + :param exclude: Set of port numbers to skip""" + port = start_port + while True: + if exclude and port in exclude: + port += 1 + continue + s = socket.socket() + try: + s.bind(("127.0.0.1", port)) + except socket.error: + port += 1 + else: + return port + finally: + s.close() + + +def wait_for_service(addr, timeout=15): + """Waits until network service given as a tuple of (host, port) becomes + available or the `timeout` duration is reached, at which point + ``socket.error`` is raised.""" + end = time.time() + timeout + while end > time.time(): + so = socket.socket() + try: + so.connect(addr) + except socket.timeout: + pass + except socket.error as e: + if e[0] != errno.ECONNREFUSED: + raise + else: + return True + finally: + so.close() + time.sleep(0.5) + raise socket.error("Service is unavailable: %s:%i" % addr) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptcommandline.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptcommandline.py new file mode 100644 index 000000000000..01d3ab9fb52c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptcommandline.py @@ -0,0 +1,458 @@ +import argparse +import ast +import os +import sys +from collections import OrderedDict +from distutils.spawn import find_executable + +import config +import wpttest + + +def abs_path(path): + return os.path.abspath(os.path.expanduser(path)) + + +def url_or_path(path): + import urlparse + + parsed = urlparse.urlparse(path) + if len(parsed.scheme) > 2: + return path + else: + return abs_path(path) + + +def require_arg(kwargs, name, value_func=None): + if value_func is None: + value_func = lambda x: x is not None + + if not name in kwargs or not value_func(kwargs[name]): + print >> sys.stderr, "Missing required argument %s" % name + sys.exit(1) + + +def create_parser(product_choices=None): + from mozlog import commandline + + import products + + if product_choices is None: + config_data = config.load() + product_choices = products.products_enabled(config_data) + + parser = argparse.ArgumentParser(description="""Runner for web-platform-tests tests.""", + usage="""%(prog)s [OPTION]... [TEST]... + +TEST is either the full path to a test file to run, or the URL of a test excluding +scheme host and port.""") + parser.add_argument("--manifest-update", action="store_true", default=False, + help="Regenerate the test manifest.") + + parser.add_argument("--timeout-multiplier", action="store", type=float, default=None, + help="Multiplier relative to standard test timeout to use") + parser.add_argument("--run-by-dir", type=int, nargs="?", default=False, + help="Split run into groups by directories. With a parameter," + "limit the depth of splits e.g. --run-by-dir=1 to split by top-level" + "directory") + parser.add_argument("--processes", action="store", type=int, default=None, + help="Number of simultaneous processes to use") + + parser.add_argument("--no-capture-stdio", action="store_true", default=False, + help="Don't capture stdio and write to logging") + + mode_group = parser.add_argument_group("Mode") + mode_group.add_argument("--list-test-groups", action="store_true", + default=False, + help="List the top level directories containing tests that will run.") + mode_group.add_argument("--list-disabled", action="store_true", + default=False, + help="List the tests that are disabled on the current platform") + + test_selection_group = parser.add_argument_group("Test Selection") + test_selection_group.add_argument("--test-types", action="store", + nargs="*", default=wpttest.enabled_tests, + choices=wpttest.enabled_tests, + help="Test types to run") + test_selection_group.add_argument("--include", action="append", + help="URL prefix to include") + test_selection_group.add_argument("--exclude", action="append", + help="URL prefix to exclude") + test_selection_group.add_argument("--include-manifest", type=abs_path, + help="Path to manifest listing tests to include") + test_selection_group.add_argument("--tag", action="append", dest="tags", + help="Labels applied to tests to include in the run. Labels starting dir: are equivalent to top-level directories.") + + debugging_group = parser.add_argument_group("Debugging") + debugging_group.add_argument('--debugger', const="__default__", nargs="?", + help="run under a debugger, e.g. gdb or valgrind") + debugging_group.add_argument('--debugger-args', help="arguments to the debugger") + debugging_group.add_argument("--repeat", action="store", type=int, default=1, + help="Number of times to run the tests") + debugging_group.add_argument("--repeat-until-unexpected", action="store_true", default=None, + help="Run tests in a loop until one returns an unexpected result") + debugging_group.add_argument('--pause-after-test', action="store_true", default=None, + help="Halt the test runner after each test (this happens by default if only a single test is run)") + debugging_group.add_argument('--no-pause-after-test', dest="pause_after_test", action="store_false", + help="Don't halt the test runner irrespective of the number of tests run") + + debugging_group.add_argument('--pause-on-unexpected', action="store_true", + help="Halt the test runner when an unexpected result is encountered") + debugging_group.add_argument('--no-restart-on-unexpected', dest="restart_on_unexpected", + default=True, action="store_false", + help="Don't restart on an unexpected result") + + debugging_group.add_argument("--symbols-path", action="store", type=url_or_path, + help="Path or url to symbols file used to analyse crash minidumps.") + debugging_group.add_argument("--stackwalk-binary", action="store", type=abs_path, + help="Path to stackwalker program used to analyse minidumps.") + + debugging_group.add_argument("--pdb", action="store_true", + help="Drop into pdb on python exception") + + config_group = parser.add_argument_group("Configuration") + config_group.add_argument("--binary", action="store", + type=abs_path, help="Binary to run tests against") + config_group.add_argument('--binary-arg', + default=[], action="append", dest="binary_args", + help="Extra argument for the binary") + config_group.add_argument("--webdriver-binary", action="store", metavar="BINARY", + type=abs_path, help="WebDriver server binary to use") + config_group.add_argument('--webdriver-arg', + default=[], action="append", dest="webdriver_args", + help="Extra argument for the WebDriver binary") + + config_group.add_argument("--metadata", action="store", type=abs_path, dest="metadata_root", + help="Path to root directory containing test metadata"), + config_group.add_argument("--tests", action="store", type=abs_path, dest="tests_root", + help="Path to root directory containing test files"), + config_group.add_argument("--run-info", action="store", type=abs_path, + help="Path to directory containing extra json files to add to run info") + config_group.add_argument("--product", action="store", choices=product_choices, + default=None, help="Browser against which to run tests") + config_group.add_argument("--config", action="store", type=abs_path, dest="config", + help="Path to config file") + + build_type = parser.add_mutually_exclusive_group() + build_type.add_argument("--debug-build", dest="debug", action="store_true", + default=None, + help="Build is a debug build (overrides any mozinfo file)") + build_type.add_argument("--release-build", dest="debug", action="store_false", + default=None, + help="Build is a release (overrides any mozinfo file)") + + + chunking_group = parser.add_argument_group("Test Chunking") + chunking_group.add_argument("--total-chunks", action="store", type=int, default=1, + help="Total number of chunks to use") + chunking_group.add_argument("--this-chunk", action="store", type=int, default=1, + help="Chunk number to run") + chunking_group.add_argument("--chunk-type", action="store", choices=["none", "equal_time", "hash", "dir_hash"], + default=None, help="Chunking type to use") + + ssl_group = parser.add_argument_group("SSL/TLS") + ssl_group.add_argument("--ssl-type", action="store", default=None, + choices=["openssl", "pregenerated", "none"], + help="Type of ssl support to enable (running without ssl may lead to spurious errors)") + + ssl_group.add_argument("--openssl-binary", action="store", + help="Path to openssl binary", default="openssl") + ssl_group.add_argument("--certutil-binary", action="store", + help="Path to certutil binary for use with Firefox + ssl") + + ssl_group.add_argument("--ca-cert-path", action="store", type=abs_path, + help="Path to ca certificate when using pregenerated ssl certificates") + ssl_group.add_argument("--host-key-path", action="store", type=abs_path, + help="Path to host private key when using pregenerated ssl certificates") + ssl_group.add_argument("--host-cert-path", action="store", type=abs_path, + help="Path to host certificate when using pregenerated ssl certificates") + + gecko_group = parser.add_argument_group("Gecko-specific") + gecko_group.add_argument("--prefs-root", dest="prefs_root", action="store", type=abs_path, + help="Path to the folder containing browser prefs") + gecko_group.add_argument("--disable-e10s", dest="gecko_e10s", action="store_false", default=True, + help="Run tests without electrolysis preferences") + gecko_group.add_argument("--stackfix-dir", dest="stackfix_dir", action="store", + help="Path to directory containing assertion stack fixing scripts") + gecko_group.add_argument("--setpref", dest="extra_prefs", action='append', + default=[], metavar="PREF=VALUE", + help="Defines an extra user preference (overrides those in prefs_root)") + + servo_group = parser.add_argument_group("Servo-specific") + servo_group.add_argument("--user-stylesheet", + default=[], action="append", dest="user_stylesheets", + help="Inject a user CSS stylesheet into every test.") + + sauce_group = parser.add_argument_group("Sauce Labs-specific") + sauce_group.add_argument("--sauce-browser", dest="sauce_browser", + help="Sauce Labs browser name") + sauce_group.add_argument("--sauce-platform", dest="sauce_platform", + help="Sauce Labs OS platform") + sauce_group.add_argument("--sauce-version", dest="sauce_version", + help="Sauce Labs browser version") + sauce_group.add_argument("--sauce-build", dest="sauce_build", + help="Sauce Labs build identifier") + sauce_group.add_argument("--sauce-tags", dest="sauce_tags", nargs="*", + help="Sauce Labs identifying tag", default=[]) + sauce_group.add_argument("--sauce-tunnel-id", dest="sauce_tunnel_id", + help="Sauce Connect tunnel identifier") + sauce_group.add_argument("--sauce-user", dest="sauce_user", + help="Sauce Labs user name") + sauce_group.add_argument("--sauce-key", dest="sauce_key", + default=os.environ.get("SAUCE_ACCESS_KEY"), + help="Sauce Labs access key") + sauce_group.add_argument("--sauce-connect-binary", + dest="sauce_connect_binary", + help="Path to Sauce Connect binary") + + parser.add_argument("test_list", nargs="*", + help="List of URLs for tests to run, or paths including tests to run. " + "(equivalent to --include)") + + commandline.add_logging_group(parser) + return parser + + +def set_from_config(kwargs): + if kwargs["config"] is None: + config_path = config.path() + else: + config_path = kwargs["config"] + + kwargs["config_path"] = config_path + + kwargs["config"] = config.read(kwargs["config_path"]) + + keys = {"paths": [("prefs", "prefs_root", True), + ("run_info", "run_info", True)], + "web-platform-tests": [("remote_url", "remote_url", False), + ("branch", "branch", False), + ("sync_path", "sync_path", True)], + "SSL": [("openssl_binary", "openssl_binary", True), + ("certutil_binary", "certutil_binary", True), + ("ca_cert_path", "ca_cert_path", True), + ("host_cert_path", "host_cert_path", True), + ("host_key_path", "host_key_path", True)]} + + for section, values in keys.iteritems(): + for config_value, kw_value, is_path in values: + if kw_value in kwargs and kwargs[kw_value] is None: + if not is_path: + new_value = kwargs["config"].get(section, config.ConfigDict({})).get(config_value) + else: + new_value = kwargs["config"].get(section, config.ConfigDict({})).get_path(config_value) + kwargs[kw_value] = new_value + + kwargs["test_paths"] = get_test_paths(kwargs["config"]) + + if kwargs["tests_root"]: + if "/" not in kwargs["test_paths"]: + kwargs["test_paths"]["/"] = {} + kwargs["test_paths"]["/"]["tests_path"] = kwargs["tests_root"] + + if kwargs["metadata_root"]: + if "/" not in kwargs["test_paths"]: + kwargs["test_paths"]["/"] = {} + kwargs["test_paths"]["/"]["metadata_path"] = kwargs["metadata_root"] + + kwargs["suite_name"] = kwargs["config"].get("web-platform-tests", {}).get("name", "web-platform-tests") + + +def get_test_paths(config): + # Set up test_paths + test_paths = OrderedDict() + + for section in config.iterkeys(): + if section.startswith("manifest:"): + manifest_opts = config.get(section) + url_base = manifest_opts.get("url_base", "/") + test_paths[url_base] = { + "tests_path": manifest_opts.get_path("tests"), + "metadata_path": manifest_opts.get_path("metadata")} + + return test_paths + + +def exe_path(name): + if name is None: + return + + path = find_executable(name) + if os.access(path, os.X_OK): + return path + + +def check_args(kwargs): + set_from_config(kwargs) + + for test_paths in kwargs["test_paths"].itervalues(): + if not ("tests_path" in test_paths and + "metadata_path" in test_paths): + print "Fatal: must specify both a test path and metadata path" + sys.exit(1) + for key, path in test_paths.iteritems(): + name = key.split("_", 1)[0] + + if not os.path.exists(path): + print "Fatal: %s path %s does not exist" % (name, path) + sys.exit(1) + + if not os.path.isdir(path): + print "Fatal: %s path %s is not a directory" % (name, path) + sys.exit(1) + + if kwargs["product"] is None: + kwargs["product"] = "firefox" + + if "sauce" in kwargs["product"]: + kwargs["pause_after_test"] = False + + if kwargs["test_list"]: + if kwargs["include"] is not None: + kwargs["include"].extend(kwargs["test_list"]) + else: + kwargs["include"] = kwargs["test_list"] + + if kwargs["run_info"] is None: + kwargs["run_info"] = kwargs["config_path"] + + if kwargs["this_chunk"] > 1: + require_arg(kwargs, "total_chunks", lambda x: x >= kwargs["this_chunk"]) + + if kwargs["chunk_type"] is None: + if kwargs["total_chunks"] > 1: + kwargs["chunk_type"] = "dir_hash" + else: + kwargs["chunk_type"] = "none" + + if kwargs["processes"] is None: + kwargs["processes"] = 1 + + if kwargs["debugger"] is not None: + import mozdebug + if kwargs["debugger"] == "__default__": + kwargs["debugger"] = mozdebug.get_default_debugger_name() + debug_info = mozdebug.get_debugger_info(kwargs["debugger"], + kwargs["debugger_args"]) + if debug_info and debug_info.interactive: + if kwargs["processes"] != 1: + kwargs["processes"] = 1 + kwargs["no_capture_stdio"] = True + kwargs["debug_info"] = debug_info + else: + kwargs["debug_info"] = None + + if kwargs["binary"] is not None: + if not os.path.exists(kwargs["binary"]): + print >> sys.stderr, "Binary path %s does not exist" % kwargs["binary"] + sys.exit(1) + + if kwargs["ssl_type"] is None: + if None not in (kwargs["ca_cert_path"], kwargs["host_cert_path"], kwargs["host_key_path"]): + kwargs["ssl_type"] = "pregenerated" + elif exe_path(kwargs["openssl_binary"]) is not None: + kwargs["ssl_type"] = "openssl" + else: + kwargs["ssl_type"] = "none" + + if kwargs["ssl_type"] == "pregenerated": + require_arg(kwargs, "ca_cert_path", lambda x:os.path.exists(x)) + require_arg(kwargs, "host_cert_path", lambda x:os.path.exists(x)) + require_arg(kwargs, "host_key_path", lambda x:os.path.exists(x)) + + elif kwargs["ssl_type"] == "openssl": + path = exe_path(kwargs["openssl_binary"]) + if path is None: + print >> sys.stderr, "openssl-binary argument missing or not a valid executable" + sys.exit(1) + kwargs["openssl_binary"] = path + + if kwargs["ssl_type"] != "none" and kwargs["product"] == "firefox": + path = exe_path(kwargs["certutil_binary"]) + if path is None: + print >> sys.stderr, "certutil-binary argument missing or not a valid executable" + sys.exit(1) + kwargs["certutil_binary"] = path + + if kwargs['extra_prefs']: + missing = any('=' not in prefarg for prefarg in kwargs['extra_prefs']) + if missing: + print >> sys.stderr, "Preferences via --setpref must be in key=value format" + sys.exit(1) + kwargs['extra_prefs'] = [tuple(prefarg.split('=', 1)) for prefarg in + kwargs['extra_prefs']] + + return kwargs + + +def check_args_update(kwargs): + set_from_config(kwargs) + + if kwargs["product"] is None: + kwargs["product"] = "firefox" + + +def create_parser_update(product_choices=None): + from mozlog.structured import commandline + + import products + + if product_choices is None: + config_data = config.load() + product_choices = products.products_enabled(config_data) + + parser = argparse.ArgumentParser("web-platform-tests-update", + description="Update script for web-platform-tests tests.") + parser.add_argument("--product", action="store", choices=product_choices, + default=None, help="Browser for which metadata is being updated") + parser.add_argument("--config", action="store", type=abs_path, help="Path to config file") + parser.add_argument("--metadata", action="store", type=abs_path, dest="metadata_root", + help="Path to the folder containing test metadata"), + parser.add_argument("--tests", action="store", type=abs_path, dest="tests_root", + help="Path to web-platform-tests"), + parser.add_argument("--sync-path", action="store", type=abs_path, + help="Path to store git checkout of web-platform-tests during update"), + parser.add_argument("--remote_url", action="store", + help="URL of web-platfrom-tests repository to sync against"), + parser.add_argument("--branch", action="store", type=abs_path, + help="Remote branch to sync against") + parser.add_argument("--rev", action="store", help="Revision to sync to") + parser.add_argument("--no-patch", action="store_true", + help="Don't create an mq patch or git commit containing the changes.") + parser.add_argument("--sync", dest="sync", action="store_true", default=False, + help="Sync the tests with the latest from upstream") + parser.add_argument("--ignore-existing", action="store_true", help="When updating test results only consider results from the logfiles provided, not existing expectations.") + parser.add_argument("--continue", action="store_true", help="Continue a previously started run of the update script") + parser.add_argument("--abort", action="store_true", help="Clear state from a previous incomplete run of the update script") + # Should make this required iff run=logfile + parser.add_argument("run_log", nargs="*", type=abs_path, + help="Log file from run of tests") + commandline.add_logging_group(parser) + return parser + + +def create_parser_reduce(product_choices=None): + parser = create_parser(product_choices) + parser.add_argument("target", action="store", help="Test id that is unstable") + return parser + + +def parse_args(): + parser = create_parser() + rv = vars(parser.parse_args()) + check_args(rv) + return rv + + +def parse_args_update(): + parser = create_parser_update() + rv = vars(parser.parse_args()) + check_args_update(rv) + return rv + + +def parse_args_reduce(): + parser = create_parser_reduce() + rv = vars(parser.parse_args()) + check_args(rv) + return rv diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptlogging.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptlogging.py new file mode 100644 index 000000000000..1ab6755c4352 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptlogging.py @@ -0,0 +1,121 @@ +import logging +import sys +import threading +from StringIO import StringIO +from multiprocessing import Queue + +from mozlog import commandline, stdadapter + +def setup(args, defaults): + logger = commandline.setup_logging("web-platform-tests", args, defaults) + setup_stdlib_logger() + + for name in args.keys(): + if name.startswith("log_"): + args.pop(name) + + return logger + + +def setup_stdlib_logger(): + logging.root.handlers = [] + logging.root = stdadapter.std_logging_adapter(logging.root) + + +class LogLevelRewriter(object): + """Filter that replaces log messages at specified levels with messages + at a different level. + + This can be used to e.g. downgrade log messages from ERROR to WARNING + in some component where ERRORs are not critical. + + :param inner: Handler to use for messages that pass this filter + :param from_levels: List of levels which should be affected + :param to_level: Log level to set for the affected messages + """ + def __init__(self, inner, from_levels, to_level): + self.inner = inner + self.from_levels = [item.upper() for item in from_levels] + self.to_level = to_level.upper() + + def __call__(self, data): + if data["action"] == "log" and data["level"].upper() in self.from_levels: + data = data.copy() + data["level"] = self.to_level + return self.inner(data) + + + +class LogThread(threading.Thread): + def __init__(self, queue, logger, level): + self.queue = queue + self.log_func = getattr(logger, level) + threading.Thread.__init__(self, name="Thread-Log") + self.daemon = True + + def run(self): + while True: + try: + msg = self.queue.get() + except (EOFError, IOError): + break + if msg is None: + break + else: + self.log_func(msg) + + +class LoggingWrapper(StringIO): + """Wrapper for file like objects to redirect output to logger + instead""" + + def __init__(self, queue, prefix=None): + StringIO.__init__(self) + self.queue = queue + self.prefix = prefix + + def write(self, data): + if isinstance(data, str): + data = data.decode("utf8") + + if data.endswith("\n"): + data = data[:-1] + if data.endswith("\r"): + data = data[:-1] + if not data: + return + if self.prefix is not None: + data = "%s: %s" % (self.prefix, data) + self.queue.put(data) + + def flush(self): + pass + + +class CaptureIO(object): + def __init__(self, logger, do_capture): + self.logger = logger + self.do_capture = do_capture + self.logging_queue = None + self.logging_thread = None + self.original_stdio = None + + def __enter__(self): + if self.do_capture: + self.original_stdio = (sys.stdout, sys.stderr) + self.logging_queue = Queue() + self.logging_thread = LogThread(self.logging_queue, self.logger, "info") + sys.stdout = LoggingWrapper(self.logging_queue, prefix="STDOUT") + sys.stderr = LoggingWrapper(self.logging_queue, prefix="STDERR") + self.logging_thread.start() + + def __exit__(self, *args, **kwargs): + if self.do_capture: + sys.stdout, sys.stderr = self.original_stdio + if self.logging_queue is not None: + self.logger.info("Closing logging queue") + self.logging_queue.put(None) + if self.logging_thread is not None: + self.logging_thread.join(10) + self.logging_queue.close() + self.logger.info("queue closed") diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/__init__.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/__init__.py new file mode 100644 index 000000000000..6b64784c7e66 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/__init__.py @@ -0,0 +1,4 @@ +from serializer import serialize +from parser import parse +from backends.static import compile as compile_static +from backends.conditional import compile as compile_condition diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/__init__.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py new file mode 100644 index 000000000000..f0f4ecf335ff --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py @@ -0,0 +1,330 @@ +import operator + +from ..node import NodeVisitor, DataNode, ConditionalNode, KeyValueNode, ListNode, ValueNode +from ..parser import parse + + +class ConditionalValue(object): + def __init__(self, node, condition_func): + self.node = node + self.condition_func = condition_func + if isinstance(node, ConditionalNode): + assert len(node.children) == 2 + self.condition_node = self.node.children[0] + self.value_node = self.node.children[1] + else: + assert isinstance(node, (ValueNode, ListNode)) + self.condition_node = None + self.value_node = self.node + + @property + def value(self): + if isinstance(self.value_node, ValueNode): + return self.value_node.data + else: + return [item.data for item in self.value_node.children] + + @value.setter + def value(self, value): + self.value_node.data = value + + def __call__(self, run_info): + return self.condition_func(run_info) + + def set_value(self, value): + self.value = value + + def remove(self): + if len(self.node.parent.children) == 1: + self.node.parent.remove() + self.node.remove() + + +class Compiler(NodeVisitor): + def compile(self, tree, data_cls_getter=None, **kwargs): + """Compile a raw AST into a form where conditional expressions + are represented by ConditionalValue objects that can be evaluated + at runtime. + + tree - The root node of the wptmanifest AST to compile + + data_cls_getter - A function taking two parameters; the previous + output node and the current ast node and returning + the class of the output node to use for the current + ast node + """ + if data_cls_getter is None: + self.data_cls_getter = lambda x, y: ManifestItem + else: + self.data_cls_getter = data_cls_getter + + self.tree = tree + self.output_node = self._initial_output_node(tree, **kwargs) + self.visit(tree) + assert self.output_node is not None + return self.output_node + + def compile_condition(self, condition): + """Compile a ConditionalNode into a ConditionalValue. + + condition: A ConditionalNode""" + data_node = DataNode() + key_value_node = KeyValueNode() + key_value_node.append(condition.copy()) + data_node.append(key_value_node) + manifest_item = self.compile(data_node) + return manifest_item._data[None][0] + + def _initial_output_node(self, node, **kwargs): + return self.data_cls_getter(None, None)(node, **kwargs) + + def visit_DataNode(self, node): + if node != self.tree: + output_parent = self.output_node + self.output_node = self.data_cls_getter(self.output_node, node)(node) + else: + output_parent = None + + assert self.output_node is not None + + for child in node.children: + self.visit(child) + + if output_parent is not None: + # Append to the parent *after* processing all the node data + output_parent.append(self.output_node) + self.output_node = self.output_node.parent + + assert self.output_node is not None + + def visit_KeyValueNode(self, node): + key_values = [] + for child in node.children: + condition, value = self.visit(child) + key_values.append(ConditionalValue(child, condition)) + + self.output_node._add_key_value(node, key_values) + + def visit_ListNode(self, node): + return (lambda x:True, [self.visit(child) for child in node.children]) + + def visit_ValueNode(self, node): + return (lambda x: True, node.data) + + def visit_AtomNode(self, node): + return (lambda x: True, node.data) + + def visit_ConditionalNode(self, node): + return self.visit(node.children[0]), self.visit(node.children[1]) + + def visit_StringNode(self, node): + indexes = [self.visit(child) for child in node.children] + + def value(x): + rv = node.data + for index in indexes: + rv = rv[index(x)] + return rv + return value + + def visit_NumberNode(self, node): + if "." in node.data: + return lambda x: float(node.data) + else: + return lambda x: int(node.data) + + def visit_VariableNode(self, node): + indexes = [self.visit(child) for child in node.children] + + def value(x): + data = x[node.data] + for index in indexes: + data = data[index(x)] + return data + return value + + def visit_IndexNode(self, node): + assert len(node.children) == 1 + return self.visit(node.children[0]) + + def visit_UnaryExpressionNode(self, node): + assert len(node.children) == 2 + operator = self.visit(node.children[0]) + operand = self.visit(node.children[1]) + + return lambda x: operator(operand(x)) + + def visit_BinaryExpressionNode(self, node): + assert len(node.children) == 3 + operator = self.visit(node.children[0]) + operand_0 = self.visit(node.children[1]) + operand_1 = self.visit(node.children[2]) + + assert operand_0 is not None + assert operand_1 is not None + + return lambda x: operator(operand_0(x), operand_1(x)) + + def visit_UnaryOperatorNode(self, node): + return {"not": operator.not_}[node.data] + + def visit_BinaryOperatorNode(self, node): + return {"and": operator.and_, + "or": operator.or_, + "==": operator.eq, + "!=": operator.ne}[node.data] + + +class ManifestItem(object): + def __init__(self, node=None, **kwargs): + self.node = node + self.parent = None + self.children = [] + self._data = {} + + def __repr__(self): + return "" % (self.node.data) + + def __str__(self): + rv = [repr(self)] + for item in self.children: + rv.extend(" %s" % line for line in str(item).split("\n")) + return "\n".join(rv) + + def __contains__(self, key): + return key in self._data + + @property + def is_empty(self): + if self._data: + return False + return all(child.is_empty for child in self.children) + + @property + def root(self): + node = self + while node.parent is not None: + node = node.parent + return node + + @property + def name(self): + return self.node.data + + def has_key(self, key): + for node in [self, self.root]: + if key in node._data: + return True + return False + + def get(self, key, run_info=None): + if run_info is None: + run_info = {} + + for node in [self, self.root]: + if key in node._data: + for cond_value in node._data[key]: + try: + matches = cond_value(run_info) + except KeyError: + matches = False + if matches: + return cond_value.value + raise KeyError + + def set(self, key, value, condition=None): + # First try to update the existing value + if key in self._data: + cond_values = self._data[key] + for cond_value in cond_values: + if cond_value.condition_node == condition: + cond_value.value = value + return + # If there isn't a conditional match reuse the existing KeyValueNode as the + # parent + node = None + for child in self.node.children: + if child.data == key: + node = child + break + assert node is not None + + else: + node = KeyValueNode(key) + self.node.append(node) + + value_node = ValueNode(value) + if condition is not None: + conditional_node = ConditionalNode() + conditional_node.append(condition) + conditional_node.append(value_node) + node.append(conditional_node) + cond_value = Compiler().compile_condition(conditional_node) + else: + node.append(value_node) + cond_value = ConditionalValue(value_node, lambda x: True) + + # Update the cache of child values. This is pretty annoying and maybe + # it should just work directly on the tree + if key not in self._data: + self._data[key] = [] + if self._data[key] and self._data[key][-1].condition_node is None: + self._data[key].insert(len(self._data[key]) - 1, cond_value) + else: + self._data[key].append(cond_value) + + def _add_key_value(self, node, values): + """Called during construction to set a key-value node""" + self._data[node.data] = values + + def append(self, child): + self.children.append(child) + child.parent = self + if child.node.parent != self.node: + self.node.append(child.node) + return child + + def remove(self): + if self.parent: + self.parent._remove_child(self) + + def _remove_child(self, child): + self.children.remove(child) + child.parent = None + + def iterchildren(self, name=None): + for item in self.children: + if item.name == name or name is None: + yield item + + def _flatten(self): + rv = {} + for node in [self, self.root]: + for name, value in node._data.iteritems(): + if name not in rv: + rv[name] = value + return rv + + def iteritems(self): + for item in self._flatten().iteritems(): + yield item + + def iterkeys(self): + for item in self._flatten().iterkeys(): + yield item + + def remove_value(self, key, value): + self._data[key].remove(value) + if not self._data[key]: + del self._data[key] + value.remove() + + +def compile_ast(ast, data_cls_getter=None, **kwargs): + return Compiler().compile(ast, data_cls_getter=data_cls_getter, **kwargs) + + +def compile(stream, data_cls_getter=None, **kwargs): + return compile_ast(parse(stream), + data_cls_getter=data_cls_getter, + **kwargs) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/static.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/static.py new file mode 100644 index 000000000000..b2b9fbe94298 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/static.py @@ -0,0 +1,220 @@ +import operator + +from ..node import NodeVisitor +from ..parser import parse + + +class Compiler(NodeVisitor): + """Compiler backend that evaluates conditional expressions + to give static output""" + + def compile(self, tree, expr_data, data_cls_getter=None, **kwargs): + """Compile a raw AST into a form with conditional expressions + evaluated. + + tree - The root node of the wptmanifest AST to compile + + expr_data - A dictionary of key / value pairs to use when + evaluating conditional expressions + + data_cls_getter - A function taking two parameters; the previous + output node and the current ast node and returning + the class of the output node to use for the current + ast node + """ + + self._kwargs = kwargs + self.expr_data = expr_data + + if data_cls_getter is None: + self.data_cls_getter = lambda x, y: ManifestItem + else: + self.data_cls_getter = data_cls_getter + + self.output_node = None + self.visit(tree) + return self.output_node + + def visit_DataNode(self, node): + output_parent = self.output_node + if self.output_node is None: + assert node.parent is None + self.output_node = self.data_cls_getter(None, None)(None, **self._kwargs) + else: + self.output_node = self.data_cls_getter(self.output_node, node)(node.data) + + for child in node.children: + self.visit(child) + + if output_parent is not None: + output_parent.append(self.output_node) + self.output_node = self.output_node.parent + + def visit_KeyValueNode(self, node): + key_name = node.data + key_value = None + for child in node.children: + value = self.visit(child) + if value is not None: + key_value = value + break + if key_value is not None: + self.output_node.set(key_name, key_value) + + def visit_ValueNode(self, node): + return node.data + + def visit_AtomNode(self, node): + return node.data + + def visit_ListNode(self, node): + return [self.visit(child) for child in node.children] + + def visit_ConditionalNode(self, node): + assert len(node.children) == 2 + if self.visit(node.children[0]): + return self.visit(node.children[1]) + + def visit_StringNode(self, node): + value = node.data + for child in node.children: + value = self.visit(child)(value) + return value + + def visit_NumberNode(self, node): + if "." in node.data: + return float(node.data) + else: + return int(node.data) + + def visit_VariableNode(self, node): + value = self.expr_data[node.data] + for child in node.children: + value = self.visit(child)(value) + return value + + def visit_IndexNode(self, node): + assert len(node.children) == 1 + index = self.visit(node.children[0]) + return lambda x: x[index] + + def visit_UnaryExpressionNode(self, node): + assert len(node.children) == 2 + operator = self.visit(node.children[0]) + operand = self.visit(node.children[1]) + + return operator(operand) + + def visit_BinaryExpressionNode(self, node): + assert len(node.children) == 3 + operator = self.visit(node.children[0]) + operand_0 = self.visit(node.children[1]) + operand_1 = self.visit(node.children[2]) + + return operator(operand_0, operand_1) + + def visit_UnaryOperatorNode(self, node): + return {"not": operator.not_}[node.data] + + def visit_BinaryOperatorNode(self, node): + return {"and": operator.and_, + "or": operator.or_, + "==": operator.eq, + "!=": operator.ne}[node.data] + + +class ManifestItem(object): + def __init__(self, name, **kwargs): + self.parent = None + self.name = name + self.children = [] + self._data = {} + + def __repr__(self): + return "" % (self.name) + + def __str__(self): + rv = [repr(self)] + for item in self.children: + rv.extend(" %s" % line for line in str(item).split("\n")) + return "\n".join(rv) + + @property + def is_empty(self): + if self._data: + return False + return all(child.is_empty for child in self.children) + + @property + def root(self): + node = self + while node.parent is not None: + node = node.parent + return node + + def has_key(self, key): + for node in [self, self.root]: + if key in node._data: + return True + return False + + def get(self, key): + for node in [self, self.root]: + if key in node._data: + return node._data[key] + raise KeyError + + def set(self, name, value): + self._data[name] = value + + def remove(self): + if self.parent: + self.parent._remove_child(self) + + def _remove_child(self, child): + self.children.remove(child) + child.parent = None + + def iterchildren(self, name=None): + for item in self.children: + if item.name == name or name is None: + yield item + + def _flatten(self): + rv = {} + for node in [self, self.root]: + for name, value in node._data.iteritems(): + if name not in rv: + rv[name] = value + return rv + + def iteritems(self): + for item in self._flatten().iteritems(): + yield item + + def iterkeys(self): + for item in self._flatten().iterkeys(): + yield item + + def itervalues(self): + for item in self._flatten().itervalues(): + yield item + + def append(self, child): + child.parent = self + self.children.append(child) + return child + + +def compile_ast(ast, expr_data, data_cls_getter=None, **kwargs): + return Compiler().compile(ast, + expr_data, + data_cls_getter=data_cls_getter, + **kwargs) + + +def compile(stream, expr_data, data_cls_getter=None, **kwargs): + return compile_ast(parse(stream), + expr_data, + data_cls_getter=data_cls_getter, + **kwargs) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/node.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/node.py new file mode 100644 index 000000000000..33e9796c430c --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/node.py @@ -0,0 +1,157 @@ +class NodeVisitor(object): + def visit(self, node): + # This is ugly as hell, but we don't have multimethods and + # they aren't trivial to fake without access to the class + # object from the class body + func = getattr(self, "visit_%s" % (node.__class__.__name__)) + return func(node) + + +class Node(object): + def __init__(self, data=None): + self.data = data + self.parent = None + self.children = [] + + def append(self, other): + other.parent = self + self.children.append(other) + + def remove(self): + self.parent.children.remove(self) + + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, self.data) + + def __str__(self): + rv = [repr(self)] + for item in self.children: + rv.extend(" %s" % line for line in str(item).split("\n")) + return "\n".join(rv) + + def __eq__(self, other): + if not (self.__class__ == other.__class__ and + self.data == other.data and + len(self.children) == len(other.children)): + return False + for child, other_child in zip(self.children, other.children): + if not child == other_child: + return False + return True + + def copy(self): + new = self.__class__(self.data) + for item in self.children: + new.append(item.copy()) + return new + + +class DataNode(Node): + def append(self, other): + # Append that retains the invariant that child data nodes + # come after child nodes of other types + other.parent = self + if isinstance(other, DataNode): + self.children.append(other) + else: + index = len(self.children) + while index > 0 and isinstance(self.children[index - 1], DataNode): + index -= 1 + for i in xrange(index): + assert other.data != self.children[i].data + self.children.insert(index, other) + + +class KeyValueNode(Node): + def append(self, other): + # Append that retains the invariant that conditional nodes + # come before unconditional nodes + other.parent = self + if isinstance(other, ValueNode): + if self.children: + assert not isinstance(self.children[-1], ValueNode) + self.children.append(other) + else: + if self.children and isinstance(self.children[-1], ValueNode): + self.children.insert(len(self.children) - 1, other) + else: + self.children.append(other) + + +class ListNode(Node): + def append(self, other): + other.parent = self + self.children.append(other) + + +class ValueNode(Node): + def append(self, other): + raise TypeError + + +class AtomNode(ValueNode): + pass + + +class ConditionalNode(Node): + pass + + +class UnaryExpressionNode(Node): + def __init__(self, operator, operand): + Node.__init__(self) + self.append(operator) + self.append(operand) + + def append(self, other): + Node.append(self, other) + assert len(self.children) <= 2 + + def copy(self): + new = self.__class__(self.children[0].copy(), + self.children[1].copy()) + return new + + +class BinaryExpressionNode(Node): + def __init__(self, operator, operand_0, operand_1): + Node.__init__(self) + self.append(operator) + self.append(operand_0) + self.append(operand_1) + + def append(self, other): + Node.append(self, other) + assert len(self.children) <= 3 + + def copy(self): + new = self.__class__(self.children[0].copy(), + self.children[1].copy(), + self.children[2].copy()) + return new + + +class UnaryOperatorNode(Node): + def append(self, other): + raise TypeError + + +class BinaryOperatorNode(Node): + def append(self, other): + raise TypeError + + +class IndexNode(Node): + pass + + +class VariableNode(Node): + pass + + +class StringNode(Node): + pass + + +class NumberNode(ValueNode): + pass diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/parser.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/parser.py new file mode 100644 index 000000000000..d84a9143fa63 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/parser.py @@ -0,0 +1,746 @@ +#default_value:foo +#include: other.manifest +# +#[test_name.js] +# expected: ERROR +# +# [subtest 1] +# expected: +# os == win: FAIL #This is a comment +# PASS +# + +# TODO: keep comments in the tree + +from __future__ import unicode_literals + +import types +from cStringIO import StringIO + +from node import * + + +class ParseError(Exception): + def __init__(self, filename, line, detail): + self.line = line + self.filename = filename + self.detail = detail + self.message = "%s: %s line %s" % (self.detail, self.filename, self.line) + Exception.__init__(self, self.message) + +eol = object +group_start = object +group_end = object +digits = "0123456789" +open_parens = "[(" +close_parens = "])" +parens = open_parens + close_parens +operator_chars = "=!" + +unary_operators = ["not"] +binary_operators = ["==", "!=", "and", "or"] + +operators = ["==", "!=", "not", "and", "or"] + +atoms = {"True": True, + "False": False, + "Reset": object()} + +def decode(s): + assert isinstance(s, unicode) + return s + + +def precedence(operator_node): + return len(operators) - operators.index(operator_node.data) + + +class TokenTypes(object): + def __init__(self): + for type in ["group_start", "group_end", "paren", "list_start", "list_end", "separator", "ident", "string", "number", "atom", "eof"]: + setattr(self, type, type) + +token_types = TokenTypes() + + +class Tokenizer(object): + def __init__(self): + self.reset() + + def reset(self): + self.indent_levels = [0] + self.state = self.line_start_state + self.next_state = self.data_line_state + self.line_number = 0 + + def tokenize(self, stream): + self.reset() + assert not isinstance(stream, unicode) + if isinstance(stream, str): + stream = StringIO(stream) + if not hasattr(stream, "name"): + self.filename = "" + else: + self.filename = stream.name + + self.next_line_state = self.line_start_state + for i, line in enumerate(stream): + assert isinstance(line, str) + self.state = self.next_line_state + assert self.state is not None + states = [] + self.next_line_state = None + self.line_number = i + 1 + self.index = 0 + self.line = line.decode('utf-8').rstrip() + assert isinstance(self.line, unicode) + while self.state != self.eol_state: + states.append(self.state) + tokens = self.state() + if tokens: + for token in tokens: + yield token + self.state() + while True: + yield (token_types.eof, None) + + def char(self): + if self.index == len(self.line): + return eol + return self.line[self.index] + + def consume(self): + if self.index < len(self.line): + self.index += 1 + + def peek(self, length): + return self.line[self.index:self.index + length] + + def skip_whitespace(self): + while self.char() == " ": + self.consume() + + def eol_state(self): + if self.next_line_state is None: + self.next_line_state = self.line_start_state + + def line_start_state(self): + self.skip_whitespace() + if self.char() == eol: + self.state = self.eol_state + return + if self.index > self.indent_levels[-1]: + self.indent_levels.append(self.index) + yield (token_types.group_start, None) + else: + while self.index < self.indent_levels[-1]: + self.indent_levels.pop() + yield (token_types.group_end, None) + # This is terrible; if we were parsing an expression + # then the next_state will be expr_or_value but when we deindent + # it must always be a heading or key next so we go back to data_line_state + self.next_state = self.data_line_state + if self.index != self.indent_levels[-1]: + raise ParseError(self.filename, self.line_number, "Unexpected indent") + + self.state = self.next_state + + def data_line_state(self): + if self.char() == "[": + yield (token_types.paren, self.char()) + self.consume() + self.state = self.heading_state + else: + self.state = self.key_state + + def heading_state(self): + rv = "" + while True: + c = self.char() + if c == "\\": + rv += self.consume_escape() + elif c == "]": + break + elif c == eol: + raise ParseError(self.filename, self.line_number, "EOL in heading") + else: + rv += c + self.consume() + + yield (token_types.string, decode(rv)) + yield (token_types.paren, "]") + self.consume() + self.state = self.line_end_state + self.next_state = self.data_line_state + + def key_state(self): + rv = "" + while True: + c = self.char() + if c == " ": + self.skip_whitespace() + if self.char() != ":": + raise ParseError(self.filename, self.line_number, "Space in key name") + break + elif c == ":": + break + elif c == eol: + raise ParseError(self.filename, self.line_number, "EOL in key name (missing ':'?)") + elif c == "\\": + rv += self.consume_escape() + else: + rv += c + self.consume() + yield (token_types.string, decode(rv)) + yield (token_types.separator, ":") + self.consume() + self.state = self.after_key_state + + def after_key_state(self): + self.skip_whitespace() + c = self.char() + if c == "#": + self.next_state = self.expr_or_value_state + self.state = self.comment_state + elif c == eol: + self.next_state = self.expr_or_value_state + self.state = self.eol_state + elif c == "[": + self.state = self.list_start_state + else: + self.state = self.value_state + + def list_start_state(self): + yield (token_types.list_start, "[") + self.consume() + self.state = self.list_value_start_state + + def list_value_start_state(self): + self.skip_whitespace() + if self.char() == "]": + self.state = self.list_end_state + elif self.char() in ("'", '"'): + quote_char = self.char() + self.consume() + yield (token_types.string, self.consume_string(quote_char)) + self.skip_whitespace() + if self.char() == "]": + self.state = self.list_end_state + elif self.char() != ",": + raise ParseError(self.filename, self.line_number, "Junk after quoted string") + self.consume() + elif self.char() == "#": + self.state = self.comment_state + self.next_line_state = self.list_value_start_state + elif self.char() == eol: + self.next_line_state = self.list_value_start_state + self.state = self.eol_state + elif self.char() == ",": + raise ParseError(self.filename, self.line_number, "List item started with separator") + elif self.char() == "@": + self.state = self.list_value_atom_state + else: + self.state = self.list_value_state + + def list_value_state(self): + rv = "" + spaces = 0 + while True: + c = self.char() + if c == "\\": + escape = self.consume_escape() + rv += escape + elif c == eol: + raise ParseError(self.filename, self.line_number, "EOL in list value") + elif c == "#": + raise ParseError(self.filename, self.line_number, "EOL in list value (comment)") + elif c == ",": + self.state = self.list_value_start_state + self.consume() + break + elif c == " ": + spaces += 1 + self.consume() + elif c == "]": + self.state = self.list_end_state + self.consume() + break + else: + rv += " " * spaces + spaces = 0 + rv += c + self.consume() + + if rv: + yield (token_types.string, decode(rv)) + + def list_value_atom_state(self): + self.consume() + for _, value in self.list_value_state(): + yield token_types.atom, value + + def list_end_state(self): + self.consume() + yield (token_types.list_end, "]") + self.state = self.line_end_state + + def value_state(self): + self.skip_whitespace() + if self.char() in ("'", '"'): + quote_char = self.char() + self.consume() + yield (token_types.string, self.consume_string(quote_char)) + if self.char() == "#": + self.state = self.comment_state + else: + self.state = self.line_end_state + elif self.char() == "@": + self.consume() + for _, value in self.value_inner_state(): + yield token_types.atom, value + else: + self.state = self.value_inner_state + + def value_inner_state(self): + rv = "" + spaces = 0 + while True: + c = self.char() + if c == "\\": + rv += self.consume_escape() + elif c == "#": + self.state = self.comment_state + break + elif c == " ": + # prevent whitespace before comments from being included in the value + spaces += 1 + self.consume() + elif c == eol: + self.state = self.line_end_state + break + else: + rv += " " * spaces + spaces = 0 + rv += c + self.consume() + yield (token_types.string, decode(rv)) + + def comment_state(self): + while self.char() is not eol: + self.consume() + self.state = self.eol_state + + def line_end_state(self): + self.skip_whitespace() + c = self.char() + if c == "#": + self.state = self.comment_state + elif c == eol: + self.state = self.eol_state + else: + raise ParseError(self.filename, self.line_number, "Junk before EOL %s" % c) + + def consume_string(self, quote_char): + rv = "" + while True: + c = self.char() + if c == "\\": + rv += self.consume_escape() + elif c == quote_char: + self.consume() + break + elif c == eol: + raise ParseError(self.filename, self.line_number, "EOL in quoted string") + else: + rv += c + self.consume() + + return decode(rv) + + def expr_or_value_state(self): + if self.peek(3) == "if ": + self.state = self.expr_state + else: + self.state = self.value_state + + def expr_state(self): + self.skip_whitespace() + c = self.char() + if c == eol: + raise ParseError(self.filename, self.line_number, "EOL in expression") + elif c in "'\"": + self.consume() + yield (token_types.string, self.consume_string(c)) + elif c == "#": + raise ParseError(self.filename, self.line_number, "Comment before end of expression") + elif c == ":": + yield (token_types.separator, c) + self.consume() + self.state = self.value_state + elif c in parens: + self.consume() + yield (token_types.paren, c) + elif c in ("!", "="): + self.state = self.operator_state + elif c in digits: + self.state = self.digit_state + else: + self.state = self.ident_state + + def operator_state(self): + # Only symbolic operators + index_0 = self.index + while True: + c = self.char() + if c == eol: + break + elif c in operator_chars: + self.consume() + else: + self.state = self.expr_state + break + yield (token_types.ident, self.line[index_0:self.index]) + + def digit_state(self): + index_0 = self.index + seen_dot = False + while True: + c = self.char() + if c == eol: + break + elif c in digits: + self.consume() + elif c == ".": + if seen_dot: + raise ParseError(self.filename, self.line_number, "Invalid number") + self.consume() + seen_dot = True + elif c in parens: + break + elif c in operator_chars: + break + elif c == " ": + break + elif c == ":": + break + else: + raise ParseError(self.filename, self.line_number, "Invalid character in number") + + self.state = self.expr_state + yield (token_types.number, self.line[index_0:self.index]) + + def ident_state(self): + index_0 = self.index + while True: + c = self.char() + if c == eol: + break + elif c == ".": + break + elif c in parens: + break + elif c in operator_chars: + break + elif c == " ": + break + elif c == ":": + break + else: + self.consume() + self.state = self.expr_state + yield (token_types.ident, self.line[index_0:self.index]) + + def consume_escape(self): + assert self.char() == "\\" + self.consume() + c = self.char() + self.consume() + if c == "x": + return self.decode_escape(2) + elif c == "u": + return self.decode_escape(4) + elif c == "U": + return self.decode_escape(6) + elif c in ["a", "b", "f", "n", "r", "t", "v"]: + return eval("'\%s'" % c) + elif c is eol: + raise ParseError(self.filename, self.line_number, "EOL in escape") + else: + return c + + def decode_escape(self, length): + value = 0 + for i in xrange(length): + c = self.char() + value *= 16 + value += self.escape_value(c) + self.consume() + + return unichr(value) + + def escape_value(self, c): + if '0' <= c <= '9': + return ord(c) - ord('0') + elif 'a' <= c <= 'f': + return ord(c) - ord('a') + 10 + elif 'A' <= c <= 'F': + return ord(c) - ord('A') + 10 + else: + raise ParseError(self.filename, self.line_number, "Invalid character escape") + + +class Parser(object): + def __init__(self): + self.reset() + + def reset(self): + self.token = None + self.unary_operators = "!" + self.binary_operators = frozenset(["&&", "||", "=="]) + self.tokenizer = Tokenizer() + self.token_generator = None + self.tree = Treebuilder(DataNode(None)) + self.expr_builder = None + self.expr_builders = [] + + def parse(self, input): + self.reset() + self.token_generator = self.tokenizer.tokenize(input) + self.consume() + self.manifest() + return self.tree.node + + def consume(self): + self.token = self.token_generator.next() + + def expect(self, type, value=None): + if self.token[0] != type: + raise ParseError + if value is not None: + if self.token[1] != value: + raise ParseError + + self.consume() + + def manifest(self): + self.data_block() + self.expect(token_types.eof) + + def data_block(self): + while self.token[0] == token_types.string: + self.tree.append(KeyValueNode(self.token[1])) + self.consume() + self.expect(token_types.separator) + self.value_block() + self.tree.pop() + + while self.token == (token_types.paren, "["): + self.consume() + if self.token[0] != token_types.string: + raise ParseError + self.tree.append(DataNode(self.token[1])) + self.consume() + self.expect(token_types.paren, "]") + if self.token[0] == token_types.group_start: + self.consume() + self.data_block() + self.eof_or_end_group() + self.tree.pop() + + def eof_or_end_group(self): + if self.token[0] != token_types.eof: + self.expect(token_types.group_end) + + def value_block(self): + if self.token[0] == token_types.list_start: + self.consume() + self.list_value() + elif self.token[0] == token_types.string: + self.value() + elif self.token[0] == token_types.group_start: + self.consume() + self.expression_values() + if self.token[0] == token_types.string: + self.value() + self.eof_or_end_group() + elif self.token[0] == token_types.atom: + self.atom() + else: + raise ParseError + + def list_value(self): + self.tree.append(ListNode()) + while self.token[0] in (token_types.atom, token_types.string): + if self.token[0] == token_types.atom: + self.atom() + else: + self.value() + self.expect(token_types.list_end) + self.tree.pop() + + def expression_values(self): + while self.token == (token_types.ident, "if"): + self.consume() + self.tree.append(ConditionalNode()) + self.expr_start() + self.expect(token_types.separator) + if self.token[0] == token_types.string: + self.value() + else: + raise ParseError + self.tree.pop() + + def value(self): + self.tree.append(ValueNode(self.token[1])) + self.consume() + self.tree.pop() + + def atom(self): + if self.token[1] not in atoms: + raise ParseError(self.tokenizer.filename, self.tokenizer.line_number, "Unrecognised symbol @%s" % self.token[1]) + self.tree.append(AtomNode(atoms[self.token[1]])) + self.consume() + self.tree.pop() + + def expr_start(self): + self.expr_builder = ExpressionBuilder(self.tokenizer) + self.expr_builders.append(self.expr_builder) + self.expr() + expression = self.expr_builder.finish() + self.expr_builders.pop() + self.expr_builder = self.expr_builders[-1] if self.expr_builders else None + if self.expr_builder: + self.expr_builder.operands[-1].children[-1].append(expression) + else: + self.tree.append(expression) + self.tree.pop() + + def expr(self): + self.expr_operand() + while (self.token[0] == token_types.ident and self.token[1] in binary_operators): + self.expr_bin_op() + self.expr_operand() + + def expr_operand(self): + if self.token == (token_types.paren, "("): + self.consume() + self.expr_builder.left_paren() + self.expr() + self.expect(token_types.paren, ")") + self.expr_builder.right_paren() + elif self.token[0] == token_types.ident and self.token[1] in unary_operators: + self.expr_unary_op() + self.expr_operand() + elif self.token[0] in [token_types.string, token_types.ident]: + self.expr_value() + elif self.token[0] == token_types.number: + self.expr_number() + else: + raise ParseError(self.tokenizer.filename, self.tokenizer.line_number, "Unrecognised operand") + + def expr_unary_op(self): + if self.token[1] in unary_operators: + self.expr_builder.push_operator(UnaryOperatorNode(self.token[1])) + self.consume() + else: + raise ParseError(self.tokenizer.filename, self.tokenizer.line_number, "Expected unary operator") + + def expr_bin_op(self): + if self.token[1] in binary_operators: + self.expr_builder.push_operator(BinaryOperatorNode(self.token[1])) + self.consume() + else: + raise ParseError(self.tokenizer.filename, self.tokenizer.line_number, "Expected binary operator") + + def expr_value(self): + node_type = {token_types.string: StringNode, + token_types.ident: VariableNode}[self.token[0]] + self.expr_builder.push_operand(node_type(self.token[1])) + self.consume() + if self.token == (token_types.paren, "["): + self.consume() + self.expr_builder.operands[-1].append(IndexNode()) + self.expr_start() + self.expect(token_types.paren, "]") + + def expr_number(self): + self.expr_builder.push_operand(NumberNode(self.token[1])) + self.consume() + + +class Treebuilder(object): + def __init__(self, root): + self.root = root + self.node = root + + def append(self, node): + self.node.append(node) + self.node = node + return node + + def pop(self): + node = self.node + self.node = self.node.parent + return node + + +class ExpressionBuilder(object): + def __init__(self, tokenizer): + self.operands = [] + self.operators = [None] + self.tokenizer = tokenizer + + def finish(self): + while self.operators[-1] is not None: + self.pop_operator() + rv = self.pop_operand() + assert self.is_empty() + return rv + + def left_paren(self): + self.operators.append(None) + + def right_paren(self): + while self.operators[-1] is not None: + self.pop_operator() + if not self.operators: + raise ParseError(self.tokenizer.filename, self.tokenizer.line, + "Unbalanced parens") + + assert self.operators.pop() is None + + def push_operator(self, operator): + assert operator is not None + while self.precedence(self.operators[-1]) > self.precedence(operator): + self.pop_operator() + + self.operators.append(operator) + + def pop_operator(self): + operator = self.operators.pop() + if isinstance(operator, BinaryOperatorNode): + operand_1 = self.operands.pop() + operand_0 = self.operands.pop() + self.operands.append(BinaryExpressionNode(operator, operand_0, operand_1)) + else: + operand_0 = self.operands.pop() + self.operands.append(UnaryExpressionNode(operator, operand_0)) + + def push_operand(self, node): + self.operands.append(node) + + def pop_operand(self): + return self.operands.pop() + + def is_empty(self): + return len(self.operands) == 0 and all(item is None for item in self.operators) + + def precedence(self, operator): + if operator is None: + return 0 + return precedence(operator) + + +def parse(stream): + p = Parser() + return p.parse(stream) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/serializer.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/serializer.py new file mode 100644 index 000000000000..52203ab240a9 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/serializer.py @@ -0,0 +1,136 @@ +from node import NodeVisitor, ValueNode, ListNode, BinaryExpressionNode +from parser import atoms, precedence + +atom_names = {v:"@%s" % k for (k,v) in atoms.iteritems()} + +named_escapes = set(["\a", "\b", "\f", "\n", "\r", "\t", "\v"]) + +def escape(string, extras=""): + rv = "" + for c in string: + if c in named_escapes: + rv += c.encode("unicode_escape") + elif c == "\\": + rv += "\\\\" + elif c < '\x20': + rv += "\\x%02x" % ord(c) + elif c in extras: + rv += "\\" + c + else: + rv += c + return rv.encode("utf8") + + +class ManifestSerializer(NodeVisitor): + def __init__(self, skip_empty_data=False): + self.skip_empty_data = skip_empty_data + + def serialize(self, root): + self.indent = 2 + rv = "\n".join(self.visit(root)) + if rv[-1] != "\n": + rv = rv + "\n" + return rv + + def visit_DataNode(self, node): + rv = [] + if not self.skip_empty_data or node.children: + if node.data: + rv.append("[%s]" % escape(node.data, extras="]")) + indent = self.indent * " " + else: + indent = "" + + for child in node.children: + rv.extend("%s%s" % (indent if item else "", item) for item in self.visit(child)) + + if node.parent: + rv.append("") + + return rv + + def visit_KeyValueNode(self, node): + rv = [escape(node.data, ":") + ":"] + indent = " " * self.indent + + if len(node.children) == 1 and isinstance(node.children[0], (ValueNode, ListNode)): + rv[0] += " %s" % self.visit(node.children[0])[0] + else: + for child in node.children: + rv.append(indent + self.visit(child)[0]) + + return rv + + def visit_ListNode(self, node): + rv = ["["] + rv.extend(", ".join(self.visit(child)[0] for child in node.children)) + rv.append("]") + return ["".join(rv)] + + def visit_ValueNode(self, node): + if "#" in node.data or (isinstance(node.parent, ListNode) and + ("," in node.data or "]" in node.data)): + if "\"" in node.data: + quote = "'" + else: + quote = "\"" + else: + quote = "" + return [quote + escape(node.data, extras=quote) + quote] + + def visit_AtomNode(self, node): + return [atom_names[node.data]] + + def visit_ConditionalNode(self, node): + return ["if %s: %s" % tuple(self.visit(item)[0] for item in node.children)] + + def visit_StringNode(self, node): + rv = ["\"%s\"" % escape(node.data, extras="\"")] + for child in node.children: + rv[0] += self.visit(child)[0] + return rv + + def visit_NumberNode(self, node): + return [str(node.data)] + + def visit_VariableNode(self, node): + rv = escape(node.data) + for child in node.children: + rv += self.visit(child) + return [rv] + + def visit_IndexNode(self, node): + assert len(node.children) == 1 + return ["[%s]" % self.visit(node.children[0])[0]] + + def visit_UnaryExpressionNode(self, node): + children = [] + for child in node.children: + child_str = self.visit(child)[0] + if isinstance(child, BinaryExpressionNode): + child_str = "(%s)" % child_str + children.append(child_str) + return [" ".join(children)] + + def visit_BinaryExpressionNode(self, node): + assert len(node.children) == 3 + children = [] + for child_index in [1, 0, 2]: + child = node.children[child_index] + child_str = self.visit(child)[0] + if (isinstance(child, BinaryExpressionNode) and + precedence(node.children[0]) < precedence(child.children[0])): + child_str = "(%s)" % child_str + children.append(child_str) + return [" ".join(children)] + + def visit_UnaryOperatorNode(self, node): + return [str(node.data)] + + def visit_BinaryOperatorNode(self, node): + return [str(node.data)] + + +def serialize(tree, *args, **kwargs): + s = ManifestSerializer(*args, **kwargs) + return s.serialize(tree) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/__init__.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_conditional.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_conditional.py new file mode 100644 index 000000000000..d9ffdf255072 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_conditional.py @@ -0,0 +1,143 @@ +import unittest + +from cStringIO import StringIO + +from ..backends import conditional +from ..node import BinaryExpressionNode, BinaryOperatorNode, VariableNode, NumberNode + + +class TestConditional(unittest.TestCase): + def compile(self, input_text): + return conditional.compile(input_text) + + def test_get_0(self): + data = """ +key: value + +[Heading 1] + other_key: + if a == 1: value_1 + if a == 2: value_2 + value_3 +""" + + manifest = self.compile(data) + + self.assertEquals(manifest.get("key"), "value") + children = list(item for item in manifest.iterchildren()) + self.assertEquals(len(children), 1) + section = children[0] + self.assertEquals(section.name, "Heading 1") + + self.assertEquals(section.get("other_key", {"a": 1}), "value_1") + self.assertEquals(section.get("other_key", {"a": 2}), "value_2") + self.assertEquals(section.get("other_key", {"a": 7}), "value_3") + self.assertEquals(section.get("key"), "value") + + def test_get_1(self): + data = """ +key: value + +[Heading 1] + other_key: + if a == "1": value_1 + if a == 2: value_2 + value_3 +""" + + manifest = self.compile(data) + + children = list(item for item in manifest.iterchildren()) + section = children[0] + + self.assertEquals(section.get("other_key", {"a": "1"}), "value_1") + self.assertEquals(section.get("other_key", {"a": 1}), "value_3") + + def test_get_2(self): + data = """ +key: + if a[1] == "b": value_1 + if a[1] == 2: value_2 + value_3 +""" + + manifest = self.compile(data) + + self.assertEquals(manifest.get("key", {"a": "ab"}), "value_1") + self.assertEquals(manifest.get("key", {"a": [1, 2]}), "value_2") + + def test_get_3(self): + data = """ +key: + if a[1] == "ab"[1]: value_1 + if a[1] == 2: value_2 + value_3 +""" + + manifest = self.compile(data) + + self.assertEquals(manifest.get("key", {"a": "ab"}), "value_1") + self.assertEquals(manifest.get("key", {"a": [1, 2]}), "value_2") + + def test_set_0(self): + data = """ +key: + if a == "a": value_1 + if a == "b": value_2 + value_3 +""" + manifest = self.compile(data) + + manifest.set("new_key", "value_new") + + self.assertEquals(manifest.get("new_key"), "value_new") + + def test_set_1(self): + data = """ +key: + if a == "a": value_1 + if a == "b": value_2 + value_3 +""" + + manifest = self.compile(data) + + manifest.set("key", "value_new") + + self.assertEquals(manifest.get("key"), "value_new") + self.assertEquals(manifest.get("key", {"a": "a"}), "value_1") + + def test_set_2(self): + data = """ +key: + if a == "a": value_1 + if a == "b": value_2 + value_3 +""" + + manifest = self.compile(data) + + expr = BinaryExpressionNode(BinaryOperatorNode("=="), + VariableNode("a"), + NumberNode("1")) + + manifest.set("key", "value_new", expr) + + self.assertEquals(manifest.get("key", {"a": 1}), "value_new") + self.assertEquals(manifest.get("key", {"a": "a"}), "value_1") + + def test_api_0(self): + data = """ +key: + if a == 1.5: value_1 + value_2 +key_1: other_value +""" + manifest = self.compile(data) + + self.assertFalse(manifest.is_empty) + self.assertEquals(manifest.root, manifest) + self.assertTrue(manifest.has_key("key_1")) + self.assertFalse(manifest.has_key("key_2")) + + self.assertEquals(set(manifest.iterkeys()), set(["key", "key_1"])) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_parser.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_parser.py new file mode 100644 index 000000000000..765c984f42f5 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_parser.py @@ -0,0 +1,75 @@ +import unittest + +from cStringIO import StringIO + +from .. import parser + +# There aren't many tests here because it turns out to be way more convenient to +# use test_serializer for the majority of cases + + +class TestExpression(unittest.TestCase): + def setUp(self): + self.parser = parser.Parser() + + def parse(self, input_str): + return self.parser.parse(StringIO(input_str)) + + def compare(self, input_text, expected): + actual = self.parse(input_text) + self.match(expected, actual) + + def match(self, expected_node, actual_node): + self.assertEquals(expected_node[0], actual_node.__class__.__name__) + self.assertEquals(expected_node[1], actual_node.data) + self.assertEquals(len(expected_node[2]), len(actual_node.children)) + for expected_child, actual_child in zip(expected_node[2], actual_node.children): + self.match(expected_child, actual_child) + + def test_expr_0(self): + self.compare( + """ +key: + if x == 1 : value""", + ["DataNode", None, + [["KeyValueNode", "key", + [["ConditionalNode", None, + [["BinaryExpressionNode", None, + [["BinaryOperatorNode", "==", []], + ["VariableNode", "x", []], + ["NumberNode", "1", []] + ]], + ["ValueNode", "value", []], + ]]]]]] + ) + + def test_expr_1(self): + self.compare( + """ +key: + if not x and y : value""", + ["DataNode", None, + [["KeyValueNode", "key", + [["ConditionalNode", None, + [["BinaryExpressionNode", None, + [["BinaryOperatorNode", "and", []], + ["UnaryExpressionNode", None, + [["UnaryOperatorNode", "not", []], + ["VariableNode", "x", []] + ]], + ["VariableNode", "y", []] + ]], + ["ValueNode", "value", []], + ]]]]]] + ) + + def test_atom_0(self): + with self.assertRaises(parser.ParseError): + self.parse("key: @Unknown") + + def test_atom_1(self): + with self.assertRaises(parser.ParseError): + self.parse("key: @true") + +if __name__ == "__main__": + unittest.main() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_serializer.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_serializer.py new file mode 100644 index 000000000000..6db2cbbbb477 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_serializer.py @@ -0,0 +1,227 @@ +import sys +import unittest + +from cStringIO import StringIO + +import pytest + +from .. import parser, serializer + + +class TokenizerTest(unittest.TestCase): + def setUp(self): + self.serializer = serializer.ManifestSerializer() + self.parser = parser.Parser() + + def serialize(self, input_str): + return self.serializer.serialize(self.parser.parse(input_str)) + + def compare(self, input_str, expected=None): + if expected is None: + expected = input_str + expected = expected.encode("utf8") + actual = self.serialize(input_str) + self.assertEquals(actual, expected) + + def test_0(self): + self.compare("""key: value +[Heading 1] + other_key: other_value +""") + + def test_1(self): + self.compare("""key: value +[Heading 1] + other_key: + if a or b: other_value +""") + + def test_2(self): + self.compare("""key: value +[Heading 1] + other_key: + if a or b: other_value + fallback_value +""") + + def test_3(self): + self.compare("""key: value +[Heading 1] + other_key: + if a == 1: other_value + fallback_value +""") + + def test_4(self): + self.compare("""key: value +[Heading 1] + other_key: + if a == "1": other_value + fallback_value +""") + + def test_5(self): + self.compare("""key: value +[Heading 1] + other_key: + if a == "abc"[1]: other_value + fallback_value +""") + + def test_6(self): + self.compare("""key: value +[Heading 1] + other_key: + if a == "abc"[c]: other_value + fallback_value +""") + + def test_7(self): + self.compare("""key: value +[Heading 1] + other_key: + if (a or b) and c: other_value + fallback_value +""", +"""key: value +[Heading 1] + other_key: + if a or b and c: other_value + fallback_value +""") + + def test_8(self): + self.compare("""key: value +[Heading 1] + other_key: + if a or (b and c): other_value + fallback_value +""") + + def test_9(self): + self.compare("""key: value +[Heading 1] + other_key: + if not (a and b): other_value + fallback_value +""") + + def test_10(self): + self.compare("""key: value +[Heading 1] + some_key: some_value + +[Heading 2] + other_key: other_value +""") + + def test_11(self): + self.compare("""key: + if not a and b and c and d: true +""") + + def test_12(self): + self.compare("""[Heading 1] + key: [a:1, b:2] +""") + + def test_13(self): + self.compare("""key: [a:1, "b:#"] +""") + + def test_14(self): + self.compare("""key: [","] +""") + + def test_15(self): + self.compare("""key: , +""") + + def test_16(self): + self.compare("""key: ["]", b] +""") + + def test_17(self): + self.compare("""key: ] +""") + + def test_18(self): + self.compare("""key: \] + """, """key: ] +""") + + def test_escape_0(self): + self.compare(r"""k\t\:y: \a\b\f\n\r\t\v""", + r"""k\t\:y: \x07\x08\x0c\n\r\t\x0b +""") + + def test_escape_1(self): + self.compare(r"""k\x00: \x12A\x45""", + r"""k\x00: \x12AE +""") + + def test_escape_2(self): + self.compare(r"""k\u0045y: \u1234A\uABc6""", + u"""kEy: \u1234A\uabc6 +""") + + def test_escape_3(self): + self.compare(r"""k\u0045y: \u1234A\uABc6""", + u"""kEy: \u1234A\uabc6 +""") + + def test_escape_4(self): + self.compare(r"""key: '\u1234A\uABc6'""", + u"""key: \u1234A\uabc6 +""") + + def test_escape_5(self): + self.compare(r"""key: [\u1234A\uABc6]""", + u"""key: [\u1234A\uabc6] +""") + + def test_escape_6(self): + self.compare(r"""key: [\u1234A\uABc6\,]""", + u"""key: ["\u1234A\uabc6,"] +""") + + def test_escape_7(self): + self.compare(r"""key: [\,\]\#]""", + r"""key: [",]#"] +""") + + def test_escape_8(self): + self.compare(r"""key: \#""", + r"""key: "#" +""") + + @pytest.mark.xfail(sys.maxunicode == 0xFFFF, reason="narrow unicode") + def test_escape_9(self): + self.compare(r"""key: \U10FFFFabc""", + u"""key: \U0010FFFFabc +""") + + def test_escape_10(self): + self.compare(r"""key: \u10FFab""", + u"""key: \u10FFab +""") + + def test_escape_11(self): + self.compare(r"""key: \\ab +""") + + def test_atom_1(self): + self.compare(r"""key: @True +""") + + def test_atom_2(self): + self.compare(r"""key: @False +""") + + def test_atom_3(self): + self.compare(r"""key: @Reset +""") + + def test_atom_4(self): + self.compare(r"""key: [a, @Reset, b] +""") diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_static.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_static.py new file mode 100644 index 000000000000..ed28578d3bfc --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_static.py @@ -0,0 +1,98 @@ +import unittest + +from cStringIO import StringIO + +from ..backends import static + +# There aren't many tests here because it turns out to be way more convenient to +# use test_serializer for the majority of cases + + +class TestStatic(unittest.TestCase): + def compile(self, input_text, input_data): + return static.compile(input_text, input_data) + + def test_get_0(self): + data = """ +key: value + +[Heading 1] + other_key: + if a == 1: value_1 + if a == 2: value_2 + value_3 +""" + + manifest = self.compile(data, {"a": 2}) + + self.assertEquals(manifest.get("key"), "value") + children = list(item for item in manifest.iterchildren()) + self.assertEquals(len(children), 1) + section = children[0] + self.assertEquals(section.name, "Heading 1") + + self.assertEquals(section.get("other_key"), "value_2") + self.assertEquals(section.get("key"), "value") + + def test_get_1(self): + data = """ +key: value + +[Heading 1] + other_key: + if a == 1: value_1 + if a == 2: value_2 + value_3 +""" + manifest = self.compile(data, {"a": 3}) + + children = list(item for item in manifest.iterchildren()) + section = children[0] + self.assertEquals(section.get("other_key"), "value_3") + + def test_get_3(self): + data = """key: + if a == "1": value_1 + if a[0] == "ab"[0]: value_2 +""" + manifest = self.compile(data, {"a": "1"}) + self.assertEquals(manifest.get("key"), "value_1") + + manifest = self.compile(data, {"a": "ac"}) + self.assertEquals(manifest.get("key"), "value_2") + + def test_get_4(self): + data = """key: + if not a: value_1 + value_2 +""" + manifest = self.compile(data, {"a": True}) + self.assertEquals(manifest.get("key"), "value_2") + + manifest = self.compile(data, {"a": False}) + self.assertEquals(manifest.get("key"), "value_1") + + def test_api(self): + data = """key: + if a == 1.5: value_1 + value_2 +key_1: other_value +""" + manifest = self.compile(data, {"a": 1.5}) + + self.assertFalse(manifest.is_empty) + self.assertEquals(manifest.root, manifest) + self.assertTrue(manifest.has_key("key_1")) + self.assertFalse(manifest.has_key("key_2")) + + self.assertEquals(set(manifest.iterkeys()), set(["key", "key_1"])) + self.assertEquals(set(manifest.itervalues()), set(["value_1", "other_value"])) + + def test_is_empty_1(self): + data = """ +[Section] + [Subsection] +""" + manifest = self.compile(data, {}) + + self.assertTrue(manifest.is_empty) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_tokenizer.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_tokenizer.py new file mode 100644 index 000000000000..88176c5a1690 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/tests/test_tokenizer.py @@ -0,0 +1,357 @@ +import sys +import os +import unittest + +sys.path.insert(0, os.path.abspath("..")) +from cStringIO import StringIO + +from .. import parser +from ..parser import token_types + + +class TokenizerTest(unittest.TestCase): + def setUp(self): + self.tokenizer = parser.Tokenizer() + + def tokenize(self, input_str): + rv = [] + for item in self.tokenizer.tokenize(StringIO(input_str)): + rv.append(item) + if item[0] == token_types.eof: + break + return rv + + def compare(self, input_text, expected): + expected = expected + [(token_types.eof, None)] + actual = self.tokenize(input_text) + self.assertEquals(actual, expected) + + def test_heading_0(self): + self.compare("""[Heading text]""", + [(token_types.paren, "["), + (token_types.string, "Heading text"), + (token_types.paren, "]")]) + + def test_heading_1(self): + self.compare("""[Heading [text\]]""", + [(token_types.paren, "["), + (token_types.string, "Heading [text]"), + (token_types.paren, "]")]) + + def test_heading_2(self): + self.compare("""[Heading #text]""", + [(token_types.paren, "["), + (token_types.string, "Heading #text"), + (token_types.paren, "]")]) + + def test_heading_3(self): + self.compare("""[Heading [\]text]""", + [(token_types.paren, "["), + (token_types.string, "Heading []text"), + (token_types.paren, "]")]) + + def test_heading_4(self): + with self.assertRaises(parser.ParseError): + self.tokenize("[Heading") + + def test_heading_5(self): + self.compare("""[Heading [\]text] #comment""", + [(token_types.paren, "["), + (token_types.string, "Heading []text"), + (token_types.paren, "]")]) + + def test_heading_6(self): + self.compare(r"""[Heading \ttext]""", + [(token_types.paren, "["), + (token_types.string, "Heading \ttext"), + (token_types.paren, "]")]) + + def test_key_0(self): + self.compare("""key:value""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_key_1(self): + self.compare("""key : value""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_key_2(self): + self.compare("""key : val ue""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.string, "val ue")]) + + def test_key_3(self): + self.compare("""key: value#comment""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_key_4(self): + with self.assertRaises(parser.ParseError): + self.tokenize("""ke y: value""") + + def test_key_5(self): + with self.assertRaises(parser.ParseError): + self.tokenize("""key""") + + def test_key_6(self): + self.compare("""key: "value\"""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_key_7(self): + self.compare("""key: 'value'""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_key_8(self): + self.compare("""key: "#value\"""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.string, "#value")]) + + def test_key_9(self): + self.compare("""key: '#value\'""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.string, "#value")]) + + def test_key_10(self): + with self.assertRaises(parser.ParseError): + self.tokenize("""key: "value""") + + def test_key_11(self): + with self.assertRaises(parser.ParseError): + self.tokenize("""key: 'value""") + + def test_key_12(self): + with self.assertRaises(parser.ParseError): + self.tokenize("""key: 'value""") + + def test_key_13(self): + with self.assertRaises(parser.ParseError): + self.tokenize("""key: 'value' abc""") + + def test_key_14(self): + self.compare(r"""key: \\nb""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.string, r"\nb")]) + + def test_list_0(self): + self.compare( +""" +key: []""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.list_start, "["), + (token_types.list_end, "]")]) + + def test_list_1(self): + self.compare( +""" +key: [a, "b"]""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.list_start, "["), + (token_types.string, "a"), + (token_types.string, "b"), + (token_types.list_end, "]")]) + + def test_list_2(self): + self.compare( +""" +key: [a, + b]""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.list_start, "["), + (token_types.string, "a"), + (token_types.string, "b"), + (token_types.list_end, "]")]) + + def test_list_3(self): + self.compare( +""" +key: [a, #b] + c]""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.list_start, "["), + (token_types.string, "a"), + (token_types.string, "c"), + (token_types.list_end, "]")]) + + def test_list_4(self): + with self.assertRaises(parser.ParseError): + self.tokenize("""key: [a #b] + c]""") + + def test_list_5(self): + with self.assertRaises(parser.ParseError): + self.tokenize("""key: [a \\ + c]""") + + def test_list_6(self): + self.compare( +"""key: [a , b]""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.list_start, "["), + (token_types.string, "a"), + (token_types.string, "b"), + (token_types.list_end, "]")]) + + def test_expr_0(self): + self.compare( +""" +key: + if cond == 1: value""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.group_start, None), + (token_types.ident, "if"), + (token_types.ident, "cond"), + (token_types.ident, "=="), + (token_types.number, "1"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_expr_1(self): + self.compare( +""" +key: + if cond == 1: value1 + value2""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.group_start, None), + (token_types.ident, "if"), + (token_types.ident, "cond"), + (token_types.ident, "=="), + (token_types.number, "1"), + (token_types.separator, ":"), + (token_types.string, "value1"), + (token_types.string, "value2")]) + + def test_expr_2(self): + self.compare( +""" +key: + if cond=="1": value""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.group_start, None), + (token_types.ident, "if"), + (token_types.ident, "cond"), + (token_types.ident, "=="), + (token_types.string, "1"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_expr_3(self): + self.compare( +""" +key: + if cond==1.1: value""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.group_start, None), + (token_types.ident, "if"), + (token_types.ident, "cond"), + (token_types.ident, "=="), + (token_types.number, "1.1"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_expr_4(self): + self.compare( + """ +key: + if cond==1.1 and cond2 == "a": value""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.group_start, None), + (token_types.ident, "if"), + (token_types.ident, "cond"), + (token_types.ident, "=="), + (token_types.number, "1.1"), + (token_types.ident, "and"), + (token_types.ident, "cond2"), + (token_types.ident, "=="), + (token_types.string, "a"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_expr_5(self): + self.compare( +""" +key: + if (cond==1.1 ): value""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.group_start, None), + (token_types.ident, "if"), + (token_types.paren, "("), + (token_types.ident, "cond"), + (token_types.ident, "=="), + (token_types.number, "1.1"), + (token_types.paren, ")"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_expr_6(self): + self.compare( +""" +key: + if "\\ttest": value""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.group_start, None), + (token_types.ident, "if"), + (token_types.string, "\ttest"), + (token_types.separator, ":"), + (token_types.string, "value")]) + + def test_expr_7(self): + with self.assertRaises(parser.ParseError): + self.tokenize( +""" +key: + if 1A: value""") + + def test_expr_8(self): + with self.assertRaises(parser.ParseError): + self.tokenize( +""" +key: + if 1a: value""") + + def test_expr_9(self): + with self.assertRaises(parser.ParseError): + self.tokenize( +""" +key: + if 1.1.1: value""") + + def test_expr_10(self): + self.compare( +""" +key: + if 1.: value""", + [(token_types.string, "key"), + (token_types.separator, ":"), + (token_types.group_start, None), + (token_types.ident, "if"), + (token_types.number, "1."), + (token_types.separator, ":"), + (token_types.string, "value")]) + +if __name__ == "__main__": + unittest.main() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptrunner.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptrunner.py new file mode 100644 index 000000000000..5c184554f0d9 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptrunner.py @@ -0,0 +1,257 @@ +from __future__ import unicode_literals + +import json +import os +import sys + +import environment as env +import products +import testloader +import wptcommandline +import wptlogging +import wpttest +from testrunner import ManagerGroup +from browsers.base import NullBrowser + +here = os.path.split(__file__)[0] + +logger = None + +"""Runner for web-platform-tests + +The runner has several design goals: + +* Tests should run with no modification from upstream. + +* Tests should be regarded as "untrusted" so that errors, timeouts and even + crashes in the tests can be handled without failing the entire test run. + +* For performance tests can be run in multiple browsers in parallel. + +The upstream repository has the facility for creating a test manifest in JSON +format. This manifest is used directly to determine which tests exist. Local +metadata files are used to store the expected test results. +""" + +def setup_logging(*args, **kwargs): + global logger + logger = wptlogging.setup(*args, **kwargs) + +def get_loader(test_paths, product, ssl_env, debug=None, run_info_extras=None, **kwargs): + if run_info_extras is None: + run_info_extras = {} + + run_info = wpttest.get_run_info(kwargs["run_info"], product, debug=debug, + extras=run_info_extras) + + test_manifests = testloader.ManifestLoader(test_paths, force_manifest_update=kwargs["manifest_update"]).load() + + manifest_filters = [] + meta_filters = [] + + if kwargs["include"] or kwargs["exclude"] or kwargs["include_manifest"]: + manifest_filters.append(testloader.TestFilter(include=kwargs["include"], + exclude=kwargs["exclude"], + manifest_path=kwargs["include_manifest"], + test_manifests=test_manifests)) + if kwargs["tags"]: + meta_filters.append(testloader.TagFilter(tags=kwargs["tags"])) + + test_loader = testloader.TestLoader(test_manifests, + kwargs["test_types"], + run_info, + manifest_filters=manifest_filters, + meta_filters=meta_filters, + chunk_type=kwargs["chunk_type"], + total_chunks=kwargs["total_chunks"], + chunk_number=kwargs["this_chunk"], + include_https=ssl_env.ssl_enabled) + return run_info, test_loader + +def list_test_groups(test_paths, product, **kwargs): + env.do_delayed_imports(logger, test_paths) + + ssl_env = env.ssl_env(logger, **kwargs) + + run_info, test_loader = get_loader(test_paths, product, ssl_env, + **kwargs) + + for item in sorted(test_loader.groups(kwargs["test_types"])): + print item + + +def list_disabled(test_paths, product, **kwargs): + env.do_delayed_imports(logger, test_paths) + + rv = [] + + ssl_env = env.ssl_env(logger, **kwargs) + + run_info, test_loader = get_loader(test_paths, product, ssl_env, + **kwargs) + + for test_type, tests in test_loader.disabled_tests.iteritems(): + for test in tests: + rv.append({"test": test.id, "reason": test.disabled()}) + print json.dumps(rv, indent=2) + + +def get_pause_after_test(test_loader, **kwargs): + total_tests = sum(len(item) for item in test_loader.tests.itervalues()) + if kwargs["pause_after_test"] is None: + if kwargs["repeat_until_unexpected"]: + return False + if kwargs["repeat"] == 1 and total_tests == 1: + return True + return False + return kwargs["pause_after_test"] + + +def run_tests(config, test_paths, product, **kwargs): + with wptlogging.CaptureIO(logger, not kwargs["no_capture_stdio"]): + env.do_delayed_imports(logger, test_paths) + + (check_args, + target_browser_cls, get_browser_kwargs, + executor_classes, get_executor_kwargs, + env_options, get_env_extras, run_info_extras) = products.load_product(config, product) + + ssl_env = env.ssl_env(logger, **kwargs) + env_extras = get_env_extras(**kwargs) + + check_args(**kwargs) + + if "test_loader" in kwargs: + run_info = wpttest.get_run_info(kwargs["run_info"], product, debug=None, + extras=run_info_extras(**kwargs)) + test_loader = kwargs["test_loader"] + else: + run_info, test_loader = get_loader(test_paths, + product, + ssl_env, + run_info_extras=run_info_extras(**kwargs), + **kwargs) + + if kwargs["run_by_dir"] is False: + test_source_cls = testloader.SingleTestSource + test_source_kwargs = {} + else: + # A value of None indicates infinite depth + test_source_cls = testloader.PathGroupedSource + test_source_kwargs = {"depth": kwargs["run_by_dir"]} + + logger.info("Using %i client processes" % kwargs["processes"]) + + unexpected_total = 0 + + kwargs["pause_after_test"] = get_pause_after_test(test_loader, **kwargs) + + with env.TestEnvironment(test_paths, + ssl_env, + kwargs["pause_after_test"], + kwargs["debug_info"], + env_options, + env_extras) as test_environment: + try: + test_environment.ensure_started() + except env.TestEnvironmentError as e: + logger.critical("Error starting test environment: %s" % e.message) + raise + + browser_kwargs = get_browser_kwargs(ssl_env=ssl_env, **kwargs) + + repeat = kwargs["repeat"] + repeat_count = 0 + repeat_until_unexpected = kwargs["repeat_until_unexpected"] + + while repeat_count < repeat or repeat_until_unexpected: + repeat_count += 1 + if repeat_until_unexpected: + logger.info("Repetition %i" % (repeat_count)) + elif repeat > 1: + logger.info("Repetition %i / %i" % (repeat_count, repeat)) + + unexpected_count = 0 + logger.suite_start(test_loader.test_ids, run_info) + for test_type in kwargs["test_types"]: + logger.info("Running %s tests" % test_type) + + # WebDriver tests may create and destroy multiple browser + # processes as part of their expected behavior. These + # processes are managed by a WebDriver server binary. This + # obviates the need for wptrunner to provide a browser, so + # the NullBrowser is used in place of the "target" browser + if test_type == "wdspec": + browser_cls = NullBrowser + else: + browser_cls = target_browser_cls + + for test in test_loader.disabled_tests[test_type]: + logger.test_start(test.id) + logger.test_end(test.id, status="SKIP") + + executor_cls = executor_classes.get(test_type) + executor_kwargs = get_executor_kwargs(test_type, + test_environment.external_config, + test_environment.cache_manager, + run_info, + **kwargs) + + if executor_cls is None: + logger.error("Unsupported test type %s for product %s" % + (test_type, product)) + continue + + + with ManagerGroup("web-platform-tests", + kwargs["processes"], + test_source_cls, + test_source_kwargs, + browser_cls, + browser_kwargs, + executor_cls, + executor_kwargs, + kwargs["pause_after_test"], + kwargs["pause_on_unexpected"], + kwargs["restart_on_unexpected"], + kwargs["debug_info"]) as manager_group: + try: + manager_group.run(test_type, test_loader.tests) + except KeyboardInterrupt: + logger.critical("Main thread got signal") + manager_group.stop() + raise + unexpected_count += manager_group.unexpected_count() + + unexpected_total += unexpected_count + logger.info("Got %i unexpected results" % unexpected_count) + if repeat_until_unexpected and unexpected_total > 0: + break + logger.suite_end() + + return unexpected_total == 0 + + +def main(): + """Main entry point when calling from the command line""" + kwargs = wptcommandline.parse_args() + + try: + if kwargs["prefs_root"] is None: + kwargs["prefs_root"] = os.path.abspath(os.path.join(here, "prefs")) + + setup_logging(kwargs, {"raw": sys.stdout}) + + if kwargs["list_test_groups"]: + list_test_groups(**kwargs) + elif kwargs["list_disabled"]: + list_disabled(**kwargs) + else: + return not run_tests(**kwargs) + except Exception: + if kwargs["pdb"]: + import pdb, traceback + print traceback.format_exc() + pdb.post_mortem() + else: + raise diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wpttest.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wpttest.py new file mode 100644 index 000000000000..d144cd66ea78 --- /dev/null +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wpttest.py @@ -0,0 +1,338 @@ +DEFAULT_TIMEOUT = 10 # seconds +LONG_TIMEOUT = 60 # seconds + +import os + +import mozinfo + +from wptmanifest.parser import atoms + +atom_reset = atoms["Reset"] +enabled_tests = set(["testharness", "reftest", "wdspec"]) + + +class Result(object): + def __init__(self, status, message, expected=None, extra=None): + if status not in self.statuses: + raise ValueError("Unrecognised status %s" % status) + self.status = status + self.message = message + self.expected = expected + self.extra = extra + + def __repr__(self): + return "<%s.%s %s>" % (self.__module__, self.__class__.__name__, self.status) + + +class SubtestResult(object): + def __init__(self, name, status, message, stack=None, expected=None): + self.name = name + if status not in self.statuses: + raise ValueError("Unrecognised status %s" % status) + self.status = status + self.message = message + self.stack = stack + self.expected = expected + + def __repr__(self): + return "<%s.%s %s %s>" % (self.__module__, self.__class__.__name__, self.name, self.status) + + +class TestharnessResult(Result): + default_expected = "OK" + statuses = set(["OK", "ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH"]) + + +class TestharnessSubtestResult(SubtestResult): + default_expected = "PASS" + statuses = set(["PASS", "FAIL", "TIMEOUT", "NOTRUN"]) + + +class ReftestResult(Result): + default_expected = "PASS" + statuses = set(["PASS", "FAIL", "ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH"]) + + +class WdspecResult(Result): + default_expected = "OK" + statuses = set(["OK", "ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH"]) + + +class WdspecSubtestResult(SubtestResult): + default_expected = "PASS" + statuses = set(["PASS", "FAIL", "ERROR"]) + + +def get_run_info(metadata_root, product, **kwargs): + return RunInfo(metadata_root, product, **kwargs) + + +class RunInfo(dict): + def __init__(self, metadata_root, product, debug, extras=None): + self._update_mozinfo(metadata_root) + self.update(mozinfo.info) + self["product"] = product + if debug is not None: + self["debug"] = debug + elif "debug" not in self: + # Default to release + self["debug"] = False + if extras is not None: + self.update(extras) + + def _update_mozinfo(self, metadata_root): + """Add extra build information from a mozinfo.json file in a parent + directory""" + path = metadata_root + dirs = set() + while path != os.path.expanduser('~'): + if path in dirs: + break + dirs.add(str(path)) + path = os.path.split(path)[0] + + mozinfo.find_and_update_from_json(*dirs) + + +class Test(object): + result_cls = None + subtest_result_cls = None + test_type = None + + def __init__(self, tests_root, url, inherit_metadata, test_metadata, + timeout=DEFAULT_TIMEOUT, path=None, protocol="http"): + self.tests_root = tests_root + self.url = url + self._inherit_metadata = inherit_metadata + self._test_metadata = test_metadata + self.timeout = timeout + self.path = path + self.environment = {"protocol": protocol, "prefs": self.prefs} + + def __eq__(self, other): + return self.id == other.id + + @classmethod + def from_manifest(cls, manifest_item, inherit_metadata, test_metadata): + timeout = LONG_TIMEOUT if manifest_item.timeout == "long" else DEFAULT_TIMEOUT + protocol = "https" if hasattr(manifest_item, "https") and manifest_item.https else "http" + return cls(manifest_item.source_file.tests_root, + manifest_item.url, + inherit_metadata, + test_metadata, + timeout=timeout, + path=manifest_item.source_file.path, + protocol=protocol) + + @property + def id(self): + return self.url + + @property + def keys(self): + return tuple() + + @property + def abs_path(self): + return os.path.join(self.tests_root, self.path) + + def _get_metadata(self, subtest=None): + if self._test_metadata is not None and subtest is not None: + return self._test_metadata.get_subtest(subtest) + else: + return self._test_metadata + + def itermeta(self, subtest=None): + for metadata in self._inherit_metadata: + yield metadata + + if self._test_metadata is not None: + yield self._get_metadata() + if subtest is not None: + subtest_meta = self._get_metadata(subtest) + if subtest_meta is not None: + yield subtest_meta + + def disabled(self, subtest=None): + for meta in self.itermeta(subtest): + disabled = meta.disabled + if disabled is not None: + return disabled + return None + + @property + def restart_after(self): + for meta in self.itermeta(None): + restart_after = meta.restart_after + if restart_after is not None: + return True + return False + + @property + def tags(self): + tags = set() + for meta in self.itermeta(): + meta_tags = meta.tags + if atom_reset in meta_tags: + tags = meta_tags.copy() + tags.remove(atom_reset) + else: + tags |= meta_tags + + tags.add("dir:%s" % self.id.lstrip("/").split("/")[0]) + + return tags + + @property + def prefs(self): + prefs = {} + for meta in self.itermeta(): + meta_prefs = meta.prefs + if atom_reset in prefs: + prefs = meta_prefs.copy() + del prefs[atom_reset] + else: + prefs.update(meta_prefs) + return prefs + + def expected(self, subtest=None): + if subtest is None: + default = self.result_cls.default_expected + else: + default = self.subtest_result_cls.default_expected + + metadata = self._get_metadata(subtest) + if metadata is None: + return default + + try: + return metadata.get("expected") + except KeyError: + return default + + def __repr__(self): + return "<%s.%s %s>" % (self.__module__, self.__class__.__name__, self.id) + + +class TestharnessTest(Test): + result_cls = TestharnessResult + subtest_result_cls = TestharnessSubtestResult + test_type = "testharness" + + @property + def id(self): + return self.url + + +class ManualTest(Test): + test_type = "manual" + + @property + def id(self): + return self.url + + +class ReftestTest(Test): + result_cls = ReftestResult + test_type = "reftest" + + def __init__(self, tests_root, url, inherit_metadata, test_metadata, references, + timeout=DEFAULT_TIMEOUT, path=None, viewport_size=None, + dpi=None, protocol="http"): + Test.__init__(self, tests_root, url, inherit_metadata, test_metadata, timeout, + path, protocol) + + for _, ref_type in references: + if ref_type not in ("==", "!="): + raise ValueError + + self.references = references + self.viewport_size = viewport_size + self.dpi = dpi + + @classmethod + def from_manifest(cls, + manifest_test, + inherit_metadata, + test_metadata, + nodes=None, + references_seen=None): + + timeout = LONG_TIMEOUT if manifest_test.timeout == "long" else DEFAULT_TIMEOUT + + if nodes is None: + nodes = {} + if references_seen is None: + references_seen = set() + + url = manifest_test.url + + node = cls(manifest_test.source_file.tests_root, + manifest_test.url, + inherit_metadata, + test_metadata, + [], + timeout=timeout, + path=manifest_test.path, + viewport_size=manifest_test.viewport_size, + dpi=manifest_test.dpi, + protocol="https" if hasattr(manifest_test, "https") and manifest_test.https else "http") + + nodes[url] = node + + for ref_url, ref_type in manifest_test.references: + comparison_key = (ref_type,) + tuple(sorted([url, ref_url])) + if ref_url in nodes: + manifest_node = ref_url + if comparison_key in references_seen: + # We have reached a cycle so stop here + # Note that just seeing a node for the second time is not + # enough to detect a cycle because + # A != B != C != A must include C != A + # but A == B == A should not include the redundant B == A. + continue + + references_seen.add(comparison_key) + + manifest_node = manifest_test.manifest.get_reference(ref_url) + if manifest_node: + reference = ReftestTest.from_manifest(manifest_node, + [], + None, + nodes, + references_seen) + else: + reference = ReftestTest(manifest_test.source_file.tests_root, + ref_url, + [], + None, + []) + + node.references.append((reference, ref_type)) + + return node + + @property + def id(self): + return self.url + + @property + def keys(self): + return ("reftype", "refurl") + + +class WdspecTest(Test): + result_cls = WdspecResult + subtest_result_cls = WdspecSubtestResult + test_type = "wdspec" + + +manifest_test_cls = {"reftest": ReftestTest, + "testharness": TestharnessTest, + "manual": ManualTest, + "wdspec": WdspecTest} + + +def from_manifest(manifest_test, inherit_metadata, test_metadata): + test_cls = manifest_test_cls[manifest_test.item_type] + return test_cls.from_manifest(manifest_test, inherit_metadata, test_metadata) diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/base.py b/testing/web-platform/tests/tools/wptserve/tests/functional/base.py index 62d5e3253e6b..9b0cb50179fe 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/base.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/base.py @@ -3,13 +3,14 @@ from __future__ import print_function import base64 import logging import os +import pytest import unittest from six.moves.urllib.parse import urlencode, urlunsplit from six.moves.urllib.request import Request as BaseRequest from six.moves.urllib.request import urlopen -import wptserve +wptserve = pytest.importorskip("wptserve") logging.basicConfig() @@ -18,6 +19,7 @@ wptserve.logger.set_logger(logging.getLogger()) here = os.path.split(__file__)[0] doc_root = os.path.join(here, "docroot") + class Request(BaseRequest): def __init__(self, *args, **kwargs): BaseRequest.__init__(self, *args, **kwargs) @@ -33,6 +35,7 @@ class Request(BaseRequest): self.add_header("Content-Length", str(len(data))) BaseRequest.add_data(self, data) + class TestUsingServer(unittest.TestCase): def setUp(self): self.server = wptserve.server.WebTestHttpd(host="localhost", diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_cookies.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_cookies.py index d1080b4bf15c..2e2d0d6771ba 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_cookies.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_cookies.py @@ -1,8 +1,11 @@ import unittest -import wptserve +import pytest + +wptserve = pytest.importorskip("wptserve") from .base import TestUsingServer + class TestResponseSetCookie(TestUsingServer): def test_name_value(self): @wptserve.handlers.handler diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_handlers.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_handlers.py index f99597a43f0a..67119d2cfbd6 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_handlers.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_handlers.py @@ -1,14 +1,15 @@ import json import os -import pytest import unittest import uuid +import pytest from six.moves.urllib.error import HTTPError -import wptserve +wptserve = pytest.importorskip("wptserve") from .base import TestUsingServer, doc_root + class TestFileHandler(TestUsingServer): def test_GET(self): resp = self.request("/document.txt") diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_pipes.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_pipes.py index af5068108c81..95da70faea9f 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_pipes.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_pipes.py @@ -2,8 +2,11 @@ import os import unittest import time +import pytest + from .base import TestUsingServer, doc_root + class TestStatus(TestUsingServer): def test_status(self): resp = self.request("/document.txt", query="pipe=status(202)") diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_request.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_request.py index 40dfe7703d14..d0d8213cfdd0 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_request.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_request.py @@ -1,8 +1,11 @@ import unittest -import wptserve +import pytest + +wptserve = pytest.importorskip("wptserve") from .base import TestUsingServer + class TestInputFile(TestUsingServer): def test_seek(self): @wptserve.handlers.handler diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_response.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_response.py index e9808b54ef19..d60127560f69 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_response.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_response.py @@ -1,9 +1,12 @@ import unittest from types import MethodType -import wptserve +import pytest + +wptserve = pytest.importorskip("wptserve") from .base import TestUsingServer + def send_body_as_header(self): if self._response.add_required_headers: self.write_default_headers() diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_server.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_server.py index 2646beda374f..26c34c31002c 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_server.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_server.py @@ -1,10 +1,12 @@ import unittest +import pytest from six.moves.urllib.error import HTTPError -import wptserve +wptserve = pytest.importorskip("wptserve") from .base import TestUsingServer + class TestFileHandler(TestUsingServer): def test_not_handled(self): with self.assertRaises(HTTPError) as cm: diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_stash.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_stash.py index 134293d3468a..97591cbb0078 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_stash.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_stash.py @@ -1,11 +1,14 @@ import unittest import uuid -import wptserve +import pytest + +wptserve = pytest.importorskip("wptserve") from wptserve.router import any_method from wptserve.stash import StashServer from .base import TestUsingServer + class TestResponseSetCookie(TestUsingServer): def run(self, result=None): with StashServer(None, authkey=str(uuid.uuid4())): diff --git a/testing/web-platform/tests/tools/wptserve/tox.ini b/testing/web-platform/tests/tools/wptserve/tox.ini deleted file mode 100644 index 0026f56e957d..000000000000 --- a/testing/web-platform/tests/tools/wptserve/tox.ini +++ /dev/null @@ -1,18 +0,0 @@ -[tox] -envlist = py27,pypy - -[testenv] -deps = - coverage - flake8 - pytest - six - -commands = - coverage run -m pytest tests/functional - flake8 - -[flake8] -ignore = E128,E129,E221,E226,E231,E251,E265,E302,E303,E305,E402,E901,F821,F841 -max-line-length = 141 -exclude=docs,.git,__pycache__,.tox,.eggs,*.egg,tests/functional/docroot/ diff --git a/testing/web-platform/tests/auxclick/auxclick_event-manual.html b/testing/web-platform/tests/uievents/auxclick/auxclick_event-manual.html similarity index 100% rename from testing/web-platform/tests/auxclick/auxclick_event-manual.html rename to testing/web-platform/tests/uievents/auxclick/auxclick_event-manual.html diff --git a/testing/web-platform/tests/uievents/constructors/inputevent-constructor.html b/testing/web-platform/tests/uievents/constructors/inputevent-constructor.html index 9ade36d6a3d9..f1f5641785eb 100644 --- a/testing/web-platform/tests/uievents/constructors/inputevent-constructor.html +++ b/testing/web-platform/tests/uievents/constructors/inputevent-constructor.html @@ -22,14 +22,4 @@ test(function() { test(function() { assert_equals(new InputEvent('type', { data: 'data' }).data, 'data'); }, 'InputEvent construtor with InputEventInit where data is non empty string'); - -test(function() { - const range = new StaticRange(); - range.setEnd(document, 1); - const resultRange = new InputEvent('type', { targetRanges: [range] }).getTargetRanges()[0]; - assert_equals(resultRange.startContainer, document); - assert_equals(resultRange.startOffset, 0); - assert_equals(resultRange.endContainer, document); - assert_equals(resultRange.endOffset, 1); -}, 'InputEvent construtor with InputEventInit where targetRanges is non empty list'); diff --git a/testing/web-platform/tests/uievents/mouse/mouseevent_move_button-manual.html b/testing/web-platform/tests/uievents/mouse/mouseevent_move_button-manual.html new file mode 100644 index 000000000000..ff5eaba6983b --- /dev/null +++ b/testing/web-platform/tests/uievents/mouse/mouseevent_move_button-manual.html @@ -0,0 +1,85 @@ + + + + Mouse Events with button depressed + + + + + + +

Mouse Events

+

Test Description: This test checks if mouse events set button property correctly +
    +
  1. Put your mouse over the green rectangle
  2. +
  3. Press a non-primary button and hold it
  4. +
  5. Drag mouse to blue rectangle
  6. +
  7. Release mouse button
  8. +
+

+
+
+
+
+ + + diff --git a/testing/web-platform/tests/url/README.md b/testing/web-platform/tests/url/README.md index 77965cc43df3..4cb3c00d61c4 100644 --- a/testing/web-platform/tests/url/README.md +++ b/testing/web-platform/tests/url/README.md @@ -21,15 +21,3 @@ The keys for each test case are: [parsing]: https://url.spec.whatwg.org/#concept-basic-url-parser [API]: https://url.spec.whatwg.org/#api - -[`annevk/url`](https://github.com/annevk/url) hosts some other files that might be of -interest if you want to create additional tests. - -Similar to `a-element.html` it would be trivial to add more tests for other objects that -expose links (e.g. URL and ``). There's also room for enhancement and bits that -require independent tests: - -* The encoding part of the URL parser -* The state override part of the URL parser (setting individual properties of a URL) -* Origin serialization -* `application/x-www-form-urlencoded` diff --git a/testing/web-platform/tests/url/failure.html b/testing/web-platform/tests/url/failure.html index 7ffb3cbe28c7..d097d4e35100 100644 --- a/testing/web-platform/tests/url/failure.html +++ b/testing/web-platform/tests/url/failure.html @@ -33,6 +33,10 @@ function runTests(testData) { self.test(() => { assert_throws(new TypeError, () => self[0].location = test.input) }, "Location's href: " + name) + + self.test(() => { + assert_throws("SyntaxError", () => self.open(test.input).close()) + }, "window.open(): " + name) } } diff --git a/testing/web-platform/tests/url/historical.worker.js b/testing/web-platform/tests/url/historical.any.js similarity index 74% rename from testing/web-platform/tests/url/historical.worker.js rename to testing/web-platform/tests/url/historical.any.js index ccee73d2ec47..c3797ad26385 100644 --- a/testing/web-platform/tests/url/historical.worker.js +++ b/testing/web-platform/tests/url/historical.any.js @@ -1,10 +1,15 @@ -importScripts("/resources/testharness.js"); - test(function() { assert_false("searchParams" in self.location, "location object should not have a searchParams attribute"); }, "searchParams on location object"); +if(self.GLOBAL.isWindow()) { + test(() => { + assert_false("searchParams" in document.createElement("a")) + assert_false("searchParams" in document.createElement("area")) + }, " and .searchParams should be undefined"); +} + test(function() { var url = new URL("./foo", "http://www.example.org"); assert_equals(url.href, "http://www.example.org/foo"); diff --git a/testing/web-platform/tests/url/historical.html b/testing/web-platform/tests/url/historical.html deleted file mode 100644 index fe35b0622500..000000000000 --- a/testing/web-platform/tests/url/historical.html +++ /dev/null @@ -1,37 +0,0 @@ - - -URL historical tests - - -
- diff --git a/testing/web-platform/tests/url/urlsearchparams-constructor.html b/testing/web-platform/tests/url/urlsearchparams-constructor.html index a27b319e0261..1e214e042669 100644 --- a/testing/web-platform/tests/url/urlsearchparams-constructor.html +++ b/testing/web-platform/tests/url/urlsearchparams-constructor.html @@ -79,6 +79,17 @@ test(function() { assert_equals(params.get('a b'), 'c'); }, 'Parse +'); +test(function() { + const testValue = '+15555555555'; + const params = new URLSearchParams(); + params.set('query', testValue); + var newParams = new URLSearchParams(params.toString()); + + assert_equals(params.toString(), 'query=%2B15555555555'); + assert_equals(params.get('query'), testValue); + assert_equals(newParams.get('query'), testValue); +}, 'Parse encoded +'); + test(function() { var params = new URLSearchParams('a=b c'); assert_equals(params.get('a'), 'b c'); diff --git a/testing/web-platform/tests/url/urltestdata.json b/testing/web-platform/tests/url/urltestdata.json index 47e86181617a..fe13d3f1edfc 100644 --- a/testing/web-platform/tests/url/urltestdata.json +++ b/testing/web-platform/tests/url/urltestdata.json @@ -3782,6 +3782,52 @@ "search": "", "hash": "" }, + "Domains with empty labels", + { + "input": "http://./", + "base": "about:blank", + "href": "http://./", + "origin": "http://.", + "protocol": "http:", + "username": "", + "password": "", + "host": ".", + "hostname": ".", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "http://../", + "base": "about:blank", + "href": "http://../", + "origin": "http://..", + "protocol": "http:", + "username": "", + "password": "", + "host": "..", + "hostname": "..", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "http://0..0x300/", + "base": "about:blank", + "href": "http://0..0x300/", + "origin": "http://0..0x300", + "protocol": "http:", + "username": "", + "password": "", + "host": "0..0x300", + "hostname": "0..0x300", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, "Broken IPv6", { "input": "http://[www.google.com]/", @@ -5377,6 +5423,105 @@ "search": "?chai", "hash": "" }, + "# Windows drive letter handling with the 'file:' base URL", + { + "input": "C|", + "base": "file://host/dir/file", + "href": "file:///C:", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/C:", + "search": "", + "hash": "" + }, + { + "input": "C|#", + "base": "file://host/dir/file", + "href": "file:///C:#", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/C:", + "search": "", + "hash": "" + }, + { + "input": "C|?", + "base": "file://host/dir/file", + "href": "file:///C:?", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/C:", + "search": "", + "hash": "" + }, + { + "input": "C|/", + "base": "file://host/dir/file", + "href": "file:///C:/", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/C:/", + "search": "", + "hash": "" + }, + { + "input": "C|\\", + "base": "file://host/dir/file", + "href": "file:///C:/", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/C:/", + "search": "", + "hash": "" + }, + { + "input": "C", + "base": "file://host/dir/file", + "href": "file://host/dir/C", + "protocol": "file:", + "username": "", + "password": "", + "host": "host", + "hostname": "host", + "port": "", + "pathname": "/dir/C", + "search": "", + "hash": "" + }, + { + "input": "C|a", + "base": "file://host/dir/file", + "href": "file://host/dir/C|a", + "protocol": "file:", + "username": "", + "password": "", + "host": "host", + "hostname": "host", + "port": "", + "pathname": "/dir/C|a", + "search": "", + "hash": "" + }, "# Windows drive letter quirk with not empty host", { "input": "file://example.net/C:/", diff --git a/testing/web-platform/tests/user-timing/measure.html b/testing/web-platform/tests/user-timing/measure.html index 4356c0abb20c..4175dbb49daf 100644 --- a/testing/web-platform/tests/user-timing/measure.html +++ b/testing/web-platform/tests/user-timing/measure.html @@ -8,6 +8,7 @@ + + + + + + + +

This test examines the ARIA properties for alertdialog modal false.

+

Modal Dialog Box Test

+
+ You have an error. + +
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/alertdialog_modal_true-manual.html b/testing/web-platform/tests/wai-aria/alertdialog_modal_true-manual.html new file mode 100644 index 000000000000..f550a99d8ba4 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/alertdialog_modal_true-manual.html @@ -0,0 +1,151 @@ + + + + alertdialog modal true + + + + + + + + +

This test examines the ARIA properties for alertdialog modal true.

+

Modal Dialog Box Test

+
+ You have an error. + +
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/application_activedescendant-manual.html b/testing/web-platform/tests/wai-aria/application_activedescendant-manual.html new file mode 100644 index 000000000000..c613bf6374a1 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/application_activedescendant-manual.html @@ -0,0 +1,237 @@ + + + + application activedescendant + + + + + + + + +

This test examines the ARIA properties for application activedescendant.

+
+
Hello world
+
+ then role:application, aria-activedescendant: bob + +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/application_activedescendant_value_changes-manual.html b/testing/web-platform/tests/wai-aria/application_activedescendant_value_changes-manual.html new file mode 100644 index 000000000000..7afa8db84f09 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/application_activedescendant_value_changes-manual.html @@ -0,0 +1,294 @@ + + + + application activedescendant value changes + + + + + + + + +

This test examines the ARIA properties for application activedescendant value changes.

+
+
Hello world
+
+ then role:application, aria-activedescendant: bob generates a state change event + +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-current_not_declared-manual.html b/testing/web-platform/tests/wai-aria/aria-current_not_declared-manual.html new file mode 100644 index 000000000000..b48180ef1022 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-current_not_declared-manual.html @@ -0,0 +1,131 @@ + + + + aria-current not declared + + + + + + + + +

This test examines the ARIA properties for aria-current not declared.

+
    +
  • 2
  • +
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-current_with_value_changes-manual.html b/testing/web-platform/tests/wai-aria/aria-current_with_value_changes-manual.html new file mode 100644 index 000000000000..d17139a14c77 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-current_with_value_changes-manual.html @@ -0,0 +1,125 @@ + + + + aria-current with value changes + + + + + + + + +

This test examines the ARIA properties for aria-current with value changes.

+
    +
  • 1
  • +
  • 2
  • +
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-current_with_value_date-manual.html b/testing/web-platform/tests/wai-aria/aria-current_with_value_date-manual.html new file mode 100644 index 000000000000..d6c3f5689705 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-current_with_value_date-manual.html @@ -0,0 +1,133 @@ + + + + aria-current with value date + + + + + + + + +

This test examines the ARIA properties for aria-current with value date.

+ + + + +
1
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-current_with_value_location-manual.html b/testing/web-platform/tests/wai-aria/aria-current_with_value_location-manual.html new file mode 100644 index 000000000000..ca9f962f2437 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-current_with_value_location-manual.html @@ -0,0 +1,129 @@ + + + + aria-current with value location + + + + + + + + +

This test examines the ARIA properties for aria-current with value location.

+ + +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-current_with_value_page-manual.html b/testing/web-platform/tests/wai-aria/aria-current_with_value_page-manual.html new file mode 100644 index 000000000000..d8bb3e086252 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-current_with_value_page-manual.html @@ -0,0 +1,129 @@ + + + + aria-current with value page + + + + + + + + +

This test examines the ARIA properties for aria-current with value page.

+
1
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-current_with_value_step-manual.html b/testing/web-platform/tests/wai-aria/aria-current_with_value_step-manual.html new file mode 100644 index 000000000000..57b4c300b94f --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-current_with_value_step-manual.html @@ -0,0 +1,129 @@ + + + + aria-current with value step + + + + + + + + +

This test examines the ARIA properties for aria-current with value step.

+
1
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-current_with_value_time-manual.html b/testing/web-platform/tests/wai-aria/aria-current_with_value_time-manual.html new file mode 100644 index 000000000000..b3bab4d44699 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-current_with_value_time-manual.html @@ -0,0 +1,133 @@ + + + + aria-current with value time + + + + + + + + +

This test examines the ARIA properties for aria-current with value time.

+ + + + +
1
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-current_with_value_true-manual.html b/testing/web-platform/tests/wai-aria/aria-current_with_value_true-manual.html new file mode 100644 index 000000000000..e299ffe2dac9 --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-current_with_value_true-manual.html @@ -0,0 +1,131 @@ + + + + aria-current with value true + + + + + + + + +

This test examines the ARIA properties for aria-current with value true.

+
    +
  • 1
  • +
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-current_with_value_unspecified-manual.html b/testing/web-platform/tests/wai-aria/aria-current_with_value_unspecified-manual.html new file mode 100644 index 000000000000..5ad291fe245f --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-current_with_value_unspecified-manual.html @@ -0,0 +1,125 @@ + + + + aria-current with value unspecified + + + + + + + + +

This test examines the ARIA properties for aria-current with value unspecified.

+
    +
  • 1
  • +
+ +
+
+
+ + + diff --git a/testing/web-platform/tests/wai-aria/aria-details_pointing_to_details_element-manual.html b/testing/web-platform/tests/wai-aria/aria-details_pointing_to_details_element-manual.html new file mode 100644 index 000000000000..66ccd7d1c28d --- /dev/null +++ b/testing/web-platform/tests/wai-aria/aria-details_pointing_to_details_element-manual.html @@ -0,0 +1,128 @@ + + + + aria-details pointing to details element + + + + + + + + +

This test examines the ARIA properties for aria-details pointing to details element.

+ +
+ More information at W3.org + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html new file mode 100644 index 000000000000..5aa7de2bb878 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html @@ -0,0 +1,62 @@ + + +Canceling an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/finishing-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/finishing-an-animation.html new file mode 100644 index 000000000000..4890bd1bde8c --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/finishing-an-animation.html @@ -0,0 +1,31 @@ + + +Finishing an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html new file mode 100644 index 000000000000..9a4da2e7c2f0 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html @@ -0,0 +1,27 @@ + + +Pausing an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html index 185e206e01a6..1cf109deb154 100644 --- a/testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html +++ b/testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html @@ -36,5 +36,24 @@ test(function(t) { assert_times_equal(animation.currentTime, 100 * MS_PER_SEC); }, 'Playing a finished and reversed animation seeks to end'); +test(function(t) { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); + animation.cancel(); + const promise = animation.ready; + animation.play(); + assert_not_equals(animation.ready, promise); +}, 'The ready promise should be replaced if the animation is not already' + + ' pending'); + +promise_test(function(t) { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); + const promise = animation.ready; + return promise.then(p => { + assert_equals(p, animation); + assert_equals(animation.ready, promise); + }); +}, 'A pending ready promise should be resolved and not replaced when the' + + ' animation enters the running state'); + diff --git a/testing/web-platform/tests/web-nfc/OWNERS b/testing/web-platform/tests/web-nfc/OWNERS new file mode 100644 index 000000000000..84e375b2e71b --- /dev/null +++ b/testing/web-platform/tests/web-nfc/OWNERS @@ -0,0 +1 @@ +@Honry diff --git a/testing/web-platform/tests/web-nfc/idlharness.https.html b/testing/web-platform/tests/web-nfc/idlharness.https.html new file mode 100644 index 000000000000..58144852f92f --- /dev/null +++ b/testing/web-platform/tests/web-nfc/idlharness.https.html @@ -0,0 +1,95 @@ + + +Web NFC IDL tests + + + + + + + +
+ +
+interface Navigator {
+};
+
+ +
+enum NFCRecordType {
+    "empty",
+    "text",
+    "url",
+    "json",
+    "opaque"
+};
+
+typedef (DOMString or unrestricted double or ArrayBuffer or Dictionary) NFCRecordData;
+
+dictionary NFCRecord {
+    NFCRecordType recordType;
+    USVString     mediaType;
+    NFCRecordData data;
+};
+
+dictionary NFCMessage {
+    sequence data;
+    USVString           url;
+};
+
+partial interface Navigator {
+    readonly attribute NFC nfc;
+};
+
+typedef (DOMString or ArrayBuffer or NFCMessage) NFCPushMessage;
+
+interface NFC {
+    Promise push(NFCPushMessage message, optional NFCPushOptions options);
+    Promise cancelPush(optional NFCPushTarget target = "any");
+    Promise watch(MessageCallback callback,
+                        optional NFCWatchOptions options);
+    Promise cancelWatch(optional long id);
+};
+
+callback MessageCallback = void (NFCMessage message);
+
+enum NFCPushTarget {
+    "tag",
+    "peer",
+    "any"
+};
+
+dictionary NFCPushOptions {
+    NFCPushTarget       target = "any";
+    unrestricted double timeout = Infinity;
+    boolean             ignoreRead = true;
+};
+
+enum NFCWatchMode {
+    "web-nfc-only",
+    "any"
+};
+
+dictionary NFCWatchOptions {
+    USVString      url = "";
+    NFCRecordType? recordType;
+    USVString      mediaType = "";
+    NFCWatchMode   mode = "web-nfc-only";
+};
+
+ + diff --git a/testing/web-platform/tests/webaudio/OWNERS b/testing/web-platform/tests/webaudio/OWNERS index d4865fcd0854..327fbfac10ca 100644 --- a/testing/web-platform/tests/webaudio/OWNERS +++ b/testing/web-platform/tests/webaudio/OWNERS @@ -1 +1,3 @@ @chrislo +@padenot +@rtoy diff --git a/testing/web-platform/tests/webaudio/README.md b/testing/web-platform/tests/webaudio/README.md index e1afecd83791..bcfe291ff368 100644 --- a/testing/web-platform/tests/webaudio/README.md +++ b/testing/web-platform/tests/webaudio/README.md @@ -1,4 +1,4 @@ -Our test suite is currently tracking the [editor's draft](https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html) of the Web Audio API. +Our test suite is currently tracking the [editor's draft](https://webaudio.github.io/web-audio-api/) of the Web Audio API. The tests are arranged in subdirectories, corresponding to different sections of the spec. So, for example, tests for the `DelayNode` are diff --git a/testing/web-platform/tests/webdriver/OWNERS b/testing/web-platform/tests/webdriver/OWNERS index 45cf0102cd81..a9972635f981 100644 --- a/testing/web-platform/tests/webdriver/OWNERS +++ b/testing/web-platform/tests/webdriver/OWNERS @@ -2,3 +2,4 @@ @lukeis @AutomatedTester @shs96c +@mjzffr diff --git a/testing/web-platform/tests/webdriver/conftest.py b/testing/web-platform/tests/webdriver/conftest.py index 9ce11ec3ec47..6dbcfea203e6 100644 --- a/testing/web-platform/tests/webdriver/conftest.py +++ b/testing/web-platform/tests/webdriver/conftest.py @@ -1,12 +1,12 @@ import pytest from support.fixtures import ( - create_frame, create_window, http, server_config, session, session_session, + create_frame, create_session, create_window, http, server_config, session, url) pytest.fixture()(create_frame) +pytest.fixture()(create_session) pytest.fixture()(create_window) pytest.fixture()(http) pytest.fixture()(server_config) pytest.fixture(scope="function")(session) -pytest.fixture()(session_session) pytest.fixture()(url) diff --git a/testing/web-platform/tests/webdriver/support/__init__.py b/testing/web-platform/tests/webdriver/support/__init__.py new file mode 100644 index 000000000000..d37faf6da048 --- /dev/null +++ b/testing/web-platform/tests/webdriver/support/__init__.py @@ -0,0 +1 @@ +from merge_dictionaries import merge_dictionaries diff --git a/testing/web-platform/tests/webdriver/support/fixtures.py b/testing/web-platform/tests/webdriver/support/fixtures.py index 8c428ae12b16..91b93757cbcd 100644 --- a/testing/web-platform/tests/webdriver/support/fixtures.py +++ b/testing/web-platform/tests/webdriver/support/fixtures.py @@ -5,6 +5,7 @@ import urlparse import webdriver from support.http_request import HTTPRequest +from support import merge_dictionaries default_host = "http://127.0.0.1" default_port = "4444" @@ -88,31 +89,48 @@ def http(session): def server_config(): return json.loads(os.environ.get("WD_SERVER_CONFIG")) -def session(session_session, request): - # finalisers are popped off a stack, - # making their ordering reverse - request.addfinalizer(lambda: _switch_to_top_level_browsing_context(session_session)) - request.addfinalizer(lambda: _restore_windows(session_session)) - request.addfinalizer(lambda: _dismiss_user_prompts(session_session)) - request.addfinalizer(lambda: _ensure_valid_window(session_session)) +def create_session(request): + """Provide a factory function that produces wdclient `Session` instances. + If the `WD_CAPABILITIES` environment variable is set, it will be parsed as + JSON and the resulting object will be included in the WebDriver "Create + Session" command. Additional capabilities may be specified as an optional + argument to this function, but the operation will fail if any values + conflict with those specified via the environment. If the session is still + active at the completion of the test, it will be destroyed + automatically.""" - return session_session + def create_session(test_capabilities=None): + host = os.environ.get("WD_HOST", default_host) + port = int(os.environ.get("WD_PORT", default_port)) + if test_capabilities is None: + test_capabilities = {} + env_capabilities = json.loads(os.environ.get("WD_CAPABILITIES", "{}")) -# Create a wdclient `Session` object for each Pytest "session" -def session_session(request): - host = os.environ.get("WD_HOST", default_host) - port = int(os.environ.get("WD_PORT", default_port)) - capabilities = json.loads(os.environ.get("WD_CAPABILITIES", "{}")) + capabilities = merge_dictionaries(env_capabilities, test_capabilities) + session = webdriver.Session(host, port, capabilities=capabilities) - session = webdriver.Session(host, port, desired_capabilities=capabilities) + def destroy(): + if session.session_id is not None: + session.end() - def destroy(): - if session.session_id is not None: - session.end() + # finalisers are popped off a stack, making their ordering reverse + request.addfinalizer(destroy) + request.addfinalizer(lambda: _switch_to_top_level_browsing_context(session)) + request.addfinalizer(lambda: _restore_windows(session)) + request.addfinalizer(lambda: _dismiss_user_prompts(session)) + request.addfinalizer(lambda: _ensure_valid_window(session)) - request.addfinalizer(destroy) + return session - return session + return create_session + +# Create a wdclient `Session` object for each Pytest "session". If the +# `WD_CAPABILITIES` environment variable is set, it will be parsed as JSON and +# the resulting object will be included in the WebDriver "Create Session" +# command. If the session is still active at the completion of the test, it +# will be destroyed automatically. +def session(create_session): + return create_session() def url(server_config): def inner(path, query="", fragment=""): diff --git a/testing/web-platform/tests/webdriver/support/merge_dictionaries.py b/testing/web-platform/tests/webdriver/support/merge_dictionaries.py new file mode 100644 index 000000000000..cf06c9b433ce --- /dev/null +++ b/testing/web-platform/tests/webdriver/support/merge_dictionaries.py @@ -0,0 +1,49 @@ +def iteritems(d): + """Create a key-value iterator for the given dict in both Python 2.x and + Python 3.x environments""" + if hasattr(d, "iteritems"): + return d.iteritems() + return d.items() + +def merge_dictionaries(first, second): + """Given two dictionaries, create a third that defines all specified + key/value pairs. This merge_dictionaries is performed "deeply" on any nested + dictionaries. If a value is defined for the same key by both dictionaries, + an exception will be raised.""" + result = dict(first) + + for key, value in iteritems(second): + if key in result and result[key] != value: + if isinstance(result[key], dict) and isinstance(value, dict): + result[key] = merge_dictionaries(result[key], value) + elif result[key] != value: + raise TypeError("merge_dictionaries: refusing to overwrite " + + "attribute: `%s`" % key) + else: + result[key] = value + + return result + +if __name__ == "__main__": + assert merge_dictionaries({}, {}) == {} + assert merge_dictionaries({}, {"a": 23}) == {"a": 23} + assert merge_dictionaries({"a": 23}, {"b": 45}) == {"a": 23, "b": 45} + + e = None + try: + merge_dictionaries({"a": 23}, {"a": 45}) + except Exception as _e: + e = _e + assert isinstance(e, TypeError) + + assert merge_dictionaries({"a": 23}, {"a": 23}) == {"a": 23} + + assert merge_dictionaries({"a": {"b": 23}}, {"a": {"c": 45}}) == {"a": {"b": 23, "c": 45}} + assert merge_dictionaries({"a": {"b": 23}}, {"a": {"b": 23}}) == {"a": {"b": 23}} + + e = None + try: + merge_dictionaries({"a": {"b": 23}}, {"a": {"b": 45}}) + except Exception as _e: + e = _e + assert isinstance(e, TypeError) diff --git a/testing/web-platform/tests/webgl/conformance-1.0.3/resources/js-test-pre.js b/testing/web-platform/tests/webgl/conformance-1.0.3/resources/js-test-pre.js index 6067e0d46082..9236711b6698 100644 --- a/testing/web-platform/tests/webgl/conformance-1.0.3/resources/js-test-pre.js +++ b/testing/web-platform/tests/webgl/conformance-1.0.3/resources/js-test-pre.js @@ -78,7 +78,7 @@ function nonKhronosFrameworkNotifyDone() { // if found, since it's overriden by some tests. var wpt_test = window.test; var wpt_assert_true = window.assert_true; - + var wt_async_test = window.async_test; window.reportTestResultsToHarness = function reportTestResultsToHarness(success, msg) { if (window.parent.webglTestHarness) { @@ -100,6 +100,12 @@ function notifyFinishedToHarness() { } } +(function() { + var oldNotify = notifyFinishedToHarness; + var t = async_test("Overall test"); + window.notifyFinishedToHarness = t.step_func_done(oldNotify); +}()) + function _logToConsole(msg) { if (window.console) diff --git a/testing/web-platform/tests/webgl/tools/js-test-pre.patch b/testing/web-platform/tests/webgl/tools/js-test-pre.patch index 1e8a4c9581d6..d44e3f496de0 100644 --- a/testing/web-platform/tests/webgl/tools/js-test-pre.patch +++ b/testing/web-platform/tests/webgl/tools/js-test-pre.patch @@ -14,7 +14,7 @@ + // if found, since it's overriden by some tests. + var wpt_test = window.test; + var wpt_assert_true = window.assert_true; -+ ++ var wt_async_test = window.async_test; + + window.reportTestResultsToHarness = function reportTestResultsToHarness(success, msg) { + if (window.parent.webglTestHarness) { @@ -30,6 +30,19 @@ function notifyFinishedToHarness() { if (window.parent.webglTestHarness) { +@@ -100,2 +100,2 @@ function notifyFinishedToHarness() { + } + } + ++(function() { ++ var oldNotify = notifyFinishedToHarness; ++ var t = async_test("Overall test"); ++ window.notifyFinishedToHarness = t.step_func_done(oldNotify); ++}()) ++ + function _logToConsole(msg) + { + if (window.console) @@ -92,7 +106,7 @@ window.console.log(msg); } diff --git a/testing/web-platform/tests/webmessaging/README.md b/testing/web-platform/tests/webmessaging/README.md index 06b3a11475d8..0b81aa0658cb 100644 --- a/testing/web-platform/tests/webmessaging/README.md +++ b/testing/web-platform/tests/webmessaging/README.md @@ -1,10 +1,2 @@ -This directory contains the HTML5 Web Messaging test suite. - -The following document contains a list of each test file in the test suite and the results of running the test file on several browsers . - -To run this test suite within a browser, go to: . - -The latest Editor's Draft of HTML5 Web Messaging is: . - -The latest W3C Technical Report of HTML5 Web Messaging is . - +These are the cross-document messaging (`postMessage()`) tests for the +[cross-document messaging chapter of the HTML Standard](https://html.spec.whatwg.org/multipage/comms.html#web-messaging). diff --git a/testing/web-platform/tests/webmessaging/messageerror.html b/testing/web-platform/tests/webmessaging/messageerror.html new file mode 100644 index 000000000000..2cb51ee3c06c --- /dev/null +++ b/testing/web-platform/tests/webmessaging/messageerror.html @@ -0,0 +1,44 @@ + +onmessageerror content attribute + + + + + + + + diff --git a/testing/web-platform/tests/webmessaging/with-ports/027.html b/testing/web-platform/tests/webmessaging/with-ports/027.html index c85e02dc7a63..e5f8c9c14abe 100644 --- a/testing/web-platform/tests/webmessaging/with-ports/027.html +++ b/testing/web-platform/tests/webmessaging/with-ports/027.html @@ -6,14 +6,21 @@ diff --git a/testing/web-platform/tests/webrtc/OWNERS b/testing/web-platform/tests/webrtc/OWNERS index f01e65f87320..3e4538bb585c 100644 --- a/testing/web-platform/tests/webrtc/OWNERS +++ b/testing/web-platform/tests/webrtc/OWNERS @@ -1,4 +1,7 @@ -@dontcallmedom -@alvestrand -@phoglund @agouaillard +@alvestrand +@dontcallmedom +@foolip +@guidou +@henbos +@phoglund diff --git a/testing/web-platform/tests/webrtc/rtcpeerconnection/rtcconfiguration-icecandidatepoolsize.html b/testing/web-platform/tests/webrtc/RTCConfiguration-iceCandidatePoolSize.html similarity index 100% rename from testing/web-platform/tests/webrtc/rtcpeerconnection/rtcconfiguration-icecandidatepoolsize.html rename to testing/web-platform/tests/webrtc/RTCConfiguration-iceCandidatePoolSize.html diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-canTrickleIceCandidates.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-canTrickleIceCandidates.html new file mode 100644 index 000000000000..63dac8f37798 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-canTrickleIceCandidates.html @@ -0,0 +1,58 @@ + + + + + RTCPeerConnection canTrickleIceCandidates tests + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/rtcpeerconnection/rtcpeerconnection-constructor.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-constructor.html similarity index 100% rename from testing/web-platform/tests/webrtc/rtcpeerconnection/rtcpeerconnection-constructor.html rename to testing/web-platform/tests/webrtc/RTCPeerConnection-constructor.html diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-createDataChannel.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-createDataChannel.html new file mode 100644 index 000000000000..cb05e2ca0680 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-createDataChannel.html @@ -0,0 +1,128 @@ + + +RTCPeerConnection createDataChannel method + + + diff --git a/testing/web-platform/tests/webrtc/rtcpeerconnection/iceGatheringState.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-iceGatheringState.html similarity index 100% rename from testing/web-platform/tests/webrtc/rtcpeerconnection/iceGatheringState.html rename to testing/web-platform/tests/webrtc/RTCPeerConnection-iceGatheringState.html diff --git a/testing/web-platform/tests/webrtc/rtcpeerconnection/rtcpeerconnection-idl.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-idl.html similarity index 100% rename from testing/web-platform/tests/webrtc/rtcpeerconnection/rtcpeerconnection-idl.html rename to testing/web-platform/tests/webrtc/RTCPeerConnection-idl.html diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription.html new file mode 100644 index 000000000000..449b3013b046 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription.html @@ -0,0 +1,88 @@ + + + + + RTCPeerConnection setRemoteDescription tests + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/datachannel-idlharness.html b/testing/web-platform/tests/webrtc/datachannel-idlharness.html new file mode 100644 index 000000000000..ea2dd2a3df98 --- /dev/null +++ b/testing/web-platform/tests/webrtc/datachannel-idlharness.html @@ -0,0 +1,75 @@ + + + + + + + RTCPeerConnection Data Channel Empty String Test + + + + +
+ + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/getstats.html b/testing/web-platform/tests/webrtc/getstats.html new file mode 100644 index 000000000000..9a10936c85a6 --- /dev/null +++ b/testing/web-platform/tests/webrtc/getstats.html @@ -0,0 +1,130 @@ + + + + + + + RTCPeerConnection GetStats + + +
+

Retrieved stats info

+
+  
+
+
+ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/interfaces.html b/testing/web-platform/tests/webrtc/interfaces.html new file mode 100644 index 000000000000..e64286d8d6bd --- /dev/null +++ b/testing/web-platform/tests/webrtc/interfaces.html @@ -0,0 +1,57 @@ + + + + WebRTC IDL Tests + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/no-media-call.html b/testing/web-platform/tests/webrtc/no-media-call.html index 5059ba6dbc46..c4979e852147 100644 --- a/testing/web-platform/tests/webrtc/no-media-call.html +++ b/testing/web-platform/tests/webrtc/no-media-call.html @@ -73,10 +73,6 @@ This test uses the legacy callback API with no media, and thus does not require } }); - var onRemoteStream = test.step_func(function(event) { - assert_unreached('WebRTC received a stream when there was none'); - }); - var onIceConnectionStateChange = test.step_func(function(event) { assert_equals(event.type, 'iceconnectionstatechange'); assert_not_equals(gFirstConnection.iceConnectionState, "failed", "iceConnectionState of first connection"); @@ -125,7 +121,6 @@ This test uses the legacy callback API with no media, and thus does not require gSecondConnection = new RTCPeerConnection(null); gSecondConnection.onicecandidate = onIceCandidateToSecond; - gSecondConnection.onaddstream = onRemoteStream; gSecondConnection.oniceconnectionstatechange = onIceConnectionStateChange; // The offerToReceiveVideo is necessary and sufficient to make diff --git a/testing/web-platform/tests/webrtc/promises-call.html b/testing/web-platform/tests/webrtc/promises-call.html index d83508a38ae4..ceb6ab258ccb 100644 --- a/testing/web-platform/tests/webrtc/promises-call.html +++ b/testing/web-platform/tests/webrtc/promises-call.html @@ -36,10 +36,6 @@ This test uses data only, and thus does not require fake media devices. } }); - var onRemoteStream = test.step_func(function(event) { - assert_unreached('WebRTC received a stream when there was none'); - }); - var onIceConnectionStateChange = test.step_func(function(event) { assert_equals(event.type, 'iceconnectionstatechange'); var stateinfo = document.getElementById('stateinfo'); @@ -75,7 +71,6 @@ This test uses data only, and thus does not require fake media devices. gSecondConnection = new RTCPeerConnection(null); gSecondConnection.onicecandidate = onIceCandidateToSecond; - gSecondConnection.onaddstream = onRemoteStream; gSecondConnection.oniceconnectionstatechange = onIceConnectionStateChange; // The createDataChannel is necessary and sufficient to make diff --git a/testing/web-platform/tests/webrtc/rtcpeerconnection/setRemoteDescription.html b/testing/web-platform/tests/webrtc/rtcpeerconnection/setRemoteDescription.html deleted file mode 100644 index 4557fcbf82fa..000000000000 --- a/testing/web-platform/tests/webrtc/rtcpeerconnection/setRemoteDescription.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - RTCPeerConnection setRemoteDescription tests - - - - - - - - - diff --git a/testing/web-platform/tests/webrtc/simplecall.html b/testing/web-platform/tests/webrtc/simplecall.html index 23f13d4675c1..bf12e5db1b67 100644 --- a/testing/web-platform/tests/webrtc/simplecall.html +++ b/testing/web-platform/tests/webrtc/simplecall.html @@ -47,7 +47,9 @@ property to true in Firefox. function getUserMediaOkCallback(localStream) { gFirstConnection = new RTCPeerConnection(null); gFirstConnection.onicecandidate = onIceCandidateToFirst; - gFirstConnection.addStream(localStream); + localStream.getTracks().forEach(function(track) { + gFirstConnection.addTrack(track, localStream); + }); gFirstConnection.createOffer(onOfferCreated, failed('createOffer')); var videoTag = document.getElementById('local-view'); @@ -65,7 +67,7 @@ property to true in Firefox. function receiveCall(offerSdp) { gSecondConnection = new RTCPeerConnection(null); gSecondConnection.onicecandidate = onIceCandidateToSecond; - gSecondConnection.onaddstream = onRemoteStream; + gSecondConnection.ontrack = onRemoteTrack; var parsedOffer = new RTCSessionDescription({ type: 'offer', sdp: offerSdp }); @@ -97,9 +99,11 @@ property to true in Firefox. gFirstConnection.addIceCandidate(event.candidate); }); - var onRemoteStream = test.step_func(function(event) { + var onRemoteTrack = test.step_func(function(event) { var videoTag = document.getElementById('remote-view'); - videoTag.srcObject = event.stream; + if (!videoTag.srcObject) { + videoTag.srcObject = event.streams[0]; + } }); // Returns a suitable error callback. diff --git a/testing/web-platform/tests/websockets/README.md b/testing/web-platform/tests/websockets/README.md index f03192230a5e..0e5ffd685dcd 100644 --- a/testing/web-platform/tests/websockets/README.md +++ b/testing/web-platform/tests/websockets/README.md @@ -1,10 +1,2 @@ -This directory contains the WebSocket API test suite. - -The following document contains a list of each test file in the test suite and the results of running the test file on several browsers . - -To run this test suite within a browser, go to: . - -The latest Editor's Draft of WebSocket API is: . - -The latest W3C Technical Report of WebSocket API is . - +These are the `WebSocket` tests for the +[Web sockets chapter of the HTML Standard](https://html.spec.whatwg.org/multipage/comms.html#network). diff --git a/testing/web-platform/tests/webstorage/README.md b/testing/web-platform/tests/webstorage/README.md index 298028cc1604..6b70aa5ac9d3 100644 --- a/testing/web-platform/tests/webstorage/README.md +++ b/testing/web-platform/tests/webstorage/README.md @@ -1,10 +1,2 @@ -This directory contains the Web Storage test suite. - -The spec's Implementation Report contains a list of each test file in the test suite and the results of running the test file on several browsers . - -To run this test suite within a browser, go to: . - -A W3C Recommendation of Web Storage was published on 30 July 2013 . - -Latest Editor's Draft of Web Storage is: . - +These are the storage (`localStorage`, `sessionStorage`) tests for the +[Web storage chapter of the HTML Standard](https://html.spec.whatwg.org/multipage/webstorage.html). diff --git a/testing/web-platform/tests/webvr/idlharness.html b/testing/web-platform/tests/webvr/idlharness.html index 77716df9bac2..b7158117c609 100644 --- a/testing/web-platform/tests/webvr/idlharness.html +++ b/testing/web-platform/tests/webvr/idlharness.html @@ -14,7 +14,6 @@ // https://w3c.github.io/webvr/archive/prerelease/1.1/index.html interface VRDisplay : EventTarget { - readonly attribute boolean isConnected; readonly attribute boolean isPresenting; /** @@ -55,25 +54,6 @@ interface VRDisplay : EventTarget { */ boolean getFrameData(VRFrameData frameData); - /** - * Return a VRPose containing the future predicted pose of the VRDisplay - * when the current frame will be presented. The value returned will not - * change until JavaScript has returned control to the browser. - * - * The VRPose will contain the position, orientation, velocity, - * and acceleration of each of these properties. - */ - [NewObject] VRPose getPose(); - - /** - * Reset the pose for this display, treating its current position and - * orientation as the "origin/zero" values. VRPose.position, - * VRPose.orientation, and VRStageParameters.sittingToStandingTransform may be - * updated when calling resetPose(). This should be called in only - * sitting-space experiences. - */ - void resetPose(); - /** * z-depth defining the near plane of the eye view frustum * enables mapping of values in the render target depth @@ -144,7 +124,6 @@ dictionary VRLayer { interface VRDisplayCapabilities { readonly attribute boolean hasPosition; - readonly attribute boolean hasOrientation; readonly attribute boolean hasExternalDisplay; readonly attribute boolean canPresent; readonly attribute unsigned long maxLayers; @@ -155,13 +134,6 @@ enum VREye { "right" }; -interface VRFieldOfView { - readonly attribute double upDegrees; - readonly attribute double rightDegrees; - readonly attribute double downDegrees; - readonly attribute double leftDegrees; -}; - interface VRPose { readonly attribute Float32Array? position; readonly attribute Float32Array? linearVelocity; @@ -186,8 +158,6 @@ interface VRFrameData { interface VREyeParameters { readonly attribute Float32Array offset; - [SameObject] readonly attribute VRFieldOfView fieldOfView; - readonly attribute unsigned long renderWidth; readonly attribute unsigned long renderHeight; }; diff --git a/testing/web-platform/tests/workers/README.md b/testing/web-platform/tests/workers/README.md index 3a1c58f3bc66..78cc74371b98 100644 --- a/testing/web-platform/tests/workers/README.md +++ b/testing/web-platform/tests/workers/README.md @@ -1,8 +1,2 @@ -This directory contains the Web Workers test suite. - -To run this test suite within a browser, go to: . - -The latest Editor's Draft of Web Workers is: . - -The latest W3C Technical Report of Web Workers is . - +These are the workers (`Worker`, `SharedWorker`) tests for the +[Web workers chapter of the HTML Standard](https://html.spec.whatwg.org/multipage/workers.html).