diff options
author | primiano@chromium.org <primiano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-13 13:06:39 +0000 |
---|---|---|
committer | primiano@chromium.org <primiano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-13 13:06:39 +0000 |
commit | 2ba0644d32705803938d2022562d2e42e5ac7615 (patch) | |
tree | ab1a3973ce11d8fcb5855b89c6287dfd9eb66230 /content/browser/speech/speech_recognizer_impl_unittest.cc | |
parent | 0d2dafb39d52717a30631e7104a9c60fa6b0e57b (diff) | |
download | chromium_src-2ba0644d32705803938d2022562d2e42e5ac7615.zip chromium_src-2ba0644d32705803938d2022562d2e42e5ac7615.tar.gz chromium_src-2ba0644d32705803938d2022562d2e42e5ac7615.tar.bz2 |
Speech refactoring: Reimplemented speech_recognizer as a FSM (CL1.5)
BUG=116954
TEST=none
Review URL: http://codereview.chromium.org/9835049
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132179 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/speech/speech_recognizer_impl_unittest.cc')
-rw-r--r-- | content/browser/speech/speech_recognizer_impl_unittest.cc | 137 |
1 files changed, 103 insertions, 34 deletions
diff --git a/content/browser/speech/speech_recognizer_impl_unittest.cc b/content/browser/speech/speech_recognizer_impl_unittest.cc index 01b7e4c..5dbe6cc 100644 --- a/content/browser/speech/speech_recognizer_impl_unittest.cc +++ b/content/browser/speech/speech_recognizer_impl_unittest.cc @@ -17,6 +17,7 @@ #include "net/url_request/url_request_status.h" #include "testing/gtest/include/gtest/gtest.h" +using base::MessageLoopProxy; using content::BrowserThread; using content::BrowserThreadImpl; using media::AudioInputController; @@ -97,16 +98,28 @@ class SpeechRecognizerImplTest : public content::SpeechRecognitionEventListener, SpeechRecognizerImplTest() : io_thread_(BrowserThread::IO, &message_loop_), audio_manager_(new MockAudioManager()), - audio_ended_(false), + recognition_started_(false), recognition_ended_(false), result_received_(false), audio_started_(false), + audio_ended_(false), + sound_started_(false), + sound_ended_(false), error_(content::SPEECH_RECOGNITION_ERROR_NONE), volume_(-1.0f) { - recognizer_ = new SpeechRecognizerImpl( - this, 1, std::string(), std::string(), NULL, false, std::string(), - std::string()); + // SpeechRecognizerImpl takes ownership of sr_engine. + GoogleOneShotRemoteEngine* sr_engine = + new GoogleOneShotRemoteEngine(NULL /* URLRequestContextGetter */); + GoogleOneShotRemoteEngineConfig config; + config.audio_num_bits_per_sample = + SpeechRecognizerImpl::kNumBitsPerAudioSample; + config.audio_sample_rate = SpeechRecognizerImpl::kAudioSampleRate; + config.filter_profanities = false; + sr_engine->SetConfig(config); + + recognizer_ = new SpeechRecognizerImpl(this, 1, sr_engine); recognizer_->SetAudioManagerForTesting(audio_manager_.get()); + int audio_packet_length_bytes = (SpeechRecognizerImpl::kAudioSampleRate * GoogleOneShotRemoteEngine::kAudioPacketIntervalMs * @@ -115,13 +128,33 @@ class SpeechRecognizerImplTest : public content::SpeechRecognitionEventListener, audio_packet_.resize(audio_packet_length_bytes); } + void CheckEventsConsistency() { + // Note: "!x || y" == "x implies y". + EXPECT_TRUE(!recognition_ended_ || recognition_started_); + EXPECT_TRUE(!audio_ended_ || audio_started_); + EXPECT_TRUE(!sound_ended_ || sound_started_); + EXPECT_TRUE(!audio_started_ || recognition_started_); + EXPECT_TRUE(!sound_started_ || audio_started_); + EXPECT_TRUE(!audio_ended_ || (sound_ended_ || !sound_started_)); + EXPECT_TRUE(!recognition_ended_ || (audio_ended_ || !audio_started_)); + } + + void CheckFinalEventsConsistency() { + // Note: "!(x ^ y)" == "(x && y) || (!x && !x)". + EXPECT_FALSE(recognition_started_ ^ recognition_ended_); + EXPECT_FALSE(audio_started_ ^ audio_ended_); + EXPECT_FALSE(sound_started_ ^ sound_ended_); + } + // Overridden from content::SpeechRecognitionEventListener: virtual void OnAudioStart(int caller_id) OVERRIDE { audio_started_ = true; + CheckEventsConsistency(); } virtual void OnAudioEnd(int caller_id) OVERRIDE { audio_ended_ = true; + CheckEventsConsistency(); } virtual void OnRecognitionResult( @@ -130,8 +163,9 @@ class SpeechRecognizerImplTest : public content::SpeechRecognitionEventListener, } virtual void OnRecognitionError( - int caller_id, - const content::SpeechRecognitionError& error) OVERRIDE { + int caller_id, const content::SpeechRecognitionError& error) OVERRIDE { + EXPECT_TRUE(recognition_started_); + EXPECT_FALSE(recognition_ended_); error_ = error.code; } @@ -143,12 +177,25 @@ class SpeechRecognizerImplTest : public content::SpeechRecognitionEventListener, virtual void OnRecognitionEnd(int caller_id) OVERRIDE { recognition_ended_ = true; + CheckEventsConsistency(); + } + + virtual void OnRecognitionStart(int caller_id) OVERRIDE { + recognition_started_ = true; + CheckEventsConsistency(); } - virtual void OnRecognitionStart(int caller_id) OVERRIDE {} virtual void OnEnvironmentEstimationComplete(int caller_id) OVERRIDE {} - virtual void OnSoundStart(int caller_id) OVERRIDE {} - virtual void OnSoundEnd(int caller_id) OVERRIDE {} + + virtual void OnSoundStart(int caller_id) OVERRIDE { + sound_started_ = true; + CheckEventsConsistency(); + } + + virtual void OnSoundEnd(int caller_id) OVERRIDE { + sound_ended_ = true; + CheckEventsConsistency(); + } // testing::Test methods. virtual void SetUp() OVERRIDE { @@ -180,10 +227,13 @@ class SpeechRecognizerImplTest : public content::SpeechRecognitionEventListener, BrowserThreadImpl io_thread_; scoped_refptr<SpeechRecognizerImpl> recognizer_; scoped_ptr<AudioManager> audio_manager_; - bool audio_ended_; + bool recognition_started_; bool recognition_ended_; bool result_received_; bool audio_started_; + bool audio_ended_; + bool sound_started_; + bool sound_ended_; content::SpeechRecognitionErrorCode error_; TestURLFetcherFactory url_fetcher_factory_; TestAudioInputControllerFactory audio_input_controller_factory_; @@ -196,11 +246,12 @@ TEST_F(SpeechRecognizerImplTest, StopNoData) { // Check for callbacks when stopping record before any audio gets recorded. recognizer_->StartRecognition(); recognizer_->AbortRecognition(); - EXPECT_FALSE(audio_ended_); - EXPECT_FALSE(recognition_ended_); - EXPECT_FALSE(result_received_); + MessageLoop::current()->RunAllPending(); + EXPECT_TRUE(recognition_started_); EXPECT_FALSE(audio_started_); + EXPECT_FALSE(result_received_); EXPECT_EQ(content::SPEECH_RECOGNITION_ERROR_NONE, error_); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, CancelNoData) { @@ -208,17 +259,19 @@ TEST_F(SpeechRecognizerImplTest, CancelNoData) { // recorded. recognizer_->StartRecognition(); recognizer_->StopAudioCapture(); - EXPECT_TRUE(audio_ended_); - EXPECT_TRUE(recognition_ended_); - EXPECT_FALSE(result_received_); + MessageLoop::current()->RunAllPending(); + EXPECT_TRUE(recognition_started_); EXPECT_FALSE(audio_started_); + EXPECT_FALSE(result_received_); EXPECT_EQ(content::SPEECH_RECOGNITION_ERROR_NONE, error_); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, StopWithData) { // Start recording, give some data and then stop. This should wait for the // network callback to arrive before completion. recognizer_->StartRecognition(); + MessageLoop::current()->RunAllPending(); TestAudioInputController* controller = audio_input_controller_factory_.controller(); ASSERT_TRUE(controller); @@ -238,6 +291,7 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) { } recognizer_->StopAudioCapture(); + MessageLoop::current()->RunAllPending(); EXPECT_TRUE(audio_started_); EXPECT_TRUE(audio_ended_); EXPECT_FALSE(recognition_ended_); @@ -256,16 +310,17 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) { fetcher->SetResponseString( "{\"status\":0,\"hypotheses\":[{\"utterance\":\"123\"}]}"); fetcher->delegate()->OnURLFetchComplete(fetcher); - + MessageLoop::current()->RunAllPending(); EXPECT_TRUE(recognition_ended_); EXPECT_TRUE(result_received_); EXPECT_EQ(content::SPEECH_RECOGNITION_ERROR_NONE, error_); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, CancelWithData) { - // Start recording, give some data and then cancel. This should create - // a network request but give no callbacks. + // Start recording, give some data and then cancel. recognizer_->StartRecognition(); + MessageLoop::current()->RunAllPending(); TestAudioInputController* controller = audio_input_controller_factory_.controller(); ASSERT_TRUE(controller); @@ -273,18 +328,20 @@ TEST_F(SpeechRecognizerImplTest, CancelWithData) { audio_packet_.size()); MessageLoop::current()->RunAllPending(); recognizer_->AbortRecognition(); + MessageLoop::current()->RunAllPending(); ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0)); + EXPECT_TRUE(recognition_started_); EXPECT_TRUE(audio_started_); - EXPECT_FALSE(audio_ended_); - EXPECT_FALSE(recognition_ended_); EXPECT_FALSE(result_received_); EXPECT_EQ(content::SPEECH_RECOGNITION_ERROR_NONE, error_); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, ConnectionError) { // Start recording, give some data and then stop. Issue the network callback // with a connection error and verify that the recognizer bubbles the error up recognizer_->StartRecognition(); + MessageLoop::current()->RunAllPending(); TestAudioInputController* controller = audio_input_controller_factory_.controller(); ASSERT_TRUE(controller); @@ -295,6 +352,7 @@ TEST_F(SpeechRecognizerImplTest, ConnectionError) { ASSERT_TRUE(fetcher); recognizer_->StopAudioCapture(); + MessageLoop::current()->RunAllPending(); EXPECT_TRUE(audio_started_); EXPECT_TRUE(audio_ended_); EXPECT_FALSE(recognition_ended_); @@ -310,16 +368,18 @@ TEST_F(SpeechRecognizerImplTest, ConnectionError) { fetcher->set_response_code(0); fetcher->SetResponseString(""); fetcher->delegate()->OnURLFetchComplete(fetcher); - - EXPECT_FALSE(recognition_ended_); + MessageLoop::current()->RunAllPending(); + EXPECT_TRUE(recognition_ended_); EXPECT_FALSE(result_received_); EXPECT_EQ(content::SPEECH_RECOGNITION_ERROR_NETWORK, error_); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, ServerError) { // Start recording, give some data and then stop. Issue the network callback // with a 500 error and verify that the recognizer bubbles the error up recognizer_->StartRecognition(); + MessageLoop::current()->RunAllPending(); TestAudioInputController* controller = audio_input_controller_factory_.controller(); ASSERT_TRUE(controller); @@ -330,6 +390,7 @@ TEST_F(SpeechRecognizerImplTest, ServerError) { ASSERT_TRUE(fetcher); recognizer_->StopAudioCapture(); + MessageLoop::current()->RunAllPending(); EXPECT_TRUE(audio_started_); EXPECT_TRUE(audio_ended_); EXPECT_FALSE(recognition_ended_); @@ -344,31 +405,34 @@ TEST_F(SpeechRecognizerImplTest, ServerError) { fetcher->set_response_code(500); fetcher->SetResponseString("Internal Server Error"); fetcher->delegate()->OnURLFetchComplete(fetcher); - - EXPECT_FALSE(recognition_ended_); + MessageLoop::current()->RunAllPending(); + EXPECT_TRUE(recognition_ended_); EXPECT_FALSE(result_received_); EXPECT_EQ(content::SPEECH_RECOGNITION_ERROR_NETWORK, error_); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, AudioControllerErrorNoData) { // Check if things tear down properly if AudioInputController threw an error. recognizer_->StartRecognition(); + MessageLoop::current()->RunAllPending(); TestAudioInputController* controller = audio_input_controller_factory_.controller(); ASSERT_TRUE(controller); controller->event_handler()->OnError(controller, 0); MessageLoop::current()->RunAllPending(); + EXPECT_TRUE(recognition_started_); EXPECT_FALSE(audio_started_); - EXPECT_FALSE(audio_ended_); - EXPECT_FALSE(recognition_ended_); EXPECT_FALSE(result_received_); EXPECT_EQ(content::SPEECH_RECOGNITION_ERROR_AUDIO, error_); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, AudioControllerErrorWithData) { // Check if things tear down properly if AudioInputController threw an error // after giving some audio data. recognizer_->StartRecognition(); + MessageLoop::current()->RunAllPending(); TestAudioInputController* controller = audio_input_controller_factory_.controller(); ASSERT_TRUE(controller); @@ -377,36 +441,35 @@ TEST_F(SpeechRecognizerImplTest, AudioControllerErrorWithData) { controller->event_handler()->OnError(controller, 0); MessageLoop::current()->RunAllPending(); ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0)); + EXPECT_TRUE(recognition_started_); EXPECT_TRUE(audio_started_); - EXPECT_FALSE(audio_ended_); - EXPECT_FALSE(recognition_ended_); EXPECT_FALSE(result_received_); EXPECT_EQ(content::SPEECH_RECOGNITION_ERROR_AUDIO, error_); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackIssued) { // Start recording and give a lot of packets with audio samples set to zero. // This should trigger the no-speech detector and issue a callback. recognizer_->StartRecognition(); + MessageLoop::current()->RunAllPending(); TestAudioInputController* controller = audio_input_controller_factory_.controller(); ASSERT_TRUE(controller); - controller = audio_input_controller_factory_.controller(); - ASSERT_TRUE(controller); int num_packets = (SpeechRecognizerImpl::kNoSpeechTimeoutMs) / - GoogleOneShotRemoteEngine::kAudioPacketIntervalMs; + GoogleOneShotRemoteEngine::kAudioPacketIntervalMs + 1; // The vector is already filled with zero value samples on create. for (int i = 0; i < num_packets; ++i) { controller->event_handler()->OnData(controller, &audio_packet_[0], audio_packet_.size()); } MessageLoop::current()->RunAllPending(); + EXPECT_TRUE(recognition_started_); EXPECT_TRUE(audio_started_); - EXPECT_FALSE(audio_ended_); - EXPECT_FALSE(recognition_ended_); EXPECT_FALSE(result_received_); EXPECT_EQ(content::SPEECH_RECOGNITION_ERROR_NO_SPEECH, error_); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackNotIssued) { @@ -415,6 +478,7 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackNotIssued) { // treated as normal speech input and the no-speech detector should not get // triggered. recognizer_->StartRecognition(); + MessageLoop::current()->RunAllPending(); TestAudioInputController* controller = audio_input_controller_factory_.controller(); ASSERT_TRUE(controller); @@ -442,6 +506,8 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackNotIssued) { EXPECT_FALSE(audio_ended_); EXPECT_FALSE(recognition_ended_); recognizer_->AbortRecognition(); + MessageLoop::current()->RunAllPending(); + CheckFinalEventsConsistency(); } TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) { @@ -450,6 +516,7 @@ TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) { // get the callback during estimation phase, then get zero for the silence // samples and proper volume for the loud audio. recognizer_->StartRecognition(); + MessageLoop::current()->RunAllPending(); TestAudioInputController* controller = audio_input_controller_factory_.controller(); ASSERT_TRUE(controller); @@ -484,6 +551,8 @@ TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) { EXPECT_FALSE(audio_ended_); EXPECT_FALSE(recognition_ended_); recognizer_->AbortRecognition(); + MessageLoop::current()->RunAllPending(); + CheckFinalEventsConsistency(); } } // namespace speech |