diff options
Diffstat (limited to 'chrome/browser/renderer_host/translation_service_unittest.cc')
-rw-r--r-- | chrome/browser/renderer_host/translation_service_unittest.cc | 505 |
1 files changed, 0 insertions, 505 deletions
diff --git a/chrome/browser/renderer_host/translation_service_unittest.cc b/chrome/browser/renderer_host/translation_service_unittest.cc deleted file mode 100644 index f973502..0000000 --- a/chrome/browser/renderer_host/translation_service_unittest.cc +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright (c) 2010 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 "base/json/json_writer.h" -#include "base/stl_util-inl.h" -#include "base/string_tokenizer.h" -#include "base/string_util.h" -#include "chrome/browser/net/test_url_fetcher_factory.h" -#include "chrome/browser/renderer_host/translation_service.h" -#include "chrome/common/render_messages.h" -#include "ipc/ipc_message.h" -#include "net/base/escape.h" -#include "net/url_request/url_request_status.h" -#include "testing/gtest/include/gtest/gtest.h" - -typedef std::vector<string16> TextChunks; -typedef std::vector<TextChunks> TextChunksList; - -class TestMessageSender : public IPC::Message::Sender { - public: - virtual ~TestMessageSender() { - ClearMessages(); - } - - virtual bool Send(IPC::Message* msg) { - messages_.push_back(msg); - return true; - } - - size_t message_count() const { return messages_.size(); } - - void GetMessageParameters(size_t message_index, int* routing_id, - int* work_id, int* error_id, - std::vector<string16>* text_chunks) { - ASSERT_LT(message_index, messages_.size()); - *routing_id = messages_.at(message_index)->routing_id(); - ViewMsg_TranslateTextReponse::Read(messages_.at(message_index), - work_id, error_id, text_chunks); - } - - void ClearMessages() { - STLDeleteElements(&messages_); - messages_.clear(); - } - - std::vector<IPC::Message*> messages_; - MessageLoop message_loop_; -}; - -class TestTranslationService : public TranslationService { - public: - explicit TestTranslationService(IPC::Message::Sender* message_sender) - : TranslationService(message_sender) {} - - virtual int GetSendRequestDelay() const { - return 0; - } -}; - -class TranslationServiceTest : public testing::Test { - public: - TranslationServiceTest() : translation_service_(&message_sender_) {} - - virtual void SetUp() { - URLFetcher::set_factory(&url_fetcher_factory_); - } - - virtual void TearDown() { - URLFetcher::set_factory(NULL); - } - - protected: - TestURLFetcherFactory url_fetcher_factory_; - TestMessageSender message_sender_; - TestTranslationService translation_service_; -}; - -static void SimulateErrorResponse(TestURLFetcher* url_fetcher, - int response_code) { - url_fetcher->delegate()->OnURLFetchComplete(url_fetcher, - url_fetcher->original_url(), - URLRequestStatus(), - response_code, - ResponseCookies(), - std::string()); -} - -// Merges the strings in |text_chunks| into the string that the translation -// server received. -static string16 BuildResponseString(const TextChunks& text_chunks) { - string16 text; - for (size_t i = 0; i < text_chunks.size(); ++i) { - text.append(ASCIIToUTF16("<a _CR_TR_ id='")); - text.append(IntToString16(i)); - text.append(ASCIIToUTF16("'>")); - text.append(text_chunks.at(i)); - text.append(ASCIIToUTF16("</a>")); - } - return text; -} - -static void SimulateSuccessfulResponse(TestURLFetcher* url_fetcher, - const TextChunksList& text_chunks_list) { - scoped_ptr<ListValue> list(new ListValue()); - for (TextChunksList::const_iterator iter = text_chunks_list.begin(); - iter != text_chunks_list.end(); ++iter) { - list->Append(Value::CreateStringValueFromUTF16(BuildResponseString(*iter))); - } - - std::string response; - base::JSONWriter::Write(list.get(), false, &response); - url_fetcher->delegate()->OnURLFetchComplete(url_fetcher, - url_fetcher->original_url(), - URLRequestStatus(), - 200, - ResponseCookies(), - response); -} - -static void SimulateSimpleSuccessfulResponse(TestURLFetcher* url_fetcher, - const char* const* c_text_chunks, - size_t text_chunks_length) { - TextChunks text_chunks; - for (size_t i = 0; i < text_chunks_length; i++) - text_chunks.push_back(ASCIIToUTF16(c_text_chunks[i])); - - string16 text = BuildResponseString(text_chunks); - - std::string response; - scoped_ptr<Value> json_text(Value::CreateStringValueFromUTF16(text)); - base::JSONWriter::Write(json_text.get(), false, &response); - url_fetcher->delegate()->OnURLFetchComplete(url_fetcher, - url_fetcher->original_url(), - URLRequestStatus(), - 200, - ResponseCookies(), - response); -} - -// Parses the upload data from |url_fetcher| and puts the value for the q -// parameters in |text_chunks|. -static void ExtractQueryStringsFromUploadData(TestURLFetcher* url_fetcher, - TextChunks* text_chunks) { - std::string upload_data = url_fetcher->upload_data(); - - CStringTokenizer str_tok(upload_data.c_str(), upload_data.c_str() + - upload_data.length(), "&"); - while (str_tok.GetNext()) { - std::string tok = str_tok.token(); - if (tok.size() > 1U && tok.at(0) == 'q' && tok.at(1) == '=') - text_chunks->push_back(UnescapeForHTML(ASCIIToUTF16(tok.substr(2)))); - } -} - -TEST_F(TranslationServiceTest, MergeTestChunks) { - TranslationService translation_service(NULL); - std::vector<string16> input; - input.push_back(ASCIIToUTF16("Hello")); - string16 result = translation_service.MergeTextChunks(input); - EXPECT_EQ(ASCIIToUTF16("Hello"), result); - input.push_back(ASCIIToUTF16(" my name")); - input.push_back(ASCIIToUTF16(" is")); - input.push_back(ASCIIToUTF16(" Jay.")); - result = translation_service.MergeTextChunks(input); - EXPECT_EQ(ASCIIToUTF16("<a _CR_TR_ id='0'>Hello</a>" - "<a _CR_TR_ id='1'> my name</a>" - "<a _CR_TR_ id='2'> is</a>" - "<a _CR_TR_ id='3'> Jay.</a>"), - result); -} - -TEST_F(TranslationServiceTest, RemoveTag) { - const char* kInputs[] = { - "", "Hello", "<a ></a>", " <a href='http://www.google.com'> Link </a>", - "<a >Link", "<a link</a>", "<a id=1><a id=1>broken</a></a>", - "<a id=1>broken</a></a> bad bad</a>", - }; - const char* kExpected[] = { - "", "Hello", "", " Link ", "Link", "<a link", "broken", "broken bad bad" - }; - - TranslationService translation_service(NULL); - ASSERT_EQ(arraysize(kInputs), arraysize(kExpected)); - for (size_t i = 0; i < arraysize(kInputs); ++i) { - SCOPED_TRACE(::testing::Message::Message() << "Iteration " << i); - string16 input = ASCIIToUTF16(kInputs[i]); - string16 output = translation_service.RemoveTag(input); - EXPECT_EQ(ASCIIToUTF16(kExpected[i]), output); - } -} - -// Tests that we deal correctly with the various results the translation server -// can return, including the buggy ones. -TEST_F(TranslationServiceTest, SplitIntoTextChunks) { - TranslationService translation_service(NULL); - - // Simple case. - std::vector<string16> text_chunks; - translation_service.SplitIntoTextChunks(ASCIIToUTF16("Hello"), &text_chunks); - ASSERT_EQ(1U, text_chunks.size()); - EXPECT_EQ(ASCIIToUTF16("Hello"), text_chunks[0]); - - text_chunks.clear(); - - // Multiple chunks case, correct syntax. - translation_service.SplitIntoTextChunks( - ASCIIToUTF16("<a _CR_TR_ id='0'>Bonjour</a>" - "<a _CR_TR_ id='1'> mon nom</a>" - "<a _CR_TR_ id='2'> est</a>" - "<a _CR_TR_ id='3'> Jay.</a>"), &text_chunks); - ASSERT_EQ(4U, text_chunks.size()); - EXPECT_EQ(ASCIIToUTF16("Bonjour"), text_chunks[0]); - EXPECT_EQ(ASCIIToUTF16(" mon nom"), text_chunks[1]); - EXPECT_EQ(ASCIIToUTF16(" est"), text_chunks[2]); - EXPECT_EQ(ASCIIToUTF16(" Jay."), text_chunks[3]); - text_chunks.clear(); - - // Multiple chunks case, duplicate and unbalanced tags. - // For info, original input: - // <a _CR_TRANSLATE_ id='0'> Experience </a><a _CR_TRANSLATE_ id='1'>Nexus One - // </a><a _CR_TRANSLATE_ id='2'>, the new Android phone from Google</a> - translation_service.SplitIntoTextChunks( - ASCIIToUTF16("<a _CR_TR_ id='0'>Experience</a> <a _CR_TR_ id='1'>Nexus" - "<a _CR_TR_ id='2'> One,</a></a> <a _CR_TR_ id='2'>the new " - "Android Phone</a>"), &text_chunks); - ASSERT_EQ(3U, text_chunks.size()); - EXPECT_EQ(ASCIIToUTF16("Experience "), text_chunks[0]); - EXPECT_EQ(ASCIIToUTF16("Nexus"), text_chunks[1]); - EXPECT_EQ(ASCIIToUTF16(" One, the new Android Phone"), text_chunks[2]); - text_chunks.clear(); - - // Other incorrect case: - // Original input: - // <a _CR_TR_ id='0'>Benzinpreis-</a><a _CR_TR_ id='1'>vergleich</a> - translation_service.SplitIntoTextChunks( - ASCIIToUTF16("<a _CR_TR_ id='0'>Gasoline <a _CR_TR_ id='1'>" - "price-comparison</a></a>"), &text_chunks); - ASSERT_EQ(2U, text_chunks.size()); - EXPECT_EQ(ASCIIToUTF16("Gasoline "), text_chunks[0]); - EXPECT_EQ(ASCIIToUTF16("price-comparison"), text_chunks[1]); - text_chunks.clear(); - - // Other incorrect case: - // Original input: - // <a _CR_TR_ id='0'>Bußgeld-</a><a _CR_TR_ id='1'>rechner</a> - translation_service.SplitIntoTextChunks( - ASCIIToUTF16("<a _CR_TR_ id='1'><a _CR_TR_ id='0'>Fine-computer</a>" - "</a>"), &text_chunks); - ASSERT_EQ(2U, text_chunks.size()); - EXPECT_EQ(ASCIIToUTF16(""), text_chunks[0]); - EXPECT_EQ(ASCIIToUTF16("Fine-computer"), text_chunks[1]); - text_chunks.clear(); - - translation_service.SplitIntoTextChunks( - ASCIIToUTF16("<a _CR_TR_ id='0'>The mountain live .</a> " - "<a _CR_TR_ id='1'>By Philipp Wittrock</a> <a _CR_TR_ id='0'>are</a> " - "<a _CR_TR_ id='2'>more ...</a> <a _CR_TR_ id='3'>Video</a> " - "<a _CR_TR_ id='4'>Forum</a>"), &text_chunks); - ASSERT_EQ(5U, text_chunks.size()); - EXPECT_EQ(ASCIIToUTF16("The mountain live . "), text_chunks[0]); - EXPECT_EQ(ASCIIToUTF16("By Philipp Wittrock are "), text_chunks[1]); - EXPECT_EQ(ASCIIToUTF16("more ... "), text_chunks[2]); - EXPECT_EQ(ASCIIToUTF16("Video "), text_chunks[3]); - EXPECT_EQ(ASCIIToUTF16("Forum"), text_chunks[4]); - text_chunks.clear(); - - // Make sure we support ending with a start tag. - translation_service.SplitIntoTextChunks( - ASCIIToUTF16("<a _CR_TR_ id='0'>Hello</a><a _CR_TR_ id='1'>"), - &text_chunks); - ASSERT_EQ(2U, text_chunks.size()); - EXPECT_EQ(ASCIIToUTF16("Hello"), text_chunks[0]); - EXPECT_EQ(EmptyString16(), text_chunks[1]); -} - -// Tests that a successful translate works as expected. -TEST_F(TranslationServiceTest, SimpleSuccessfulTranslation) { - const char* const kEnglishTextChunks[] = { - "An atom is talking to another atom:", - "- I think I lost an electron.", - "- Are you sure?", - "- I am positive." - }; - - const char* const kFrenchTextChunks[] = { - "Un atome parle a un autre atome:", - "- Je crois que j'ai perdu un electron.", - "- T'es sur?", - "- Je suis positif." // Note that the joke translates poorly in French. - }; - - // Translate some text unsecurely. - std::vector<string16> text_chunks; - for (size_t i = 0; i < arraysize(kEnglishTextChunks); ++i) - text_chunks.push_back(ASCIIToUTF16(kEnglishTextChunks[i])); - translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", false); - - TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); - // The message was too short to triger the sending of a request to the - // translation request. A task has been pushed for that. - EXPECT_TRUE(url_fetcher == NULL); - MessageLoop::current()->RunAllPending(); - - // Now the task has been run, the message should have been sent. - url_fetcher = url_fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(url_fetcher != NULL); - // Check the URL is HTTP. - EXPECT_FALSE(url_fetcher->original_url().SchemeIsSecure()); - - // Let's simulate the JSON response from the server. - SimulateSimpleSuccessfulResponse(url_fetcher, &(kFrenchTextChunks[0]), - arraysize(kFrenchTextChunks)); - - // This should have triggered a ViewMsg_TranslateTextReponse message. - ASSERT_EQ(1U, message_sender_.message_count()); - - // Test the message has the right translation. - int routing_id = 0; - int work_id = 0; - int error_id = 0; - std::vector<string16> translated_text_chunks; - message_sender_.GetMessageParameters(0, &routing_id, &work_id, &error_id, - &translated_text_chunks); - EXPECT_EQ(0, routing_id); - EXPECT_EQ(0, error_id); - ASSERT_EQ(arraysize(kFrenchTextChunks), translated_text_chunks.size()); - for (size_t i = 0; i < arraysize(kFrenchTextChunks); ++i) - EXPECT_EQ(ASCIIToUTF16(kFrenchTextChunks[i]), translated_text_chunks[i]); -} - -// Tests that on failure we send the expected error message. -TEST_F(TranslationServiceTest, FailedTranslation) { - std::vector<string16> text_chunks; - text_chunks.push_back(ASCIIToUTF16("Hello")); - translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", false); - - // Run the task that creates the URLFetcher and sends the request. - MessageLoop::current()->RunAllPending(); - - TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(url_fetcher != NULL); - SimulateErrorResponse(url_fetcher, 500); - - // This should have triggered a ViewMsg_TranslateTextReponse message. - ASSERT_EQ(1U, message_sender_.message_count()); - - // Test the message has some error. - int routing_id = 0; - int work_id = 0; - int error_id = 0; - std::vector<string16> translated_text_chunks; - message_sender_.GetMessageParameters(0, &routing_id, &work_id, &error_id, - &translated_text_chunks); - - EXPECT_NE(0, error_id); // Anything but 0 means there was an error. - EXPECT_TRUE(translated_text_chunks.empty()); -} - -// Tests that a secure translation is done over a secure connection. -TEST_F(TranslationServiceTest, SecureTranslation) { - std::vector<string16> text_chunks; - text_chunks.push_back(ASCIIToUTF16("Hello")); - translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", - true /* secure */); - - // Run the task that creates the URLFetcher and sends the request. - MessageLoop::current()->RunAllPending(); - - TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(url_fetcher != NULL); - EXPECT_TRUE(url_fetcher->original_url().SchemeIsSecure()); -} - -// Test mixing requests from different renderers. -TEST_F(TranslationServiceTest, MultipleRVRequests) { - const char* const kExpectedRV1_1 = "Bonjour RV1"; - const char* const kExpectedRV1_2 = "Encore bonjour RV1"; - const char* const kExpectedRV1_3 = "Encore bonjour a nouveau RV1"; - const char* const kExpectedRV2 = "Bonjour RV2"; - const char* const kExpectedRV3 = "Bonjour RV3"; - - TextChunks text_chunks; - text_chunks.push_back(ASCIIToUTF16("Hello RV1")); - text_chunks.push_back(ASCIIToUTF16("Hello again RV1")); - translation_service_.Translate(1, 0, 0, text_chunks, "en", "fr", false); - text_chunks.clear(); - text_chunks.push_back(ASCIIToUTF16("Hello RV2")); - translation_service_.Translate(2, 0, 0, text_chunks, "en", "fr", false); - text_chunks.clear(); - text_chunks.push_back(ASCIIToUTF16("Hello again one more time RV1")); - translation_service_.Translate(1, 0, 1, text_chunks, "en", "fr", false); - text_chunks.clear(); - text_chunks.push_back(ASCIIToUTF16("Hello RV3")); - translation_service_.Translate(3, 0, 0, text_chunks, "en", "fr", false); - - // Run the tasks that create the URLFetcher and send the requests. - MessageLoop::current()->RunAllPending(); - - // We should have 3 pending URL fetchers. (The 2 translate requests for RV1 - // should have been grouped in 1.) Simluate the translation server responses. - TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(1); - ASSERT_TRUE(url_fetcher != NULL); - - TextChunksList text_chunks_list; - text_chunks.clear(); - text_chunks.push_back(ASCIIToUTF16(kExpectedRV1_1)); - text_chunks.push_back(ASCIIToUTF16(kExpectedRV1_2)); - text_chunks_list.push_back(text_chunks); - text_chunks.clear(); - text_chunks.push_back(ASCIIToUTF16(kExpectedRV1_3)); - text_chunks_list.push_back(text_chunks); - SimulateSuccessfulResponse(url_fetcher, text_chunks_list); - - url_fetcher = url_fetcher_factory_.GetFetcherByID(2); - ASSERT_TRUE(url_fetcher != NULL); - SimulateSimpleSuccessfulResponse(url_fetcher, &kExpectedRV2, 1); - - url_fetcher = url_fetcher_factory_.GetFetcherByID(3); - ASSERT_TRUE(url_fetcher != NULL); - SimulateSimpleSuccessfulResponse(url_fetcher, &kExpectedRV3, 1); - - // This should have triggered 4 ViewMsg_TranslateTextReponse messages. - ASSERT_EQ(4U, message_sender_.message_count()); - - const int kExpectedRoutingID[] = { 1, 1, 2, 3 }; - const int kExpectedWorkID[] = { 0, 1, 0, 0 }; - const size_t kExpectedStringCount[] = { 2U, 1U, 1U, 1U }; - - // Test the messages have the expected content. - for (size_t i = 0; i < 4; i++) { - SCOPED_TRACE(::testing::Message::Message() << "Iteration " << i); - int routing_id = 0; - int work_id = 0; - int error_id = 0; - std::vector<string16> translated_text_chunks; - message_sender_.GetMessageParameters(i, &routing_id, &work_id, &error_id, - &translated_text_chunks); - EXPECT_EQ(kExpectedRoutingID[i], routing_id); - EXPECT_EQ(kExpectedWorkID[i], work_id); - EXPECT_EQ(0, error_id); - EXPECT_EQ(kExpectedStringCount[i], translated_text_chunks.size()); - // TODO(jcampan): we should compare the strings. - } -} - -// Tests sending more than the max size. -TEST_F(TranslationServiceTest, MoreThanMaxSizeRequests) { - std::string one_kb_string(1024U, 'A'); - TextChunks text_chunks; - text_chunks.push_back(ASCIIToUTF16(one_kb_string)); - // Send 2 small requests, then a big one. - translation_service_.Translate(1, 0, 0, text_chunks, "en", "fr", false); - translation_service_.Translate(1, 0, 1, text_chunks, "en", "fr", false); - // We need a string big enough to be more than 30KB on top of the other 2 - // requests, but to be less than 30KB when sent (that sizes includes the - // other parameters required by the translation server). - std::string twenty_nine_kb_string(29 * 1024, 'G'); - text_chunks.clear(); - text_chunks.push_back(ASCIIToUTF16(twenty_nine_kb_string)); - translation_service_.Translate(1, 0, 2, text_chunks, "en", "fr", false); - - // Without any task been run, the 2 first requests should have been sent. - TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(1); - TextChunks query_strings; - ExtractQueryStringsFromUploadData(url_fetcher, &query_strings); - ASSERT_EQ(2U, query_strings.size()); - EXPECT_EQ(one_kb_string, UTF16ToASCII(query_strings[0])); - EXPECT_EQ(one_kb_string, UTF16ToASCII(query_strings[1])); - - // Then when the task runs, the big request is sent. - MessageLoop::current()->RunAllPending(); - - url_fetcher = url_fetcher_factory_.GetFetcherByID(1); - query_strings.clear(); - ExtractQueryStringsFromUploadData(url_fetcher, &query_strings); - ASSERT_EQ(1U, query_strings.size()); - EXPECT_EQ(twenty_nine_kb_string, UTF16ToASCII(query_strings[0])); -} - -// Test mixing secure/insecure requests and that secure requests are always sent -// over HTTPS. -TEST_F(TranslationServiceTest, MixedHTTPAndHTTPS) { - const char* kUnsecureMessage = "Hello"; - const char* kSecureMessage = "Hello_Secure"; - - std::vector<string16> text_chunks; - text_chunks.push_back(ASCIIToUTF16(kUnsecureMessage)); - translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", false); - text_chunks.clear(); - text_chunks.push_back(ASCIIToUTF16(kSecureMessage)); - translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", true); - - // Run the task that creates the URLFetcher and send the request. - MessageLoop::current()->RunAllPending(); - - // We only get the last URLFetcher since we id them based on their routing id - // which we want to be the same in that test. We'll just check that as - // expected the last one is the HTTPS and contains only the secure string. - TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); - TextChunks query_strings; - ExtractQueryStringsFromUploadData(url_fetcher, &query_strings); - ASSERT_EQ(1U, query_strings.size()); - EXPECT_EQ(kSecureMessage, UTF16ToASCII(query_strings[0])); -} |