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

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

Issue 2675713002: Switch Speech Recognition to asynchronous callback-based AudioManager interactions. (Closed)
Patch Set: review comments addressed Created 3 years, 10 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: content/browser/speech/speech_recognizer_impl_unittest.cc
diff --git a/content/browser/speech/speech_recognizer_impl_unittest.cc b/content/browser/speech/speech_recognizer_impl_unittest.cc
index 80b94bc95cb772e8a9aa0e18dfdf8a92c4592e3d..2240fddc035dd9bd799068c5007a94d4b7213fdc 100644
--- a/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -8,7 +8,9 @@
#include <vector>
#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
#include "base/sys_byteorder.h"
+#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/speech/proto/google_streaming_api.pb.h"
#include "content/browser/speech/speech_recognition_engine.h"
@@ -16,11 +18,13 @@
#include "content/public/browser/speech_recognition_event_listener.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_system_impl.h"
#include "media/audio/fake_audio_input_stream.h"
#include "media/audio/fake_audio_output_stream.h"
#include "media/audio/mock_audio_manager.h"
#include "media/audio/test_audio_input_controller_factory.h"
#include "media/base/audio_bus.h"
+#include "media/base/test_helpers.h"
#include "net/base/net_errors.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_status.h"
@@ -39,7 +43,8 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
public testing::Test {
public:
SpeechRecognizerImplTest()
- : recognition_started_(false),
+ : audio_thread_("SpeechAudioThread"),
+ recognition_started_(false),
recognition_ended_(false),
result_received_(false),
audio_started_(false),
@@ -59,11 +64,15 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
sr_engine->SetConfig(config);
const int kTestingSessionId = 1;
- recognizer_ = new SpeechRecognizerImpl(
- this, kTestingSessionId, false, false, sr_engine);
+
+ audio_thread_.StartAndWaitForTesting();
audio_manager_.reset(
- new media::MockAudioManager(base::ThreadTaskRunnerHandle::Get().get()));
- recognizer_->SetAudioManagerForTesting(audio_manager_.get());
+ new media::MockAudioManager(audio_thread_.task_runner()));
+ audio_manager_->SetInputStreamParameters(
+ media::AudioParameters::UnavailableDeviceParams());
+ audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get());
+ recognizer_ = new SpeechRecognizerImpl(
+ this, audio_system_.get(), kTestingSessionId, false, false, sr_engine);
int audio_packet_length_bytes =
(SpeechRecognizerImpl::kAudioSampleRate *
@@ -80,6 +89,12 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
audio_bus_->Zero();
}
+ ~SpeechRecognizerImplTest() override {
+ // Deleting |audio_manager_| on audio thread.
+ audio_manager_.reset();
+ audio_thread_.Stop();
+ }
+
void CheckEventsConsistency() {
// Note: "!x || y" == "x implies y".
EXPECT_TRUE(!recognition_ended_ || recognition_started_);
@@ -189,10 +204,22 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
writer->Write(data, 0.0, false, 0);
}
+ void WaitForAudioThreadToPostDeviceInfo() {
+ media::WaitableMessageLoopEvent event;
+ audio_thread_.task_runner()->PostTaskAndReply(
+ FROM_HERE, base::Bind(&base::DoNothing), event.GetClosure());
+ // Runs the loop and waits for the |audio_thread_| to call event's closure,
+ // which means AudioSystem reply containing device parameters is already
+ // queued on the main thread.
+ event.RunAndWait();
+ }
+
protected:
TestBrowserThreadBundle thread_bundle_;
scoped_refptr<SpeechRecognizerImpl> recognizer_;
- media::ScopedAudioManagerPtr audio_manager_;
+ base::Thread audio_thread_;
+ media::MockAudioManager::UniquePtr audio_manager_;
+ std::unique_ptr<media::AudioSystem> audio_system_;
bool recognition_started_;
bool recognition_ended_;
bool result_received_;
@@ -210,10 +237,81 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
float noise_volume_;
};
+TEST_F(SpeechRecognizerImplTest, StartNoInputDevices) {
+ // Check for callbacks when stopping record before any audio gets recorded.
+ audio_manager_->SetHasInputDevices(false);
+ recognizer_->StartRecognition(
+ media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(recognition_started_);
+ EXPECT_FALSE(audio_started_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE, error_);
+ CheckFinalEventsConsistency();
+}
+
+TEST_F(SpeechRecognizerImplTest, StopBeforeDeviceInfoReceived) {
+ // Check for callbacks when stopping record before reply is received from
+ // AudioSystem.
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ // Block audio thread.
+ audio_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&base::WaitableEvent::Wait, base::Unretained(&event)));
+
+ recognizer_->StartRecognition(
+ media::AudioDeviceDescription::kDefaultDeviceId);
+ recognizer_->StopAudioCapture();
+ base::RunLoop().RunUntilIdle();
+
+ // Release audio thread and receive a callback from it.
+ event.Signal();
+ WaitForAudioThreadToPostDeviceInfo();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(recognition_started_);
+ EXPECT_FALSE(audio_started_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ CheckFinalEventsConsistency();
+}
+
+TEST_F(SpeechRecognizerImplTest, CancelBeforeDeviceInfoReceived) {
+ // Check for callbacks when stopping record before reply is received from
+ // AudioSystem.
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ // Block audio thread.
+ audio_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&base::WaitableEvent::Wait, base::Unretained(&event)));
+
+ recognizer_->StartRecognition(
+ media::AudioDeviceDescription::kDefaultDeviceId);
+ recognizer_->AbortRecognition();
+ base::RunLoop().RunUntilIdle();
+
+ // Release audio thread and receive a callback from it.
+ event.Signal();
+ WaitForAudioThreadToPostDeviceInfo();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(recognition_started_);
+ EXPECT_FALSE(audio_started_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ CheckFinalEventsConsistency();
+}
+
TEST_F(SpeechRecognizerImplTest, StopNoData) {
// Check for callbacks when stopping record before any audio gets recorded.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
recognizer_->StopAudioCapture();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_started_);
@@ -228,6 +326,7 @@ TEST_F(SpeechRecognizerImplTest, CancelNoData) {
// recorded.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
recognizer_->AbortRecognition();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_started_);
@@ -242,6 +341,7 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) {
// network callback to arrive before completion.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
@@ -304,6 +404,7 @@ TEST_F(SpeechRecognizerImplTest, CancelWithData) {
// Start recording, give some data and then cancel.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
@@ -325,6 +426,7 @@ TEST_F(SpeechRecognizerImplTest, ConnectionError) {
// with a connection error and verify that the recognizer bubbles the error up
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
@@ -361,6 +463,7 @@ TEST_F(SpeechRecognizerImplTest, ServerError) {
// with a 500 error and verify that the recognizer bubbles the error up
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
@@ -395,6 +498,7 @@ TEST_F(SpeechRecognizerImplTest, AudioControllerErrorNoData) {
// Check if things tear down properly if AudioInputController threw an error.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
@@ -414,6 +518,7 @@ TEST_F(SpeechRecognizerImplTest, AudioControllerErrorWithData) {
// after giving some audio data.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
@@ -435,6 +540,7 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackIssued) {
// This should trigger the no-speech detector and issue a callback.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
@@ -461,6 +567,7 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackNotIssued) {
// triggered.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
@@ -498,6 +605,7 @@ TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) {
// samples and proper volume for the loud audio.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
+ WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();

Powered by Google App Engine
This is Rietveld 408576698