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

Side by Side Diff: third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp

Issue 2727733002: Implement AudioWorkletProcessor interface (Closed)
Patch Set: Added more unit test for parsing Created 3 years, 9 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
OLDNEW
(Empty)
1 // Copyright 2017 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 #include "modules/webaudio/AudioWorkletGlobalScope.h"
6
7 #include "bindings/core/v8/ScriptSourceCode.h"
8 #include "bindings/core/v8/ScriptState.h"
9 #include "bindings/core/v8/ScriptValue.h"
10 #include "bindings/core/v8/SourceLocation.h"
11 #include "bindings/core/v8/ToV8.h"
12 #include "bindings/core/v8/V8Binding.h"
13 #include "bindings/core/v8/V8BindingForTesting.h"
14 #include "bindings/core/v8/V8BindingMacros.h"
15 #include "bindings/core/v8/V8GCController.h"
16 #include "bindings/core/v8/V8ObjectConstructor.h"
17 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
18 #include "core/workers/WorkerBackingThread.h"
19 #include "core/workers/WorkerReportingProxy.h"
20 #include "core/workers/WorkerThreadStartupData.h"
21 #include "modules/webaudio/AudioBuffer.h"
22 #include "modules/webaudio/AudioWorkletProcessor.h"
23 #include "modules/webaudio/AudioWorkletProcessorDefinition.h"
24 #include "modules/webaudio/AudioWorkletThread.h"
25 #include "platform/weborigin/SecurityOrigin.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 namespace blink {
29
30 namespace {
31
32 static const size_t kRenderQuantumFrames = 128;
33 static const float kTestingSampleRate = 44100;
Raymond Toy 2017/03/17 16:45:32 Add comment that 44100 isn't really special, just
hongchan 2017/03/20 17:03:32 Done.
34
35 // A null WorkerReportingProxy, supplied when creating AudioWorkletThreads.
36 class TestAudioWorkletReportingProxy : public WorkerReportingProxy {
37 public:
38 static std::unique_ptr<TestAudioWorkletReportingProxy> create() {
39 return WTF::wrapUnique(new TestAudioWorkletReportingProxy());
40 }
41
42 // (Empty) WorkerReportingProxy implementation:
43 void countFeature(UseCounter::Feature) override {}
44 void countDeprecation(UseCounter::Feature) override {}
45 void reportException(const String& errorMessage,
46 std::unique_ptr<SourceLocation>,
47 int exceptionId) override {}
48 void reportConsoleMessage(MessageSource,
49 MessageLevel,
50 const String& message,
51 SourceLocation*) override {}
52 void postMessageToPageInspector(const String&) override {}
53 void didEvaluateWorkerScript(bool success) override {}
54 void didCloseWorkerGlobalScope() override {}
55 void willDestroyWorkerGlobalScope() override {}
56 void didTerminateWorkerThread() override {}
57
58 private:
59 TestAudioWorkletReportingProxy() {}
60 };
61
62 } // namespace
63
64 class AudioWorkletGlobalScopeTest : public ::testing::Test {
65 public:
66 void SetUp() override {
67 AudioWorkletThread::createSharedBackingThreadForTest();
68 m_reportingProxy = TestAudioWorkletReportingProxy::create();
69 m_securityOrigin =
70 SecurityOrigin::create(KURL(ParsedURLString, "http://fake.url/"));
71 }
72
73 void TearDown() override { AudioWorkletThread::clearSharedBackingThread(); }
74
75 std::unique_ptr<AudioWorkletThread> createAudioWorkletThread() {
76 std::unique_ptr<AudioWorkletThread> thread =
77 AudioWorkletThread::create(nullptr, *m_reportingProxy);
78 thread->start(
79 WorkerThreadStartupData::create(
80 KURL(ParsedURLString, "http://fake.url/"), "fake user agent", "",
81 nullptr, DontPauseWorkerGlobalScopeOnStart, nullptr, "",
82 m_securityOrigin.get(), nullptr, WebAddressSpaceLocal, nullptr,
83 nullptr, WorkerV8Settings::Default()),
84 ParentFrameTaskRunners::create(nullptr));
85 return thread;
86 }
87
88 void runBasicTest(WorkerThread* thread) {
Raymond Toy 2017/03/17 16:45:32 Describe what these tests are trying to test.
hongchan 2017/03/20 17:03:32 Done.
89 WaitableEvent waitableEvent;
90 thread->postTask(
91 BLINK_FROM_HERE,
92 crossThreadBind(
93 &AudioWorkletGlobalScopeTest::runBasicTestOnWorkletThread,
94 crossThreadUnretained(this), crossThreadUnretained(thread),
95 crossThreadUnretained(&waitableEvent)));
96 waitableEvent.wait();
97 }
98
99 void runSimpleProcessTest(WorkerThread* thread) {
100 WaitableEvent waitableEvent;
101 thread->postTask(
102 BLINK_FROM_HERE,
103 crossThreadBind(
104 &AudioWorkletGlobalScopeTest::runSimpleProcessTestOnWorkletThread,
105 crossThreadUnretained(this), crossThreadUnretained(thread),
106 crossThreadUnretained(&waitableEvent)));
107 waitableEvent.wait();
108 }
109
110 void runParsingTest(WorkerThread* thread) {
111 WaitableEvent waitableEvent;
112 thread->postTask(
113 BLINK_FROM_HERE,
114 crossThreadBind(
115 &AudioWorkletGlobalScopeTest::runParsingTestOnWorkletThread,
116 crossThreadUnretained(this), crossThreadUnretained(thread),
117 crossThreadUnretained(&waitableEvent)));
118 waitableEvent.wait();
119 }
120
121 private:
122 void runBasicTestOnWorkletThread(WorkerThread* thread,
123 WaitableEvent* waitEvent) {
124 EXPECT_TRUE(thread->isCurrentThread());
125
126 AudioWorkletGlobalScope* globalScope =
127 static_cast<AudioWorkletGlobalScope*>(thread->globalScope());
128 EXPECT_TRUE(globalScope);
129 EXPECT_TRUE(globalScope->isAudioWorkletGlobalScope());
130
131 ScriptState* scriptState =
132 globalScope->scriptController()->getScriptState();
133 EXPECT_TRUE(scriptState);
134
135 v8::Isolate* isolate = scriptState->isolate();
136 EXPECT_TRUE(isolate);
137
138 ScriptState::Scope scope(scriptState);
139
140 globalScope->scriptController()->evaluate(ScriptSourceCode(
141 R"JS(
142 registerProcessor('testProcessor', class {
143 constructor () {}
144 process () {}
145 });
146 )JS"));
147
148 AudioWorkletProcessorDefinition* definition =
149 globalScope->findDefinition("testProcessor");
150 EXPECT_TRUE(definition);
151 EXPECT_EQ(definition->name(), "testProcessor");
152 EXPECT_TRUE(definition->constructorLocal(isolate)->IsFunction());
153 EXPECT_TRUE(definition->processLocal(isolate)->IsFunction());
154
155 AudioWorkletProcessor* processor =
156 globalScope->createInstance("testProcessor");
157 EXPECT_TRUE(processor);
158 EXPECT_EQ(processor->name(), "testProcessor");
159 EXPECT_TRUE(processor->instanceLocal(isolate)->IsObject());
160
161 waitEvent->signal();
162 }
163
164 void runParsingTestOnWorkletThread(WorkerThread* thread,
165 WaitableEvent* waitEvent) {
166 EXPECT_TRUE(thread->isCurrentThread());
167
168 AudioWorkletGlobalScope* globalScope =
169 static_cast<AudioWorkletGlobalScope*>(thread->globalScope());
170 ScriptState* scriptState =
171 globalScope->scriptController()->getScriptState();
172
173 ScriptState::Scope scope(scriptState);
174
175 globalScope->scriptController()->evaluate(ScriptSourceCode(
176 R"JS(
177 var class1 = function () {};
178 class1.prototype.process = function () {};
179 registerProcessor('class1', class1);
180
181 var class2 = function () {};
182 class2.prototype = { process: function () {} };
183 registerProcessor('class2', class2);
184
185 var class3 = function () {};
186 Object.defineProperty(class3, 'prototype', {
187 get: function () {
188 return {
189 process: function () {}
190 };
191 }
192 });
193 registerProcessor('class3', class3);
194 )JS"));
195
196 EXPECT_TRUE(globalScope->findDefinition("class1"));
197 EXPECT_TRUE(globalScope->findDefinition("class2"));
198 EXPECT_FALSE(globalScope->findDefinition("class3"));
199
200 waitEvent->signal();
201 }
202
203 void runSimpleProcessTestOnWorkletThread(WorkerThread* thread,
204 WaitableEvent* waitEvent) {
205 EXPECT_TRUE(thread->isCurrentThread());
206
207 AudioWorkletGlobalScope* globalScope =
208 static_cast<AudioWorkletGlobalScope*>(thread->globalScope());
209 ScriptState* scriptState =
210 globalScope->scriptController()->getScriptState();
211
212 ScriptState::Scope scope(scriptState);
213
214 globalScope->scriptController()->evaluate(ScriptSourceCode(
215 R"JS(
216 registerProcessor('testProcessor', class {
217 constructor () {
218 this.constant = 1;
219 }
220 process (input, output) {
221 let inputChannelData = input.getChannelData(0);
222 let outputChannelData = output.getChannelData(0);
223 for (let i = 0; i < input.length; ++i) {
224 outputChannelData[i] = inputChannelData[i] + this.constant;
225 }
226 }
227 }
228 )
229 )JS"));
230
231 AudioWorkletProcessor* processor =
232 globalScope->createInstance("testProcessor");
233 EXPECT_TRUE(processor);
234
235 AudioBuffer* inputBuffer =
236 AudioBuffer::create(1, kRenderQuantumFrames, kTestingSampleRate);
237 AudioBuffer* outputBuffer =
238 AudioBuffer::create(1, kRenderQuantumFrames, kTestingSampleRate);
239 DOMFloat32Array* inputChannelData = inputBuffer->getChannelData(0);
240 float* inputArrayData = inputChannelData->data();
241 EXPECT_TRUE(inputArrayData);
242 DOMFloat32Array* outputChannelData = outputBuffer->getChannelData(0);
243 float* outputArrayData = outputChannelData->data();
244 EXPECT_TRUE(outputArrayData);
245
246 // Fill |inputBuffer| with 1 and zero out |outputBuffer|.
247 std::fill(inputArrayData, inputArrayData + inputBuffer->length(), 1);
248 outputBuffer->zero();
249
250 // Then invoke the process() method to perform JS buffer manipulation. The
251 // output buffer should contain a constant value of 2.
252 processor->process(inputBuffer, outputBuffer);
253 for (unsigned i = 0; i < outputBuffer->length(); ++i) {
254 EXPECT_EQ(outputArrayData[i], 2);
255 }
256
257 waitEvent->signal();
258 }
259
260 RefPtr<SecurityOrigin> m_securityOrigin;
261 std::unique_ptr<WorkerReportingProxy> m_reportingProxy;
262 };
263
264 TEST_F(AudioWorkletGlobalScopeTest, Basic) {
265 std::unique_ptr<AudioWorkletThread> thread = createAudioWorkletThread();
266 runBasicTest(thread.get());
267 thread->terminateAndWait();
268 }
269
270 TEST_F(AudioWorkletGlobalScopeTest, Parsing) {
271 std::unique_ptr<AudioWorkletThread> thread = createAudioWorkletThread();
272 runParsingTest(thread.get());
273 thread->terminateAndWait();
274 }
275
276 TEST_F(AudioWorkletGlobalScopeTest, BufferProcessing) {
277 std::unique_ptr<AudioWorkletThread> thread = createAudioWorkletThread();
278 runSimpleProcessTest(thread.get());
279 thread->terminateAndWait();
280 }
281
282 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698