| Index: third_party/WebKit/Source/web/tests/HTMLDocumentParserLoadingTest.cpp
|
| diff --git a/third_party/WebKit/Source/web/tests/HTMLDocumentParserLoadingTest.cpp b/third_party/WebKit/Source/web/tests/HTMLDocumentParserLoadingTest.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4f084d6f3fd5fbcd67a6dbb6a9a6e1b5a0f4cd10
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/web/tests/HTMLDocumentParserLoadingTest.cpp
|
| @@ -0,0 +1,377 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "core/html/parser/HTMLDocumentParser.h"
|
| +
|
| +#include "core/dom/Document.h"
|
| +#include "platform/testing/UnitTestHelpers.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "web/tests/sim/SimRequest.h"
|
| +#include "web/tests/sim/SimTest.h"
|
| +
|
| +namespace blink {
|
| +
|
| +using namespace HTMLNames;
|
| +
|
| +class HTMLDocumentParserLoadingTest
|
| + : public SimTest,
|
| + public ::testing::WithParamInterface<bool> {
|
| + protected:
|
| + HTMLDocumentParserLoadingTest() {
|
| + Document::setThreadedParsingEnabledForTesting(GetParam());
|
| + }
|
| +};
|
| +
|
| +INSTANTIATE_TEST_CASE_P(Threaded,
|
| + HTMLDocumentParserLoadingTest,
|
| + ::testing::Values(true));
|
| +INSTANTIATE_TEST_CASE_P(NotThreaded,
|
| + HTMLDocumentParserLoadingTest,
|
| + ::testing::Values(false));
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + ShouldNotPauseParsingForExternalStylesheetsInHead) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssHeadResource("https://example.com/testHead.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + mainResource.complete(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "<link rel=stylesheet href=testHead.css>"
|
| + "</head><body>"
|
| + "<div id=\"bodyDiv\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("bodyDiv"));
|
| + cssHeadResource.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("bodyDiv"));
|
| +}
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + ShouldNotPauseParsingForExternalStylesheetsImportedInHead) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssHeadResource("https://example.com/testHead.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + mainResource.complete(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "<style>"
|
| + "@import 'testHead.css'"
|
| + "</style>"
|
| + "</head><body>"
|
| + "<div id=\"bodyDiv\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("bodyDiv"));
|
| + cssHeadResource.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("bodyDiv"));
|
| +}
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + ShouldPauseParsingForExternalStylesheetsInBody) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssHeadResource("https://example.com/testHead.css", "text/css");
|
| + SimRequest cssBodyResource("https://example.com/testBody.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + mainResource.complete(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "<link rel=stylesheet href=testHead.css>"
|
| + "</head><body>"
|
| + "<div id=\"before\"></div>"
|
| + "<link rel=stylesheet href=testBody.css>"
|
| + "<div id=\"after\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after"));
|
| +
|
| + // Completing the head css shouldn't change anything
|
| + cssHeadResource.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after"));
|
| +
|
| + // Completing the body resource and pumping the tasks should continue parsing
|
| + // and create the "after" div.
|
| + cssBodyResource.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_TRUE(document().getElementById("after"));
|
| +}
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + ShouldPauseParsingForExternalStylesheetsInBodyIncremental) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssHeadResource("https://example.com/testHead.css", "text/css");
|
| + SimRequest cssBodyResource1("https://example.com/testBody1.css", "text/css");
|
| + SimRequest cssBodyResource2("https://example.com/testBody2.css", "text/css");
|
| + SimRequest cssBodyResource3("https://example.com/testBody3.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + mainResource.start();
|
| + mainResource.write(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "<link rel=stylesheet href=testHead.css>"
|
| + "</head><body>"
|
| + "<div id=\"before\"></div>"
|
| + "<link rel=stylesheet href=testBody1.css>"
|
| + "<div id=\"after1\"></div>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after1"));
|
| + EXPECT_FALSE(document().getElementById("after2"));
|
| + EXPECT_FALSE(document().getElementById("after3"));
|
| +
|
| + mainResource.write(
|
| + "<link rel=stylesheet href=testBody2.css>"
|
| + "<div id=\"after2\"></div>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after1"));
|
| + EXPECT_FALSE(document().getElementById("after2"));
|
| + EXPECT_FALSE(document().getElementById("after3"));
|
| +
|
| + mainResource.complete(
|
| + "<link rel=stylesheet href=testBody3.css>"
|
| + "<div id=\"after3\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after1"));
|
| + EXPECT_FALSE(document().getElementById("after2"));
|
| + EXPECT_FALSE(document().getElementById("after3"));
|
| +
|
| + // Completing the head css shouldn't change anything
|
| + cssHeadResource.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after1"));
|
| + EXPECT_FALSE(document().getElementById("after2"));
|
| + EXPECT_FALSE(document().getElementById("after3"));
|
| +
|
| + // Completing the second css shouldn't change anything
|
| + cssBodyResource2.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after1"));
|
| + EXPECT_FALSE(document().getElementById("after2"));
|
| + EXPECT_FALSE(document().getElementById("after3"));
|
| +
|
| + // Completing the first css should allow the parser to continue past it and
|
| + // the second css which was already completed and then pause again before the
|
| + // third css.
|
| + cssBodyResource1.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_TRUE(document().getElementById("after1"));
|
| + EXPECT_TRUE(document().getElementById("after2"));
|
| + EXPECT_FALSE(document().getElementById("after3"));
|
| +
|
| + // Completing the third css should let it continue to the end.
|
| + cssBodyResource3.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_TRUE(document().getElementById("after1"));
|
| + EXPECT_TRUE(document().getElementById("after2"));
|
| + EXPECT_TRUE(document().getElementById("after3"));
|
| +}
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + ShouldNotPauseParsingForExternalNonMatchingStylesheetsInBody) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssHeadResource("https://example.com/testHead.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + mainResource.complete(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "<link rel=stylesheet href=testHead.css>"
|
| + "</head><body>"
|
| + "<div id=\"before\"></div>"
|
| + "<link rel=stylesheet href=testBody.css type='print'>"
|
| + "<div id=\"after\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_TRUE(document().getElementById("after"));
|
| +
|
| + // Completing the head css shouldn't change anything
|
| + cssHeadResource.complete("");
|
| +}
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + ShouldPauseParsingForExternalStylesheetsImportedInBody) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssHeadResource("https://example.com/testHead.css", "text/css");
|
| + SimRequest cssBodyResource("https://example.com/testBody.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + mainResource.complete(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "<link rel=stylesheet href=testHead.css>"
|
| + "</head><body>"
|
| + "<div id=\"before\"></div>"
|
| + "<style>"
|
| + "@import 'testBody.css'"
|
| + "</style>"
|
| + "<div id=\"after\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after"));
|
| +
|
| + // Completing the head css shouldn't change anything
|
| + cssHeadResource.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after"));
|
| +
|
| + // Completing the body resource and pumping the tasks should continue parsing
|
| + // and create the "after" div.
|
| + cssBodyResource.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_TRUE(document().getElementById("after"));
|
| +}
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + ShouldPauseParsingForExternalStylesheetsWrittenInBody) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssHeadResource("https://example.com/testHead.css", "text/css");
|
| + SimRequest cssBodyResource("https://example.com/testBody.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + mainResource.complete(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "<link rel=stylesheet href=testHead.css>"
|
| + "</head><body>"
|
| + "<div id=\"before\"></div>"
|
| + "<script>"
|
| + "document.write('<link rel=stylesheet href=testBody.css>');"
|
| + "</script>"
|
| + "<div id=\"after\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after"));
|
| +
|
| + // Completing the head css shouldn't change anything
|
| + cssHeadResource.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_FALSE(document().getElementById("after"));
|
| +
|
| + // Completing the body resource and pumping the tasks should continue parsing
|
| + // and create the "after" div.
|
| + cssBodyResource.complete("");
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_TRUE(document().getElementById("after"));
|
| +}
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + PendingHeadStylesheetShouldNotBlockParserForBodyInlineStyle) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssHeadResource("https://example.com/testHead.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + mainResource.complete(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "<link rel=stylesheet href=testHead.css>"
|
| + "</head><body>"
|
| + "<div id=\"before\"></div>"
|
| + "<style>"
|
| + "</style>"
|
| + "<div id=\"after\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_TRUE(document().getElementById("after"));
|
| + cssHeadResource.complete("");
|
| +}
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + PendingHeadStylesheetShouldNotBlockParserForBodyShadowDom) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssHeadResource("https://example.com/testHead.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + // The marquee tag has a shadow DOM that synchronously applies a stylesheet.
|
| + mainResource.complete(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "<link rel=stylesheet href=testHead.css>"
|
| + "</head><body>"
|
| + "<div id=\"before\"></div>"
|
| + "<marquee>Marquee</marquee>"
|
| + "<div id=\"after\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_TRUE(document().getElementById("after"));
|
| + cssHeadResource.complete("");
|
| +}
|
| +
|
| +TEST_P(HTMLDocumentParserLoadingTest,
|
| + ShouldNotPauseParsingForExternalStylesheetsAttachedInBody) {
|
| + SimRequest mainResource("https://example.com/test.html", "text/html");
|
| + SimRequest cssAsyncResource("https://example.com/testAsync.css", "text/css");
|
| +
|
| + loadURL("https://example.com/test.html");
|
| +
|
| + mainResource.complete(
|
| + "<!DOCTYPE html>"
|
| + "<html><head>"
|
| + "</head><body>"
|
| + "<div id=\"before\"></div>"
|
| + "<script>"
|
| + "var attach = document.getElementsByTagName('script')[0];"
|
| + "var link = document.createElement('link');"
|
| + "link.rel = 'stylesheet';"
|
| + "link.type = 'text/css';"
|
| + "link.href = 'testAsync.css';"
|
| + "link.media = 'all';"
|
| + "attach.appendChild(link);"
|
| + "</script>"
|
| + "<div id=\"after\"></div>"
|
| + "</body></html>");
|
| +
|
| + testing::runPendingTasks();
|
| + EXPECT_TRUE(document().getElementById("before"));
|
| + EXPECT_TRUE(document().getElementById("after"));
|
| +
|
| + cssAsyncResource.complete("");
|
| +}
|
| +
|
| +} // namespace blink
|
|
|