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

Unified Diff: content/browser/speech/speech_recognition_audio_receiver_unittest.cc

Issue 549373003: Binding media stream audio track to speech recognition [browser] Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Wait with no timeout Created 6 years, 1 month 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: content/browser/speech/speech_recognition_audio_receiver_unittest.cc
diff --git a/content/browser/speech/speech_recognition_audio_receiver_unittest.cc b/content/browser/speech/speech_recognition_audio_receiver_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a0ea0f97bc22e1a89e0a426cb1ca4590103f78e8
--- /dev/null
+++ b/content/browser/speech/speech_recognition_audio_receiver_unittest.cc
@@ -0,0 +1,168 @@
+// Copyright 2014 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 "base/bind.h"
+#include "base/memory/shared_memory.h"
+#include "base/message_loop/message_loop.h"
+#include "base/process/process_handle.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/speech/speech_recognition_audio_receiver.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_bus.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace content {
+
+namespace {
+
+// Used to terminate a loop from a different thread than the loop belongs to.
+// |loop| should be a MessageLoopProxy.
+ACTION_P(QuitLoop, loop) {
+ loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
+}
+
+void SendIndexViaSocket(base::SyncSocket* socket, uint32 index) {
+ size_t bytes_sent = socket->Send(&index, sizeof(index));
+ EXPECT_EQ(bytes_sent, sizeof(index));
+}
+
+class MockEventHandler : public media::AudioInputController::EventHandler {
+ public:
+ MockEventHandler() {}
+ virtual ~MockEventHandler() {}
+
+ MOCK_METHOD1(OnCreated, void(media::AudioInputController* controller));
+ MOCK_METHOD1(OnRecording, void(media::AudioInputController* controller));
+ MOCK_METHOD2(OnLog, void(media::AudioInputController* controller,
+ const std::string& message));
+ MOCK_METHOD2(OnError, void(media::AudioInputController* controller,
+ media::AudioInputController::ErrorCode error));
+ MOCK_METHOD2(OnData, void(media::AudioInputController* controller,
+ const media::AudioBus* data));
+};
+
+} // namespace
+
+class SpeechRecognitionAudioReceiverTest : public testing::Test {
+ public:
+ SpeechRecognitionAudioReceiverTest()
+ : io_thread_(BrowserThread::IO, &io_loop_),
+ audio_thread_("AudioReceiverThread") {
+ audio_thread_.Start();
+
+ media::AudioParameters audio_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO,
+ 16000, 16, 1600);
+ base::SharedMemoryHandle foreign_memory_handle;
+ base::SyncSocket::TransitDescriptor foreign_socket_descriptor;
+ receiver_ = SpeechRecognitionAudioReceiver::Create(
+ audio_params, base::GetCurrentProcessHandle(), &event_handler_,
+ audio_thread_.task_runner().get(),
+ &foreign_memory_handle, &foreign_socket_descriptor);
+ DCHECK(receiver_.get());
+
+ // Create a send socket.
+ send_socket_.reset(new base::CancelableSyncSocket(
+ base::SyncSocket::UnwrapHandle(foreign_socket_descriptor)));
+
+ // Get the shared memory.
+ shared_memory_.reset(new base::SharedMemory(foreign_memory_handle, false));
+ const size_t memory_length =
+ media::AudioBus::CalculateMemorySize(audio_params) +
+ sizeof(media::AudioInputBufferParameters);
+ DCHECK(shared_memory_->Map(memory_length));
+
+ // Peer's buffer index is accessed via |params.size| in shared memory.
+ uint8* ptr = static_cast<uint8*>(shared_memory_->memory());
+ media::AudioInputBuffer* buffer =
+ reinterpret_cast<media::AudioInputBuffer*>(ptr);
+ peer_buffer_index_ = &(buffer->params.size);
+
+ // The peer must manage their own counter and reset it.
+ //ASSERT_EQ(0U, *peer_buffer_index_);
+ output_bus_ = media::AudioBus::WrapMemory(audio_params, buffer->audio);
+
+ // Start the receiver.
+ EXPECT_CALL(event_handler_, OnRecording(NULL))
+ .WillOnce(QuitLoop(io_loop()));
+ receiver_->StartListening();
+ WaitUntilCallback();
+ }
+
+ virtual ~SpeechRecognitionAudioReceiverTest() {
+ }
+
+ protected:
+ // Each test case needs to Stop() before quiting.
+ void Stop() {
+ ASSERT_EQ(io_loop(), base::MessageLoop::current());
+ receiver_->Stop();
+ const bool previous_io_allowed =
+ base::ThreadRestrictions::SetIOAllowed(true);
+ audio_thread_.Stop();
+ base::ThreadRestrictions::SetIOAllowed(previous_io_allowed);
+ }
+
+ void WaitUntilCallback() {
+ // Don't hang the test if we never get the Render() callback.
+ io_loop()->PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
+ TestTimeouts::action_timeout());
+ io_loop()->Run();
+ }
+
+ base::MessageLoopForIO* io_loop() { return &io_loop_; }
+ base::MessageLoop* audio_loop() { return audio_thread_.message_loop(); }
+
+ base::MessageLoopForIO io_loop_;
+ BrowserThreadImpl io_thread_;
+ MockEventHandler event_handler_;
+ scoped_ptr<base::CancelableSyncSocket> send_socket_;
+
+ private:
+ uint32 peer_buffer_index() { return *peer_buffer_index_; }
+
+ base::Thread audio_thread_;
+ scoped_ptr<SpeechRecognitionAudioReceiver> receiver_;
+ scoped_ptr<base::SharedMemory> shared_memory_;
+ scoped_ptr<media::AudioBus> output_bus_;
+ uint32* peer_buffer_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionAudioReceiverTest);
+};
+
+TEST_F(SpeechRecognitionAudioReceiverTest, CreateAndStop) {
+ // Objects are created, initialized, and stopped.
+ Stop();
+};
+
+TEST_F(SpeechRecognitionAudioReceiverTest, VerifyDataFlow) {
+ int index = 1;
+ EXPECT_CALL(event_handler_, OnData(NULL, _))
+ .WillOnce(QuitLoop(io_loop()));
+ SendIndexViaSocket(send_socket_.get(), index);
+ WaitUntilCallback();
+ Stop();
+};
+
+TEST_F(SpeechRecognitionAudioReceiverTest, SocketClosingTriggersError) {
+ EXPECT_CALL(event_handler_, OnData(NULL, _))
+ .Times(testing::AtMost(1));
+ EXPECT_CALL(event_handler_, OnError(NULL, _))
+ .WillOnce(QuitLoop(io_loop()));
+ SendIndexViaSocket(send_socket_.get(), 0U);
+ send_socket_->Shutdown();
+ WaitUntilCallback();
+ Stop();
+};
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698