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

Unified Diff: third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp

Issue 2727733002: Implement AudioWorkletProcessor interface (Closed)
Patch Set: Added AudioWorkletGlobalScopeTest.cpp 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9174f44c18a5c6f90ba916328089d935a2fde4cd
--- /dev/null
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
@@ -0,0 +1,217 @@
+// 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 "modules/webaudio/AudioWorkletGlobalScope.h"
+
+#include "bindings/core/v8/ScriptSourceCode.h"
+#include "bindings/core/v8/ScriptState.h"
+#include "bindings/core/v8/ScriptValue.h"
+#include "bindings/core/v8/SourceLocation.h"
+#include "bindings/core/v8/ToV8.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8BindingForTesting.h"
+#include "bindings/core/v8/V8BindingMacros.h"
+#include "bindings/core/v8/V8GCController.h"
+#include "bindings/core/v8/V8ObjectConstructor.h"
+#include "bindings/core/v8/WorkerOrWorkletScriptController.h"
+#include "core/workers/WorkerBackingThread.h"
+#include "core/workers/WorkerReportingProxy.h"
+#include "core/workers/WorkerThreadStartupData.h"
+#include "modules/webaudio/AudioBuffer.h"
+#include "modules/webaudio/AudioWorkletProcessor.h"
+#include "modules/webaudio/AudioWorkletProcessorDefinition.h"
+#include "modules/webaudio/AudioWorkletThread.h"
+#include "platform/weborigin/SecurityOrigin.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+namespace {
+
+// A null WorkerReportingProxy, supplied when creating AudioWorkletThreads.
+class TestAudioWorkletReportingProxy : public WorkerReportingProxy {
+ public:
+ static std::unique_ptr<TestAudioWorkletReportingProxy> create() {
+ return WTF::wrapUnique(new TestAudioWorkletReportingProxy());
+ }
+
+ // (Empty) WorkerReportingProxy implementation:
+ void countFeature(UseCounter::Feature) override {}
+ void countDeprecation(UseCounter::Feature) override {}
+ void reportException(const String& errorMessage,
+ std::unique_ptr<SourceLocation>,
+ int exceptionId) override {}
+ void reportConsoleMessage(MessageSource,
+ MessageLevel,
+ const String& message,
+ SourceLocation*) override {}
+ void postMessageToPageInspector(const String&) override {}
+ void didEvaluateWorkerScript(bool success) override {}
+ void didCloseWorkerGlobalScope() override {}
+ void willDestroyWorkerGlobalScope() override {}
+ void didTerminateWorkerThread() override {}
+
+ private:
+ TestAudioWorkletReportingProxy() {}
+};
+
+} // namespace
+
+class AudioWorkletGlobalScopeTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ AudioWorkletThread::createSharedBackingThreadForTest();
+ m_reportingProxy = TestAudioWorkletReportingProxy::create();
+ m_securityOrigin =
+ SecurityOrigin::create(KURL(ParsedURLString, "http://fake.url/"));
+ }
+
+ void TearDown() override { AudioWorkletThread::clearSharedBackingThread(); }
+
+ std::unique_ptr<AudioWorkletThread> createAudioWorkletThread() {
+ std::unique_ptr<AudioWorkletThread> thread =
+ AudioWorkletThread::create(nullptr, *m_reportingProxy);
+ thread->start(
+ WorkerThreadStartupData::create(
+ KURL(ParsedURLString, "http://fake.url/"), "fake user agent", "",
+ nullptr, DontPauseWorkerGlobalScopeOnStart, nullptr, "",
+ m_securityOrigin.get(), nullptr, WebAddressSpaceLocal, nullptr,
+ nullptr, WorkerV8Settings::Default()),
+ ParentFrameTaskRunners::create(nullptr));
+ return thread;
+ }
+
+ void runBasicTest(WorkerThread* thread) {
+ WaitableEvent waitableEvent;
+ thread->workerBackingThread().backingThread().postTask(
nhiroki 2017/03/16 00:21:35 Why don't we call thread->postTask()?
hongchan 2017/03/16 22:11:28 Done.
+ BLINK_FROM_HERE,
+ crossThreadBind(
+ &AudioWorkletGlobalScopeTest::runBasicTestOnWorkletThread,
+ crossThreadUnretained(this), crossThreadUnretained(thread),
+ crossThreadUnretained(&waitableEvent)));
+ waitableEvent.wait();
+ }
+
+ void runSimpleProcessTest(WorkerThread* thread) {
+ WaitableEvent waitableEvent;
+ thread->workerBackingThread().backingThread().postTask(
nhiroki 2017/03/16 00:21:35 ditto.
hongchan 2017/03/16 22:11:28 Done.
+ BLINK_FROM_HERE,
+ crossThreadBind(
+ &AudioWorkletGlobalScopeTest::runSimpleProcessTestOnWorkletThread,
+ crossThreadUnretained(this), crossThreadUnretained(thread),
+ crossThreadUnretained(&waitableEvent)));
+ waitableEvent.wait();
+ }
+
+ private:
+ void runBasicTestOnWorkletThread(WorkerThread* thread,
+ WaitableEvent* waitEvent) {
nhiroki 2017/03/16 00:21:35 EXPECT_TRUE(thread->isCurrentThread());
hongchan 2017/03/16 22:11:28 Done.
+ AudioWorkletGlobalScope* globalScope =
+ static_cast<AudioWorkletGlobalScope*>(thread->globalScope());
+ EXPECT_TRUE(globalScope);
+ EXPECT_TRUE(globalScope->isAudioWorkletGlobalScope());
+
+ ScriptState* scriptState =
+ globalScope->scriptController()->getScriptState();
+ EXPECT_TRUE(scriptState);
+
+ v8::Isolate* isolate = scriptState->isolate();
+ EXPECT_TRUE(isolate);
+
+ ScriptState::Scope scope(scriptState);
+
+ globalScope->scriptController()->evaluate(ScriptSourceCode(
+ R"JS(
+ registerProcessor('testProcessor', class {
+ constructor () {}
+ process () {}
+ });
+ )JS"));
+
+ AudioWorkletProcessorDefinition* definition =
+ globalScope->findDefinition("testProcessor");
+ EXPECT_TRUE(definition);
+ EXPECT_EQ(definition->name(), "testProcessor");
+ EXPECT_TRUE(definition->constructorLocal(isolate)->IsFunction());
+ EXPECT_TRUE(definition->processLocal(isolate)->IsFunction());
+
+ AudioWorkletProcessor* processor =
+ globalScope->createInstance("testProcessor");
+ EXPECT_TRUE(processor);
+ EXPECT_EQ(processor->name(), "testProcessor");
+ EXPECT_TRUE(processor->instanceLocal(isolate)->IsObject());
+
+ waitEvent->signal();
+ }
+
+ void runSimpleProcessTestOnWorkletThread(WorkerThread* thread,
+ WaitableEvent* waitEvent) {
nhiroki 2017/03/16 00:21:35 EXPECT_TRUE(thread->isCurrentThread());
hongchan 2017/03/16 22:11:28 Done.
+ AudioWorkletGlobalScope* globalScope =
+ static_cast<AudioWorkletGlobalScope*>(thread->globalScope());
+ ScriptState* scriptState =
+ globalScope->scriptController()->getScriptState();
+
+ ScriptState::Scope scope(scriptState);
+
+ globalScope->scriptController()->evaluate(ScriptSourceCode(
+ R"JS(
+ registerProcessor('foo', class {
+ constructor () {
+ this.constant = 1;
+ }
+ process (input, output) {
+ let inputChannelData = input.getChannelData(0);
+ let outputChannelData = output.getChannelData(0);
+ for (let i = 0; i < input.length; ++i) {
+ outputChannelData[i] = inputChannelData[i] + this.constant;
+ }
+ }
+ }
+ )
+ )JS"));
+
+ AudioWorkletProcessor* processor = globalScope->createInstance("foo");
+ EXPECT_TRUE(processor);
+
+ // Set the buffer length to 128. (= WebAudio's render quantum size)
nhiroki 2017/03/16 00:21:35 For readability and maintainability, how about def
hongchan 2017/03/16 22:11:28 Done.
+ AudioBuffer* inputBuffer = AudioBuffer::create(1, 128, 44100);
+ AudioBuffer* outputBuffer = AudioBuffer::create(1, 128, 44100);
+ DOMFloat32Array* inputChannelData = inputBuffer->getChannelData(0);
+ float* inputArrayData = inputChannelData->data();
+ EXPECT_TRUE(inputArrayData);
+ DOMFloat32Array* outputChannelData = outputBuffer->getChannelData(0);
+ float* outputArrayData = outputChannelData->data();
+ EXPECT_TRUE(outputArrayData);
+
+ // Fill |inputBuffer| with 1 and zero out |outputBuffer|.
+ std::fill(inputArrayData, inputArrayData + inputBuffer->length(), 1);
+ outputBuffer->zero();
+
+ // Then invoke the process() method to perform JS buffer manipulation. The
+ // output buffer should contain a constant value of 2.
+ processor->process(inputBuffer, outputBuffer);
+ for (unsigned i = 0; i < outputBuffer->length(); ++i) {
+ EXPECT_EQ(outputArrayData[i], 2);
+ }
+
+ waitEvent->signal();
+ }
+
+ RefPtr<SecurityOrigin> m_securityOrigin;
+ std::unique_ptr<WorkerReportingProxy> m_reportingProxy;
+};
+
+TEST_F(AudioWorkletGlobalScopeTest, Basic) {
+ std::unique_ptr<AudioWorkletThread> thread = createAudioWorkletThread();
+ runBasicTest(thread.get());
+ thread->terminateAndWait();
+}
+
+TEST_F(AudioWorkletGlobalScopeTest, BufferProcessing) {
+ std::unique_ptr<AudioWorkletThread> thread = createAudioWorkletThread();
+ runSimpleProcessTest(thread.get());
+ thread->terminateAndWait();
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698