190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_thread_impl.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/speech/google_one_shot_remote_engine.h" 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/browser/speech/speech_recognizer_impl.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/speech_recognition_event_listener.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "media/audio/audio_manager_base.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/fake_audio_input_stream.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/fake_audio_output_stream.h" 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "media/audio/mock_audio_manager.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/test_audio_input_controller_factory.h" 166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "media/base/audio_bus.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/test_url_fetcher_factory.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::MessageLoopProxy; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::AudioInputController; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::AudioInputStream; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::AudioManager; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::AudioOutputStream; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::AudioParameters; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::TestAudioInputController; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::TestAudioInputControllerFactory; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class SpeechRecognizerImplTest : public SpeechRecognitionEventListener, 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public testing::Test { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpeechRecognizerImplTest() 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : io_thread_(BrowserThread::IO, &message_loop_), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognition_started_(false), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognition_ended_(false), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_received_(false), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_started_(false), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_ended_(false), 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sound_started_(false), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sound_ended_(false), 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_(SPEECH_RECOGNITION_ERROR_NONE), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) volume_(-1.0f) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SpeechRecognizer takes ownership of sr_engine. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpeechRecognitionEngine* sr_engine = 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new GoogleOneShotRemoteEngine(NULL /* URLRequestContextGetter */); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpeechRecognitionEngineConfig config; 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) config.audio_num_bits_per_sample = 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpeechRecognizerImpl::kNumBitsPerAudioSample; 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) config.audio_sample_rate = SpeechRecognizerImpl::kAudioSampleRate; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config.filter_profanities = false; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sr_engine->SetConfig(config); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kTestingSessionId = 1; 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) recognizer_ = new SpeechRecognizerImpl( 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, kTestingSessionId, false, false, sr_engine); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_manager_.reset(new media::MockAudioManager( 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::MessageLoop::current()->message_loop_proxy().get())); 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) recognizer_->SetAudioManagerForTesting(audio_manager_.get()); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int audio_packet_length_bytes = 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (SpeechRecognizerImpl::kAudioSampleRate * 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleOneShotRemoteEngine::kAudioPacketIntervalMs * 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ChannelLayoutToChannelCount(SpeechRecognizerImpl::kChannelLayout) * 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpeechRecognizerImpl::kNumBitsPerAudioSample) / (8 * 1000); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_packet_.resize(audio_packet_length_bytes); 706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int channels = 726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ChannelLayoutToChannelCount(SpeechRecognizerImpl::kChannelLayout); 736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) bytes_per_sample_ = SpeechRecognizerImpl::kNumBitsPerAudioSample / 8; 746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int frames = audio_packet_length_bytes / channels / bytes_per_sample_; 756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) audio_bus_ = media::AudioBus::Create(channels, frames); 766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) audio_bus_->Zero(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CheckEventsConsistency() { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: "!x || y" == "x implies y". 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(!recognition_ended_ || recognition_started_); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(!audio_ended_ || audio_started_); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(!sound_ended_ || sound_started_); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(!audio_started_ || recognition_started_); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(!sound_started_ || audio_started_); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(!audio_ended_ || (sound_ended_ || !sound_started_)); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(!recognition_ended_ || (audio_ended_ || !audio_started_)); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CheckFinalEventsConsistency() { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: "!(x ^ y)" == "(x && y) || (!x && !x)". 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(recognition_started_ ^ recognition_ended_); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(audio_started_ ^ audio_ended_); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(sound_started_ ^ sound_ended_); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Overridden from SpeechRecognitionEventListener: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAudioStart(int session_id) OVERRIDE { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_started_ = true; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckEventsConsistency(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAudioEnd(int session_id) OVERRIDE { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_ended_ = true; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckEventsConsistency(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnRecognitionResults( 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int session_id, const SpeechRecognitionResults& results) OVERRIDE { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_received_ = true; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnRecognitionError( 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int session_id, const SpeechRecognitionError& error) OVERRIDE { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_started_); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(recognition_ended_); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = error.code; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAudioLevelsChange(int session_id, float volume, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float noise_volume) OVERRIDE { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) volume_ = volume; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) noise_volume_ = noise_volume; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnRecognitionEnd(int session_id) OVERRIDE { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognition_ended_ = true; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckEventsConsistency(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnRecognitionStart(int session_id) OVERRIDE { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognition_started_ = true; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckEventsConsistency(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnEnvironmentEstimationComplete(int session_id) OVERRIDE {} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnSoundStart(int session_id) OVERRIDE { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sound_started_ = true; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckEventsConsistency(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnSoundEnd(int session_id) OVERRIDE { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sound_ended_ = true; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckEventsConsistency(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // testing::Test methods. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() OVERRIDE { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputController::set_factory_for_testing( 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &audio_input_controller_factory_); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() OVERRIDE { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputController::set_factory_for_testing(NULL); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) void CopyPacketToAudioBus() { 1596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Copy the created signal into an audio bus in a deinterleaved format. 1606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) audio_bus_->FromInterleaved( 1616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) &audio_packet_[0], audio_bus_->frames(), bytes_per_sample_); 1626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void FillPacketWithTestWaveform() { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill the input with a simple pattern, a 125Hz sawtooth waveform. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < audio_packet_.size(); ++i) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_packet_[i] = static_cast<uint8>(i); 1686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) CopyPacketToAudioBus(); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void FillPacketWithNoise() { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value = 0; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int factor = 175; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < audio_packet_.size(); ++i) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value += factor; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_packet_[i] = value % 100; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) CopyPacketToAudioBus(); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForIO message_loop_; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThreadImpl io_thread_; 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_refptr<SpeechRecognizerImpl> recognizer_; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager_; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool recognition_started_; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool recognition_ended_; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result_received_; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool audio_started_; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool audio_ended_; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool sound_started_; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool sound_ended_; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpeechRecognitionErrorCode error_; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::TestURLFetcherFactory url_fetcher_factory_; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputControllerFactory audio_input_controller_factory_; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8> audio_packet_; 1976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<media::AudioBus> audio_bus_; 1986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int bytes_per_sample_; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float volume_; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float noise_volume_; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, StopNoData) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for callbacks when stopping record before any audio gets recorded. 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognizer_->StopAudioCapture(); 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_started_); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(audio_started_); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, CancelNoData) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for callbacks when canceling recognition before any audio gets 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // recorded. 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognizer_->AbortRecognition(); 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_started_); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(audio_started_); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_ABORTED, error_); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, StopWithData) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start recording, give some data and then stop. This should wait for the 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // network callback to arrive before completion. 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputController* controller = 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_input_controller_factory_.controller(); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try sending 5 chunks of mock audio data and verify that each of them 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resulted immediately in a packet sent out via the network. This verifies 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that we are streaming out encoded data as chunks without waiting for the 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // full recording to complete. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t kNumChunks = 5; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < kNumChunks; ++i) { 2436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(fetcher); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(i + 1, fetcher->upload_chunks().size()); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognizer_->StopAudioCapture(); 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_started_); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_ended_); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(recognition_ended_); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Issue the network callback to complete the process. 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(fetcher); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->set_url(fetcher->GetOriginalURL()); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestStatus status; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status.set_status(net::URLRequestStatus::SUCCESS); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->set_status(status); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->set_response_code(200); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->SetResponseString( 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "{\"status\":0,\"hypotheses\":[{\"utterance\":\"123\"}]}"); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->delegate()->OnURLFetchComplete(fetcher); 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_ended_); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(result_received_); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, CancelWithData) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start recording, give some data and then cancel. 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputController* controller = 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_input_controller_factory_.controller(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 2846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognizer_->AbortRecognition(); 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0)); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_started_); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_started_); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_ABORTED, error_); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, ConnectionError) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start recording, give some data and then stop. Issue the network callback 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with a connection error and verify that the recognizer bubbles the error up 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputController* controller = 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_input_controller_factory_.controller(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 3046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(fetcher); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognizer_->StopAudioCapture(); 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_started_); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_ended_); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(recognition_ended_); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Issue the network callback to complete the process. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->set_url(fetcher->GetOriginalURL()); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestStatus status; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status.set_status(net::URLRequestStatus::FAILED); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status.set_error(net::ERR_CONNECTION_REFUSED); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->set_status(status); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->set_response_code(0); 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fetcher->SetResponseString(std::string()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->delegate()->OnURLFetchComplete(fetcher); 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_ended_); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, ServerError) { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start recording, give some data and then stop. Issue the network callback 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with a 500 error and verify that the recognizer bubbles the error up 336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputController* controller = 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_input_controller_factory_.controller(); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 3416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(fetcher); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognizer_->StopAudioCapture(); 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_started_); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_ended_); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(recognition_ended_); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Issue the network callback to complete the process. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->set_url(fetcher->GetOriginalURL()); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestStatus status; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status.set_status(net::URLRequestStatus::SUCCESS); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->set_status(status); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->set_response_code(500); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->SetResponseString("Internal Server Error"); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->delegate()->OnURLFetchComplete(fetcher); 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_ended_); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, AudioControllerErrorNoData) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if things tear down properly if AudioInputController threw an error. 371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputController* controller = 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_input_controller_factory_.controller(); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) controller->event_handler()->OnError(controller, 377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioInputController::UNKNOWN_ERROR); 378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_started_); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(audio_started_); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO, error_); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, AudioControllerErrorWithData) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if things tear down properly if AudioInputController threw an error 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after giving some audio data. 389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputController* controller = 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_input_controller_factory_.controller(); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 3946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) controller->event_handler()->OnError(controller, 396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioInputController::UNKNOWN_ERROR); 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0)); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_started_); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_started_); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO, error_); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackIssued) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start recording and give a lot of packets with audio samples set to zero. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should trigger the no-speech detector and issue a callback. 409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputController* controller = 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_input_controller_factory_.controller(); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int num_packets = (SpeechRecognizerImpl::kNoSpeechTimeoutMs) / 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleOneShotRemoteEngine::kAudioPacketIntervalMs + 1; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The vector is already filled with zero value samples on create. 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_packets; ++i) { 4196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(recognition_started_); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_started_); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(result_received_); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NO_SPEECH, error_); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackNotIssued) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start recording and give a lot of packets with audio samples set to zero 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and then some more with reasonably loud audio samples. This should be 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // treated as normal speech input and the no-speech detector should not get 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered. 434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputController* controller = 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_input_controller_factory_.controller(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller = audio_input_controller_factory_.controller(); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 44290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int num_packets = (SpeechRecognizerImpl::kNoSpeechTimeoutMs) / 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleOneShotRemoteEngine::kAudioPacketIntervalMs; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The vector is already filled with zero value samples on create. 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_packets / 2; ++i) { 4476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillPacketWithTestWaveform(); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_packets / 2; ++i) { 4526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(audio_started_); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(audio_ended_); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(recognition_ended_); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognizer_->AbortRecognition(); 461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start recording and give a lot of packets with audio samples set to zero 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and then some more with reasonably loud audio samples. Check that we don't 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get the callback during estimation phase, then get zero for the silence 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // samples and proper volume for the loud audio. 470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recognizer_->StartRecognition(media::AudioManagerBase::kDefaultDeviceId); 471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudioInputController* controller = 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_input_controller_factory_.controller(); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller = audio_input_controller_factory_.controller(); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(controller); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Feed some samples to begin with for the endpointer to do noise estimation. 47990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int num_packets = SpeechRecognizerImpl::kEndpointerEstimationTimeMs / 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleOneShotRemoteEngine::kAudioPacketIntervalMs; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillPacketWithNoise(); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_packets; ++i) { 4836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(-1.0f, volume_); // No audio volume set yet. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The vector is already filled with zero value samples on create. 4896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FLOAT_EQ(0.74939233f, volume_); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillPacketWithTestWaveform(); 4946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller->event_handler()->OnData(controller, audio_bus_.get()); 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_NEAR(0.89926866f, volume_, 0.00001f); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FLOAT_EQ(0.75071919f, noise_volume_); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(audio_ended_); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(recognition_ended_); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recognizer_->AbortRecognition(); 503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckFinalEventsConsistency(); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 508