1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/message_loop/message_loop.h" 6 #include "base/strings/utf_string_conversions.h" 7 #include "content/browser/speech/audio_buffer.h" 8 #include "content/browser/speech/google_one_shot_remote_engine.h" 9 #include "content/public/common/speech_recognition_error.h" 10 #include "content/public/common/speech_recognition_result.h" 11 #include "net/url_request/test_url_fetcher_factory.h" 12 #include "net/url_request/url_request_context_getter.h" 13 #include "net/url_request/url_request_status.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace content { 17 18 class GoogleOneShotRemoteEngineTest : public SpeechRecognitionEngineDelegate, 19 public testing::Test { 20 public: 21 GoogleOneShotRemoteEngineTest() 22 : error_(SPEECH_RECOGNITION_ERROR_NONE) {} 23 24 // Creates a speech recognition request and invokes its URL fetcher delegate 25 // with the given test data. 26 void CreateAndTestRequest(bool success, const std::string& http_response); 27 28 // SpeechRecognitionRequestDelegate methods. 29 virtual void OnSpeechRecognitionEngineResults( 30 const SpeechRecognitionResults& results) OVERRIDE { 31 results_ = results; 32 } 33 34 virtual void OnSpeechRecognitionEngineError( 35 const SpeechRecognitionError& error) OVERRIDE { 36 error_ = error.code; 37 } 38 39 // Accessor for the only result item. 40 const SpeechRecognitionResult& result() const { 41 DCHECK_EQ(results_.size(), 1U); 42 return results_[0]; 43 } 44 45 protected: 46 base::MessageLoop message_loop_; 47 net::TestURLFetcherFactory url_fetcher_factory_; 48 SpeechRecognitionErrorCode error_; 49 SpeechRecognitionResults results_; 50 }; 51 52 void GoogleOneShotRemoteEngineTest::CreateAndTestRequest( 53 bool success, const std::string& http_response) { 54 GoogleOneShotRemoteEngine client(NULL); 55 unsigned char dummy_audio_buffer_data[2] = {'\0', '\0'}; 56 scoped_refptr<AudioChunk> dummy_audio_chunk( 57 new AudioChunk(&dummy_audio_buffer_data[0], 58 sizeof(dummy_audio_buffer_data), 59 2 /* bytes per sample */)); 60 client.set_delegate(this); 61 client.StartRecognition(); 62 client.TakeAudioChunk(*dummy_audio_chunk.get()); 63 client.AudioChunksEnded(); 64 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 65 ASSERT_TRUE(fetcher); 66 67 fetcher->set_url(fetcher->GetOriginalURL()); 68 net::URLRequestStatus status; 69 status.set_status(success ? net::URLRequestStatus::SUCCESS : 70 net::URLRequestStatus::FAILED); 71 fetcher->set_status(status); 72 fetcher->set_response_code(success ? 200 : 500); 73 fetcher->SetResponseString(http_response); 74 75 fetcher->delegate()->OnURLFetchComplete(fetcher); 76 // Parsed response will be available in result(). 77 } 78 79 TEST_F(GoogleOneShotRemoteEngineTest, BasicTest) { 80 // Normal success case with one result. 81 CreateAndTestRequest(true, 82 "{\"status\":0,\"hypotheses\":" 83 "[{\"utterance\":\"123456\",\"confidence\":0.9}]}"); 84 EXPECT_EQ(error_, SPEECH_RECOGNITION_ERROR_NONE); 85 EXPECT_EQ(1U, result().hypotheses.size()); 86 EXPECT_EQ(base::ASCIIToUTF16("123456"), result().hypotheses[0].utterance); 87 EXPECT_EQ(0.9, result().hypotheses[0].confidence); 88 89 // Normal success case with multiple results. 90 CreateAndTestRequest(true, 91 "{\"status\":0,\"hypotheses\":[" 92 "{\"utterance\":\"hello\",\"confidence\":0.9}," 93 "{\"utterance\":\"123456\",\"confidence\":0.5}]}"); 94 EXPECT_EQ(error_, SPEECH_RECOGNITION_ERROR_NONE); 95 EXPECT_EQ(2u, result().hypotheses.size()); 96 EXPECT_EQ(base::ASCIIToUTF16("hello"), result().hypotheses[0].utterance); 97 EXPECT_EQ(0.9, result().hypotheses[0].confidence); 98 EXPECT_EQ(base::ASCIIToUTF16("123456"), result().hypotheses[1].utterance); 99 EXPECT_EQ(0.5, result().hypotheses[1].confidence); 100 101 // Zero results. 102 CreateAndTestRequest(true, "{\"status\":0,\"hypotheses\":[]}"); 103 EXPECT_EQ(error_, SPEECH_RECOGNITION_ERROR_NONE); 104 EXPECT_EQ(0U, result().hypotheses.size()); 105 106 // Http failure case. 107 CreateAndTestRequest(false, std::string()); 108 EXPECT_EQ(error_, SPEECH_RECOGNITION_ERROR_NETWORK); 109 EXPECT_EQ(0U, result().hypotheses.size()); 110 111 // Invalid status case. 112 CreateAndTestRequest(true, "{\"status\":\"invalid\",\"hypotheses\":[]}"); 113 EXPECT_EQ(error_, SPEECH_RECOGNITION_ERROR_NETWORK); 114 EXPECT_EQ(0U, result().hypotheses.size()); 115 116 // Server-side error case. 117 CreateAndTestRequest(true, "{\"status\":1,\"hypotheses\":[]}"); 118 EXPECT_EQ(error_, SPEECH_RECOGNITION_ERROR_NETWORK); 119 EXPECT_EQ(0U, result().hypotheses.size()); 120 121 // Malformed JSON case. 122 CreateAndTestRequest(true, "{\"status\":0,\"hypotheses\":" 123 "[{\"unknownkey\":\"hello\"}]}"); 124 EXPECT_EQ(error_, SPEECH_RECOGNITION_ERROR_NETWORK); 125 EXPECT_EQ(0U, result().hypotheses.size()); 126 } 127 128 } // namespace content 129