Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(955)

Side by Side Diff: Source/bindings/core/v8/ScriptStreamerTest.cpp

Issue 368283002: Stream scripts to V8 as they load - Blink side. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: removed untrue assert Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5
6 #include "config.h"
7 #include "bindings/core/v8/ScriptStreamer.h"
8
9 #include "bindings/core/v8/ScriptStreamerThread.h"
10 #include "bindings/core/v8/V8Binding.h"
11 #include "bindings/core/v8/V8ScriptRunner.h"
12 #include "core/dom/PendingScript.h"
13 #include "core/frame/Settings.h"
14 #include "platform/Task.h"
15 #include "public/platform/Platform.h"
16
17 #include <gtest/gtest.h>
18 #include <v8.h>
19
20 namespace blink {
21
22 namespace {
23
24 class ScriptStreamingTest : public testing::Test {
25 public:
26 ScriptStreamingTest()
27 : m_scope(v8::Isolate::GetCurrent())
28 , m_settings(Settings::create())
29 , m_resourceRequest("http://www.streaming-test.com/")
30 , m_resource(new ScriptResource(m_resourceRequest, "text/utf-8"))
31 , m_pendingScript(0, m_resource) // Takes ownership of m_resource.
32 {
33 m_settings->setV8ScriptStreamingEnabled(true);
34 m_resource->setLoading(true);
35 }
36
37 ScriptState* scriptState() const { return m_scope.scriptState(); }
38 v8::Isolate* isolate() const { return m_scope.isolate(); }
39
40 protected:
41 void appendData(const char* data)
42 {
43 m_resource->appendData(data, strlen(data));
44 // Yield control to the background thread, so that V8 gets a change to
45 // process the data before the main thread adds more. Note that we
46 // cannot fully control in what kind of chunks the data is passed to V8
47 // (if the V8 is not requesting more data between two appendData calls,
48 // V8 will get both chunks together).
49 WTF::yield();
50 }
51
52 void appendPadding()
53 {
54 for (int i = 0; i < 10; ++i) {
55 appendData(" /* this is padding to make the script long enough, so "
56 "that V8's buffer gets filled and it starts processing "
57 "the data */ ");
58 }
59 }
60
61 void finish()
62 {
63 m_resource->finish();
64 m_resource->setLoading(false);
65 }
66
67 void processTasksUntilStreamingComplete()
68 {
69 while (ScriptStreamerThread::shared()->isRunningTask()) {
70 WebThread* currentThread = blink::Platform::current()->currentThread ();
71 currentThread->postTask(new Task(WTF::bind(&WebThread::exitRunLoop, currentThread)));
72 currentThread->enterRunLoop();
73 }
74 }
75
76 V8TestingScope m_scope;
77 OwnPtr<Settings> m_settings;
78 // The Resource and PendingScript where we stream from. These don't really
79 // fetch any data outside the test; the test controls the data by calling
80 // ScriptResource::appendData.
81 ResourceRequest m_resourceRequest;
82 ScriptResource* m_resource;
83 PendingScript m_pendingScript;
84 };
85
86 class TestScriptResourceClient : public ScriptResourceClient {
87 public:
88 TestScriptResourceClient()
89 : m_finished(false) { }
90
91 virtual void notifyFinished(Resource*) OVERRIDE { m_finished = true; }
92
93 bool finished() const { return m_finished; }
94
95 private:
96 bool m_finished;
97 };
98
99 TEST_F(ScriptStreamingTest, CompilingStreamedScript)
100 {
101 // Test that we can successfully compile a streamed script.
102 bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.ge t(), m_scope.scriptState());
103 TestScriptResourceClient client;
104 m_pendingScript.watchForLoad(&client);
105 EXPECT_TRUE(started);
106
107 appendData("function foo() {");
108 appendPadding();
109 appendData("return 5; }");
110 appendPadding();
111 appendData("foo();");
112 EXPECT_FALSE(client.finished());
113 finish();
114
115 // Process tasks on the main thread until the streaming background thread
116 // has completed its tasks.
117 processTasksUntilStreamingComplete();
118 EXPECT_TRUE(client.finished());
119 bool errorOccurred = false;
120 ScriptSourceCode sourceCode = m_pendingScript.getSource(KURL(), errorOccurre d);
121 EXPECT_FALSE(errorOccurred);
122 EXPECT_TRUE(sourceCode.streamer());
123 v8::TryCatch tryCatch;
124 v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(sourceCode, is olate());
125 EXPECT_FALSE(script.IsEmpty());
126 EXPECT_FALSE(tryCatch.HasCaught());
127 }
128
129 TEST_F(ScriptStreamingTest, CompilingStreamedScriptWithParseError)
130 {
131 // Test that scripts with parse errors are handled properly. In those cases,
132 // the V8 side typically finished before loading finishes: make sure we
133 // handle it gracefully.
134 bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.ge t(), m_scope.scriptState());
135 TestScriptResourceClient client;
136 m_pendingScript.watchForLoad(&client);
137 EXPECT_TRUE(started);
138 appendData("function foo() {");
139 appendData("this is the part which will be a parse error");
140 // V8 won't realize the parse error until it actually starts parsing the
141 // script, and this happens only when its buffer is filled.
142 appendPadding();
143
144 EXPECT_FALSE(client.finished());
145
146 // Force the V8 side to finish before the loading.
147 processTasksUntilStreamingComplete();
148 EXPECT_FALSE(client.finished());
149
150 finish();
151 EXPECT_TRUE(client.finished());
152
153 bool errorOccurred = false;
154 ScriptSourceCode sourceCode = m_pendingScript.getSource(KURL(), errorOccurre d);
155 EXPECT_FALSE(errorOccurred);
156 EXPECT_TRUE(sourceCode.streamer());
157 v8::TryCatch tryCatch;
158 v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(sourceCode, is olate());
159 EXPECT_TRUE(script.IsEmpty());
160 EXPECT_TRUE(tryCatch.HasCaught());
161 }
162
163 TEST_F(ScriptStreamingTest, CancellingStreaming)
164 {
165 // Test that the upper layers (PendingScript and up) can be ramped down
166 // while streaming is ongoing, and ScriptStreamer handles it gracefully.
167 bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.ge t(), m_scope.scriptState());
168 TestScriptResourceClient client;
169 m_pendingScript.watchForLoad(&client);
170 EXPECT_TRUE(started);
171 appendData("function foo() {");
172
173 // In general, we cannot control what the background thread is doing
174 // (whether it's parsing or waiting for more data). In this test, we have
175 // given it so little data that it's surely waiting for more.
176
177 // Simulate cancelling the network load (e.g., because the user navigated
178 // away).
179 EXPECT_FALSE(client.finished());
180 m_pendingScript.stopWatchingForLoad(&client);
181 m_pendingScript = PendingScript(); // This will destroy m_resource.
182 m_resource = 0;
183
184 // The V8 side will complete too. This should not crash. We don't receive
185 // any results from the streaming and the client doesn't get notified.
186 processTasksUntilStreamingComplete();
187 EXPECT_FALSE(client.finished());
188 }
189
190 TEST_F(ScriptStreamingTest, SuppressingStreaming)
191 {
192 // If we notice during streaming that there is a code cache, streaming
193 // is suppressed (V8 doesn't parse while the script is loading), and the
194 // upper layer (ScriptResourceClient) should get a notification when the
195 // script is loaded.
196 bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.ge t(), m_scope.scriptState());
197 TestScriptResourceClient client;
198 m_pendingScript.watchForLoad(&client);
199 EXPECT_TRUE(started);
200 appendData("function foo() {");
201 appendPadding();
202
203 m_resource->setCachedMetadata(V8ScriptRunner::tagForCodeCache(), "X", 1, Res ource::CacheLocally);
204
205 appendPadding();
206 finish();
207 processTasksUntilStreamingComplete();
208 EXPECT_TRUE(client.finished());
209
210 bool errorOccurred = false;
211 ScriptSourceCode sourceCode = m_pendingScript.getSource(KURL(), errorOccurre d);
212 EXPECT_FALSE(errorOccurred);
213 // ScriptSourceCode doesn't refer to the streamer, since we have suppressed
214 // the streaming and resumed the non-streaming code path for script
215 // compilation.
216 EXPECT_FALSE(sourceCode.streamer());
217 }
218
219 } // namespace
220
221 } // namespace blink
OLDNEW
« no previous file with comments | « Source/bindings/core/v8/ScriptStreamer.cpp ('k') | Source/bindings/core/v8/ScriptStreamerThread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698