Index: third_party/WebKit/Source/platform/audio/PushPullFIFOSmokeTest.cpp |
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOSmokeTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOSmokeTest.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6bac179f8bf2f86cdf75f8b30bf674f443f2fff2 |
--- /dev/null |
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOSmokeTest.cpp |
@@ -0,0 +1,165 @@ |
+// 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 "platform/audio/PushPullFIFO.h" |
+ |
+#include <memory> |
+#include <vector> |
+#include "platform/CrossThreadFunctional.h" |
+#include "platform/WaitableEvent.h" |
+#include "platform/WebTaskRunner.h" |
+#include "platform/audio/AudioUtilities.h" |
+#include "platform/testing/UnitTestHelpers.h" |
+#include "platform/wtf/Functional.h" |
+#include "platform/wtf/PtrUtil.h" |
+#include "public/platform/Platform.h" |
+#include "public/platform/WebThread.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace blink { |
+ |
+namespace { |
+ |
+// To forcibly stop the message loop. |
+// TODO(hongchan): move this hack into Test class. |
+void FinishTest() { |
+ LOG(INFO) << "FinishTest"; |
+ testing::ExitRunLoop(); |
+} |
+ |
+// To wait for spawned threads to finish their tasks. |
+// TODO(hongchan): move this hack into Test class. |
+void HoldTestForDuration(double duration_ms) { |
+ LOG(INFO) << "HoldTestForDuration"; |
+ Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostDelayedTask( |
+ BLINK_FROM_HERE, |
+ WTF::Bind(&FinishTest), |
+ duration_ms); |
+ testing::EnterRunLoop(); |
+} |
+ |
+// Base FIFOClient with an extra thread for looping and jitter control. The |
+// child class must define a specific task to run on the thread. |
+class FIFOClient { |
+ public: |
+ FIFOClient(PushPullFIFO* fifo, size_t jitter_range_ms) |
+ : fifo_(fifo), |
+ jitter_range_ms_(jitter_range_ms), |
+ client_thread_(WTF::WrapUnique( |
+ Platform::Current()->CreateThread("client thread"))) {} |
+ |
+ void Start(double duration_ms, double interval_ms) { |
+ duration_ms_ = duration_ms; |
+ interval_ms_ = interval_ms; |
+ client_thread_->GetWebTaskRunner()->PostTask( |
+ BLINK_FROM_HERE, |
+ CrossThreadBind(&FIFOClient::RunTaskOnOwnThread, |
+ CrossThreadUnretained(this))); |
+ } |
+ |
+ virtual void RunTask() = 0; |
+ virtual void Stop() = 0; |
+ |
+ protected: |
+ RefPtr<AudioBus> bus_; |
+ PushPullFIFO* fifo_; |
+ double elapesd_ms_ = 0; |
+ |
+ private: |
+ void RunTaskOnOwnThread() { |
+ double interval_with_jitter = interval_ms_ |
+ + (static_cast<double>(std::rand()) / RAND_MAX) * jitter_range_ms_; |
Raymond Toy
2017/04/21 16:26:57
Maybe use std::uniform_real_distribution to genera
hongchan
2017/04/21 20:44:02
Hmm, I think the variable names quite accurate and
|
+ elapesd_ms_ += interval_with_jitter; |
Raymond Toy
2017/04/21 16:26:57
elapesd_ms should probably be elapsed_ms
hongchan
2017/04/21 20:44:01
Done.
|
+ RunTask(); |
+ if (elapesd_ms_ < duration_ms_) { |
+ client_thread_->GetWebTaskRunner()->PostDelayedTask( |
+ BLINK_FROM_HERE, |
+ CrossThreadBind(&FIFOClient::RunTaskOnOwnThread, |
+ CrossThreadUnretained(this)), |
+ interval_with_jitter); |
Raymond Toy
2017/04/21 16:26:57
The documentation for PostDelayedTask says the del
hongchan
2017/04/21 20:44:02
Not sure if it would matters for anything, but thi
|
+ } else { |
+ Stop(); |
+ } |
+ } |
+ |
+ double duration_ms_; |
+ double interval_ms_; |
+ double jitter_range_ms_; |
+ std::unique_ptr<WebThread> client_thread_; |
+}; |
+ |
+// FIFO-pulling client (consumer). This mimics the audio device thread. |
+class PullClient : public FIFOClient { |
+ public: |
+ PullClient(PushPullFIFO* fifo, size_t frames_to_pull, double jitter_range_ms) |
+ : FIFOClient(fifo, jitter_range_ms), |
+ frames_to_pull_(frames_to_pull) { |
+ bus_ = AudioBus::Create(fifo_->NumberOfChannels(), frames_to_pull_); |
+ } |
+ |
+ void RunTask() override { |
+ LOG(INFO) << "PullClient::RunTask (" << elapesd_ms_ << ")"; |
+ fifo_->Pull(bus_.Get(), frames_to_pull_); |
+ } |
+ |
+ void Stop() override { |
+ LOG(INFO) << "PullClient::Stop (" << elapesd_ms_ << ")"; |
+ } |
+ |
+ private: |
+ size_t frames_to_pull_; |
+}; |
+ |
+// FIFO-pushing client (producer). This mimics the WebAudio rendering thread. |
+class PushClient : public FIFOClient { |
+ public: |
+ PushClient(PushPullFIFO* fifo, size_t frames_to_push, double jitter_range_ms) |
+ : FIFOClient(fifo, jitter_range_ms) { |
+ bus_ = AudioBus::Create(fifo_->NumberOfChannels(), frames_to_push); |
+ } |
+ |
+ void RunTask() override { |
+ LOG(INFO) << "PushClient::RunTask (" << elapesd_ms_ << ")"; |
+ fifo_->Push(bus_.Get()); |
+ } |
+ |
+ void Stop() override { |
+ LOG(INFO) << "PushClient::Stop (" << elapesd_ms_ << ")"; |
+ } |
+}; |
+ |
+class PushPullFIFOSmokeTest : public ::testing::Test {}; |
+ |
+// TODO(hongchan): parameterize this sample test. |
+TEST_F(PushPullFIFOSmokeTest, SmokeTest) { |
+ const double sample_rate = 48000; |
+ const size_t fifo_length = 8192; |
+ const size_t pull_buffer_size = 1024; |
+ const double pull_interval_ms = pull_buffer_size / sample_rate * 1000; |
Raymond Toy
2017/04/21 16:26:57
pull_buffer_size / sample_rate * 1000 isn't exactl
hongchan
2017/04/21 20:44:02
As we discussed offline, this does not really matt
|
+ const double pull_jitter_range_ms = 5; |
Raymond Toy
2017/04/21 16:26:57
Why 5? Please comment on valid values and reason
hongchan
2017/04/21 20:44:02
Multiple test cases with various parameters were a
|
+ const size_t push_buffer_size = AudioUtilities::kRenderQuantumFrames; |
+ const double push_interval_ms = push_buffer_size / sample_rate * 1000; |
+ const double push_jitter_range_ms = 8; |
+ const unsigned number_of_channels = 2; |
+ |
+ const double test_duration_ms = 1000; |
Raymond Toy
2017/04/21 16:26:57
Is this long enough? I think this means that there
hongchan
2017/04/21 20:44:02
Multiple test cases with various parameters were a
|
+ |
+ std::unique_ptr<PushPullFIFO> test_fifo = |
+ WTF::WrapUnique(new PushPullFIFO(number_of_channels, fifo_length)); |
+ |
+ std::unique_ptr<PullClient> pull_client = WTF::WrapUnique( |
+ new PullClient(test_fifo.get(), pull_buffer_size, pull_jitter_range_ms)); |
+ std::unique_ptr<PushClient> push_client = WTF::WrapUnique( |
+ new PushClient(test_fifo.get(), push_buffer_size, push_jitter_range_ms)); |
+ |
+ pull_client->Start(test_duration_ms, pull_interval_ms); |
+ push_client->Start(test_duration_ms, push_interval_ms); |
+ |
+ // Give a bit more time for clients to finish the task. |
+ HoldTestForDuration(test_duration_ms + 250); |
+} |
+ |
+} // namespace |
+ |
+} // namespace blink |