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