summaryrefslogtreecommitdiffstats
path: root/content/browser/speech/speech_recognizer_unittest.cc
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-26 18:46:15 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-26 18:46:15 +0000
commit50fab53bddb2c3cb24d5682c913a03226ccf49ef (patch)
treebb04af83ca5f2be010e32c2e10cfd245117a4847 /content/browser/speech/speech_recognizer_unittest.cc
parent5c557f37629dc12dfd99e8fb55c235c8c46a8098 (diff)
downloadchromium_src-50fab53bddb2c3cb24d5682c913a03226ccf49ef.zip
chromium_src-50fab53bddb2c3cb24d5682c913a03226ccf49ef.tar.gz
chromium_src-50fab53bddb2c3cb24d5682c913a03226ccf49ef.tar.bz2
Move core pieces of speech from chrome to content.
TBR=satish Review URL: http://codereview.chromium.org/6591024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76165 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/speech/speech_recognizer_unittest.cc')
-rw-r--r--content/browser/speech/speech_recognizer_unittest.cc300
1 files changed, 300 insertions, 0 deletions
diff --git a/content/browser/speech/speech_recognizer_unittest.cc b/content/browser/speech/speech_recognizer_unittest.cc
new file mode 100644
index 0000000..8365396
--- /dev/null
+++ b/content/browser/speech/speech_recognizer_unittest.cc
@@ -0,0 +1,300 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "chrome/common/net/test_url_fetcher_factory.h"
+#include "content/browser/browser_thread.h"
+#include "content/browser/speech/speech_recognizer.h"
+#include "media/audio/test_audio_input_controller_factory.h"
+#include "net/url_request/url_request_status.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using media::AudioInputController;
+using media::TestAudioInputController;
+using media::TestAudioInputControllerFactory;
+
+namespace speech_input {
+
+class SpeechRecognizerTest : public SpeechRecognizerDelegate,
+ public testing::Test {
+ public:
+ SpeechRecognizerTest()
+ : io_thread_(BrowserThread::IO, &message_loop_),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ recognizer_(new SpeechRecognizer(this, 1, std::string(),
+ std::string(), std::string(),
+ std::string()))),
+ recording_complete_(false),
+ recognition_complete_(false),
+ result_received_(false),
+ error_(SpeechRecognizer::RECOGNIZER_NO_ERROR),
+ volume_(-1.0f) {
+ int audio_packet_length_bytes =
+ (SpeechRecognizer::kAudioSampleRate *
+ SpeechRecognizer::kAudioPacketIntervalMs *
+ SpeechRecognizer::kNumAudioChannels *
+ SpeechRecognizer::kNumBitsPerAudioSample) / (8 * 1000);
+ audio_packet_.resize(audio_packet_length_bytes);
+ }
+
+ // SpeechRecognizer::Delegate methods.
+ virtual void SetRecognitionResult(int caller_id,
+ bool error,
+ const SpeechInputResultArray& result) {
+ result_received_ = true;
+ }
+
+ virtual void DidCompleteRecording(int caller_id) {
+ recording_complete_ = true;
+ }
+
+ virtual void DidCompleteRecognition(int caller_id) {
+ recognition_complete_ = true;
+ }
+
+ virtual void DidCompleteEnvironmentEstimation(int caller_id) {
+ }
+
+ virtual void OnRecognizerError(int caller_id,
+ SpeechRecognizer::ErrorCode error) {
+ error_ = error;
+ }
+
+ virtual void SetInputVolume(int caller_id, float volume) {
+ volume_ = volume;
+ }
+
+ // testing::Test methods.
+ virtual void SetUp() {
+ URLFetcher::set_factory(&url_fetcher_factory_);
+ AudioInputController::set_factory(&audio_input_controller_factory_);
+ }
+
+ virtual void TearDown() {
+ URLFetcher::set_factory(NULL);
+ AudioInputController::set_factory(NULL);
+ }
+
+ void FillPacketWithTestWaveform() {
+ // Fill the input with a simple pattern, a 125Hz sawtooth waveform.
+ for (size_t i = 0; i < audio_packet_.size(); ++i)
+ audio_packet_[i] = static_cast<uint8>(i);
+ }
+
+ protected:
+ MessageLoopForIO message_loop_;
+ BrowserThread io_thread_;
+ scoped_refptr<SpeechRecognizer> recognizer_;
+ bool recording_complete_;
+ bool recognition_complete_;
+ bool result_received_;
+ SpeechRecognizer::ErrorCode error_;
+ TestURLFetcherFactory url_fetcher_factory_;
+ TestAudioInputControllerFactory audio_input_controller_factory_;
+ std::vector<uint8> audio_packet_;
+ float volume_;
+};
+
+TEST_F(SpeechRecognizerTest, StopNoData) {
+ // Check for callbacks when stopping record before any audio gets recorded.
+ EXPECT_TRUE(recognizer_->StartRecording());
+ recognizer_->CancelRecognition();
+ EXPECT_FALSE(recording_complete_);
+ EXPECT_FALSE(recognition_complete_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_NO_ERROR, error_);
+}
+
+TEST_F(SpeechRecognizerTest, CancelNoData) {
+ // Check for callbacks when canceling recognition before any audio gets
+ // recorded.
+ EXPECT_TRUE(recognizer_->StartRecording());
+ recognizer_->StopRecording();
+ EXPECT_TRUE(recording_complete_);
+ EXPECT_TRUE(recognition_complete_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_NO_ERROR, error_);
+}
+
+TEST_F(SpeechRecognizerTest, StopWithData) {
+ // Start recording, give some data and then stop. This should wait for the
+ // network callback to arrive before completion.
+ EXPECT_TRUE(recognizer_->StartRecording());
+ TestAudioInputController* controller =
+ audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+ controller = audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+ controller->event_handler()->OnData(controller, &audio_packet_[0],
+ audio_packet_.size());
+ MessageLoop::current()->RunAllPending();
+ recognizer_->StopRecording();
+ EXPECT_TRUE(recording_complete_);
+ EXPECT_FALSE(recognition_complete_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_NO_ERROR, error_);
+
+ // Issue the network callback to complete the process.
+ TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
+ ASSERT_TRUE(fetcher);
+ net::URLRequestStatus status;
+ status.set_status(net::URLRequestStatus::SUCCESS);
+ fetcher->delegate()->OnURLFetchComplete(
+ fetcher, fetcher->original_url(), status, 200, ResponseCookies(),
+ "{\"hypotheses\":[{\"utterance\":\"123\"}]}");
+ EXPECT_TRUE(recognition_complete_);
+ EXPECT_TRUE(result_received_);
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_NO_ERROR, error_);
+}
+
+TEST_F(SpeechRecognizerTest, CancelWithData) {
+ // Start recording, give some data and then cancel. This should not create
+ // a network request and finish immediately.
+ EXPECT_TRUE(recognizer_->StartRecording());
+ TestAudioInputController* controller =
+ audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+ controller->event_handler()->OnData(controller, &audio_packet_[0],
+ audio_packet_.size());
+ MessageLoop::current()->RunAllPending();
+ recognizer_->CancelRecognition();
+ EXPECT_EQ(NULL, url_fetcher_factory_.GetFetcherByID(0));
+ EXPECT_FALSE(recording_complete_);
+ EXPECT_FALSE(recognition_complete_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_NO_ERROR, error_);
+}
+
+TEST_F(SpeechRecognizerTest, AudioControllerErrorNoData) {
+ // Check if things tear down properly if AudioInputController threw an error.
+ EXPECT_TRUE(recognizer_->StartRecording());
+ TestAudioInputController* controller =
+ audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+ controller->event_handler()->OnError(controller, 0);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_FALSE(recording_complete_);
+ EXPECT_FALSE(recognition_complete_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_ERROR_CAPTURE, error_);
+}
+
+TEST_F(SpeechRecognizerTest, AudioControllerErrorWithData) {
+ // Check if things tear down properly if AudioInputController threw an error
+ // after giving some audio data.
+ EXPECT_TRUE(recognizer_->StartRecording());
+ TestAudioInputController* controller =
+ audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+ controller->event_handler()->OnData(controller, &audio_packet_[0],
+ audio_packet_.size());
+ controller->event_handler()->OnError(controller, 0);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(NULL, url_fetcher_factory_.GetFetcherByID(0));
+ EXPECT_FALSE(recording_complete_);
+ EXPECT_FALSE(recognition_complete_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_ERROR_CAPTURE, error_);
+}
+
+TEST_F(SpeechRecognizerTest, NoSpeechCallbackIssued) {
+ // Start recording and give a lot of packets with audio samples set to zero.
+ // This should trigger the no-speech detector and issue a callback.
+ EXPECT_TRUE(recognizer_->StartRecording());
+ TestAudioInputController* controller =
+ audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+ controller = audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+
+ int num_packets = (SpeechRecognizer::kNoSpeechTimeoutSec * 1000) /
+ SpeechRecognizer::kAudioPacketIntervalMs;
+ // The vector is already filled with zero value samples on create.
+ for (int i = 0; i < num_packets; ++i) {
+ controller->event_handler()->OnData(controller, &audio_packet_[0],
+ audio_packet_.size());
+ }
+ MessageLoop::current()->RunAllPending();
+ EXPECT_FALSE(recording_complete_);
+ EXPECT_FALSE(recognition_complete_);
+ EXPECT_FALSE(result_received_);
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_ERROR_NO_SPEECH, error_);
+}
+
+TEST_F(SpeechRecognizerTest, NoSpeechCallbackNotIssued) {
+ // Start recording and give a lot of packets with audio samples set to zero
+ // and then some more with reasonably loud audio samples. This should be
+ // treated as normal speech input and the no-speech detector should not get
+ // triggered.
+ EXPECT_TRUE(recognizer_->StartRecording());
+ TestAudioInputController* controller =
+ audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+ controller = audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+
+ int num_packets = (SpeechRecognizer::kNoSpeechTimeoutSec * 1000) /
+ SpeechRecognizer::kAudioPacketIntervalMs;
+
+ // The vector is already filled with zero value samples on create.
+ for (int i = 0; i < num_packets / 2; ++i) {
+ controller->event_handler()->OnData(controller, &audio_packet_[0],
+ audio_packet_.size());
+ }
+
+ FillPacketWithTestWaveform();
+ for (int i = 0; i < num_packets / 2; ++i) {
+ controller->event_handler()->OnData(controller, &audio_packet_[0],
+ audio_packet_.size());
+ }
+
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_NO_ERROR, error_);
+ EXPECT_FALSE(recording_complete_);
+ EXPECT_FALSE(recognition_complete_);
+ recognizer_->CancelRecognition();
+}
+
+TEST_F(SpeechRecognizerTest, SetInputVolumeCallback) {
+ // Start recording and give a lot of packets with audio samples set to zero
+ // and then some more with reasonably loud audio samples. Check that we don't
+ // get the callback during estimation phase, then get zero for the silence
+ // samples and proper volume for the loud audio.
+ EXPECT_TRUE(recognizer_->StartRecording());
+ TestAudioInputController* controller =
+ audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+ controller = audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+
+ // Feed some samples to begin with for the endpointer to do noise estimation.
+ int num_packets = SpeechRecognizer::kEndpointerEstimationTimeMs /
+ SpeechRecognizer::kAudioPacketIntervalMs;
+ for (int i = 0; i < num_packets; ++i) {
+ controller->event_handler()->OnData(controller, &audio_packet_[0],
+ audio_packet_.size());
+ }
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(-1.0f, volume_); // No audio volume set yet.
+
+ // The vector is already filled with zero value samples on create.
+ controller->event_handler()->OnData(controller, &audio_packet_[0],
+ audio_packet_.size());
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(0, volume_);
+
+ FillPacketWithTestWaveform();
+ controller->event_handler()->OnData(controller, &audio_packet_[0],
+ audio_packet_.size());
+ MessageLoop::current()->RunAllPending();
+ EXPECT_FLOAT_EQ(0.9f, volume_);
+
+ EXPECT_EQ(SpeechRecognizer::RECOGNIZER_NO_ERROR, error_);
+ EXPECT_FALSE(recording_complete_);
+ EXPECT_FALSE(recognition_complete_);
+ recognizer_->CancelRecognition();
+}
+
+} // namespace speech_input