| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2010 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/json/json_writer.h" |
| 6 #include "base/stl_util-inl.h" |
| 7 #include "base/string_tokenizer.h" |
| 8 #include "base/string_util.h" |
| 9 #include "chrome/browser/net/test_url_fetcher_factory.h" |
| 10 #include "chrome/browser/renderer_host/translation_service.h" |
| 11 #include "chrome/common/render_messages.h" |
| 12 #include "ipc/ipc_message.h" |
| 13 #include "net/base/escape.h" |
| 14 #include "net/url_request/url_request_status.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 |
| 17 typedef std::vector<string16> TextChunks; |
| 18 typedef std::vector<TextChunks> TextChunksList; |
| 19 |
| 20 class TestMessageSender : public IPC::Message::Sender { |
| 21 public: |
| 22 virtual ~TestMessageSender() { |
| 23 ClearMessages(); |
| 24 } |
| 25 |
| 26 virtual bool Send(IPC::Message* msg) { |
| 27 messages_.push_back(msg); |
| 28 return true; |
| 29 } |
| 30 |
| 31 size_t message_count() const { return messages_.size(); } |
| 32 |
| 33 void GetMessageParameters(size_t message_index, int* routing_id, |
| 34 int* work_id, int* error_id, |
| 35 std::vector<string16>* text_chunks) { |
| 36 ASSERT_LT(message_index, messages_.size()); |
| 37 *routing_id = messages_.at(message_index)->routing_id(); |
| 38 ViewMsg_TranslateTextReponse::Read(messages_.at(message_index), |
| 39 work_id, error_id, text_chunks); |
| 40 } |
| 41 |
| 42 void ClearMessages() { |
| 43 STLDeleteElements(&messages_); |
| 44 messages_.clear(); |
| 45 } |
| 46 |
| 47 std::vector<IPC::Message*> messages_; |
| 48 MessageLoop message_loop_; |
| 49 }; |
| 50 |
| 51 class TestTranslationService : public TranslationService { |
| 52 public: |
| 53 explicit TestTranslationService(IPC::Message::Sender* message_sender) |
| 54 : TranslationService(message_sender) {} |
| 55 |
| 56 virtual int GetSendRequestDelay() const { |
| 57 return 0; |
| 58 } |
| 59 }; |
| 60 |
| 61 class TranslationServiceTest : public testing::Test { |
| 62 public: |
| 63 TranslationServiceTest() : translation_service_(&message_sender_) {} |
| 64 |
| 65 virtual void SetUp() { |
| 66 URLFetcher::set_factory(&url_fetcher_factory_); |
| 67 } |
| 68 |
| 69 virtual void TearDown() { |
| 70 URLFetcher::set_factory(NULL); |
| 71 } |
| 72 |
| 73 protected: |
| 74 TestURLFetcherFactory url_fetcher_factory_; |
| 75 TestMessageSender message_sender_; |
| 76 TestTranslationService translation_service_; |
| 77 }; |
| 78 |
| 79 static void SimulateErrorResponse(TestURLFetcher* url_fetcher, |
| 80 int response_code) { |
| 81 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher, |
| 82 url_fetcher->original_url(), |
| 83 URLRequestStatus(), |
| 84 response_code, |
| 85 ResponseCookies(), |
| 86 std::string()); |
| 87 } |
| 88 |
| 89 // Merges the strings in |text_chunks| into the string that the translation |
| 90 // server received. |
| 91 static string16 BuildResponseString(const TextChunks& text_chunks) { |
| 92 string16 text; |
| 93 for (size_t i = 0; i < text_chunks.size(); ++i) { |
| 94 text.append(ASCIIToUTF16("<a _CR_TR_ id='")); |
| 95 text.append(IntToString16(i)); |
| 96 text.append(ASCIIToUTF16("'>")); |
| 97 text.append(text_chunks.at(i)); |
| 98 text.append(ASCIIToUTF16("</a>")); |
| 99 } |
| 100 return text; |
| 101 } |
| 102 |
| 103 static void SimulateSuccessfulResponse(TestURLFetcher* url_fetcher, |
| 104 const TextChunksList& text_chunks_list) { |
| 105 scoped_ptr<ListValue> list(new ListValue()); |
| 106 for (TextChunksList::const_iterator iter = text_chunks_list.begin(); |
| 107 iter != text_chunks_list.end(); ++iter) { |
| 108 list->Append(Value::CreateStringValueFromUTF16(BuildResponseString(*iter))); |
| 109 } |
| 110 |
| 111 std::string response; |
| 112 base::JSONWriter::Write(list.get(), false, &response); |
| 113 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher, |
| 114 url_fetcher->original_url(), |
| 115 URLRequestStatus(), |
| 116 200, |
| 117 ResponseCookies(), |
| 118 response); |
| 119 } |
| 120 |
| 121 static void SimulateSimpleSuccessfulResponse(TestURLFetcher* url_fetcher, |
| 122 const char* const* c_text_chunks, |
| 123 size_t text_chunks_length) { |
| 124 TextChunks text_chunks; |
| 125 for (size_t i = 0; i < text_chunks_length; i++) |
| 126 text_chunks.push_back(ASCIIToUTF16(c_text_chunks[i])); |
| 127 |
| 128 string16 text = BuildResponseString(text_chunks); |
| 129 |
| 130 std::string response; |
| 131 base::JSONWriter::Write(Value::CreateStringValueFromUTF16(text), |
| 132 false, &response); |
| 133 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher, |
| 134 url_fetcher->original_url(), |
| 135 URLRequestStatus(), |
| 136 200, |
| 137 ResponseCookies(), |
| 138 response); |
| 139 } |
| 140 |
| 141 // Parses the upload data from |url_fetcher| and puts the value for the q |
| 142 // parameters in |text_chunks|. |
| 143 static void ExtractQueryStringsFromUploadData(TestURLFetcher* url_fetcher, |
| 144 TextChunks* text_chunks) { |
| 145 std::string upload_data = url_fetcher->upload_data(); |
| 146 |
| 147 CStringTokenizer str_tok(upload_data.c_str(), upload_data.c_str() + |
| 148 upload_data.length(), "&"); |
| 149 while (str_tok.GetNext()) { |
| 150 std::string tok = str_tok.token(); |
| 151 if (tok.size() > 1U && tok.at(0) == 'q' && tok.at(1) == '=') |
| 152 text_chunks->push_back(UnescapeForHTML(ASCIIToUTF16(tok.substr(2)))); |
| 153 } |
| 154 } |
| 155 |
| 156 TEST_F(TranslationServiceTest, MergeTestChunks) { |
| 157 std::vector<string16> input; |
| 158 input.push_back(ASCIIToUTF16("Hello")); |
| 159 string16 result = TranslationService::MergeTextChunks(input); |
| 160 EXPECT_EQ(ASCIIToUTF16("Hello"), result); |
| 161 input.push_back(ASCIIToUTF16(" my name")); |
| 162 input.push_back(ASCIIToUTF16(" is")); |
| 163 input.push_back(ASCIIToUTF16(" Jay.")); |
| 164 result = TranslationService::MergeTextChunks(input); |
| 165 EXPECT_EQ(ASCIIToUTF16("<a _CR_TR_ id='0'>Hello</a>" |
| 166 "<a _CR_TR_ id='1'> my name</a>" |
| 167 "<a _CR_TR_ id='2'> is</a>" |
| 168 "<a _CR_TR_ id='3'> Jay.</a>"), |
| 169 result); |
| 170 } |
| 171 |
| 172 TEST_F(TranslationServiceTest, RemoveTag) { |
| 173 const char* kInputs[] = { |
| 174 "", "Hello", "<a ></a>", " <a href='http://www.google.com'> Link </a>", |
| 175 "<a >Link", "<a link</a>", "<a id=1><a id=1>broken</a></a>", |
| 176 "<a id=1>broken</a></a> bad bad</a>", |
| 177 }; |
| 178 const char* kExpected[] = { |
| 179 "", "Hello", "", " Link ", "Link", "<a link", "broken", "broken bad bad" |
| 180 }; |
| 181 |
| 182 ASSERT_EQ(arraysize(kInputs), arraysize(kExpected)); |
| 183 for (size_t i = 0; i < arraysize(kInputs); ++i) { |
| 184 SCOPED_TRACE(::testing::Message::Message() << "Iteration " << i); |
| 185 string16 input = ASCIIToUTF16(kInputs[i]); |
| 186 string16 output = TranslationService::RemoveTag(input); |
| 187 EXPECT_EQ(ASCIIToUTF16(kExpected[i]), output); |
| 188 } |
| 189 } |
| 190 |
| 191 // Tests that we deal correctly with the various results the translation server |
| 192 // can return, including the buggy ones. |
| 193 TEST_F(TranslationServiceTest, SplitTestChunks) { |
| 194 // Simple case. |
| 195 std::vector<string16> text_chunks; |
| 196 TranslationService::SplitTextChunks(ASCIIToUTF16("Hello"), &text_chunks); |
| 197 ASSERT_EQ(1U, text_chunks.size()); |
| 198 EXPECT_EQ(ASCIIToUTF16("Hello"), text_chunks[0]); |
| 199 |
| 200 text_chunks.clear(); |
| 201 |
| 202 // Multiple chunks case, correct syntax. |
| 203 TranslationService::SplitTextChunks( |
| 204 ASCIIToUTF16("<a _CR_TR_ id='0'>Bonjour</a>" |
| 205 "<a _CR_TR_ id='1'> mon nom</a>" |
| 206 "<a _CR_TR_ id='2'> est</a>" |
| 207 "<a _CR_TR_ id='3'> Jay.</a>"), &text_chunks); |
| 208 ASSERT_EQ(4U, text_chunks.size()); |
| 209 EXPECT_EQ(ASCIIToUTF16("Bonjour"), text_chunks[0]); |
| 210 EXPECT_EQ(ASCIIToUTF16(" mon nom"), text_chunks[1]); |
| 211 EXPECT_EQ(ASCIIToUTF16(" est"), text_chunks[2]); |
| 212 EXPECT_EQ(ASCIIToUTF16(" Jay."), text_chunks[3]); |
| 213 text_chunks.clear(); |
| 214 |
| 215 // Multiple chunks case, duplicate and unbalanced tags. |
| 216 // For info, original input: |
| 217 // <a _CR_TRANSLATE_ id='0'> Experience </a><a _CR_TRANSLATE_ id='1'>Nexus One |
| 218 // </a><a _CR_TRANSLATE_ id='2'>, the new Android phone from Google</a> |
| 219 TranslationService::SplitTextChunks( |
| 220 ASCIIToUTF16("<a _CR_TR_ id='0'>Experience</a> <a _CR_TR_ id='1'>Nexus" |
| 221 "<a _CR_TR_ id='2'> One,</a></a> <a _CR_TR_ id='2'>the new " |
| 222 "Android Phone</a>"), &text_chunks); |
| 223 ASSERT_EQ(3U, text_chunks.size()); |
| 224 EXPECT_EQ(ASCIIToUTF16("Experience "), text_chunks[0]); |
| 225 EXPECT_EQ(ASCIIToUTF16("Nexus One, "), text_chunks[1]); |
| 226 EXPECT_EQ(ASCIIToUTF16("the new Android Phone"), text_chunks[2]); |
| 227 text_chunks.clear(); |
| 228 } |
| 229 |
| 230 // Tests that a successful translate works as expected. |
| 231 TEST_F(TranslationServiceTest, SimpleSuccessfulTranslation) { |
| 232 const char* const kEnglishTextChunks[] = { |
| 233 "An atom is talking to another atom:", |
| 234 "- I think I lost an electron.", |
| 235 "- Are you sure?", |
| 236 "- I am positive." |
| 237 }; |
| 238 |
| 239 const char* const kFrenchTextChunks[] = { |
| 240 "Un atome parle a un autre atome:", |
| 241 "- Je crois que j'ai perdu un electron.", |
| 242 "- T'es sur?", |
| 243 "- Je suis positif." // Note that the joke translates poorly in French. |
| 244 }; |
| 245 |
| 246 // Translate some text unsecurely. |
| 247 std::vector<string16> text_chunks; |
| 248 for (size_t i = 0; i < arraysize(kEnglishTextChunks); ++i) |
| 249 text_chunks.push_back(ASCIIToUTF16(kEnglishTextChunks[i])); |
| 250 translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", false); |
| 251 |
| 252 TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); |
| 253 // The message was too short to triger the sending of a request to the |
| 254 // translation request. A task has been pushed for that. |
| 255 EXPECT_TRUE(url_fetcher == NULL); |
| 256 MessageLoop::current()->RunAllPending(); |
| 257 |
| 258 // Now the task has been run, the message should have been sent. |
| 259 url_fetcher = url_fetcher_factory_.GetFetcherByID(0); |
| 260 ASSERT_TRUE(url_fetcher != NULL); |
| 261 // Check the URL is HTTP. |
| 262 EXPECT_FALSE(url_fetcher->original_url().SchemeIsSecure()); |
| 263 |
| 264 // Let's simulate the JSON response from the server. |
| 265 SimulateSimpleSuccessfulResponse(url_fetcher, &(kFrenchTextChunks[0]), |
| 266 arraysize(kFrenchTextChunks)); |
| 267 |
| 268 // This should have triggered a ViewMsg_TranslateTextReponse message. |
| 269 ASSERT_EQ(1U, message_sender_.message_count()); |
| 270 |
| 271 // Test the message has the right translation. |
| 272 int routing_id = 0; |
| 273 int work_id = 0; |
| 274 int error_id = 0; |
| 275 std::vector<string16> translated_text_chunks; |
| 276 message_sender_.GetMessageParameters(0, &routing_id, &work_id, &error_id, |
| 277 &translated_text_chunks); |
| 278 EXPECT_EQ(0, routing_id); |
| 279 EXPECT_EQ(0, error_id); |
| 280 ASSERT_EQ(arraysize(kFrenchTextChunks), translated_text_chunks.size()); |
| 281 for (size_t i = 0; i < arraysize(kFrenchTextChunks); ++i) |
| 282 EXPECT_EQ(ASCIIToUTF16(kFrenchTextChunks[i]), translated_text_chunks[i]); |
| 283 } |
| 284 |
| 285 // Tests that on failure we send the expected error message. |
| 286 TEST_F(TranslationServiceTest, FailedTranslation) { |
| 287 std::vector<string16> text_chunks; |
| 288 text_chunks.push_back(ASCIIToUTF16("Hello")); |
| 289 translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", false); |
| 290 |
| 291 // Run the task that creates the URLFetcher and sends the request. |
| 292 MessageLoop::current()->RunAllPending(); |
| 293 |
| 294 TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); |
| 295 ASSERT_TRUE(url_fetcher != NULL); |
| 296 SimulateErrorResponse(url_fetcher, 500); |
| 297 |
| 298 // This should have triggered a ViewMsg_TranslateTextReponse message. |
| 299 ASSERT_EQ(1U, message_sender_.message_count()); |
| 300 |
| 301 // Test the message has some error. |
| 302 int routing_id = 0; |
| 303 int work_id = 0; |
| 304 int error_id = 0; |
| 305 std::vector<string16> translated_text_chunks; |
| 306 message_sender_.GetMessageParameters(0, &routing_id, &work_id, &error_id, |
| 307 &translated_text_chunks); |
| 308 |
| 309 EXPECT_NE(0, error_id); // Anything but 0 means there was an error. |
| 310 EXPECT_TRUE(translated_text_chunks.empty()); |
| 311 } |
| 312 |
| 313 // Tests that a secure translation is done over a secure connection. |
| 314 TEST_F(TranslationServiceTest, SecureTranslation) { |
| 315 std::vector<string16> text_chunks; |
| 316 text_chunks.push_back(ASCIIToUTF16("Hello")); |
| 317 translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", |
| 318 true /* secure */); |
| 319 |
| 320 // Run the task that creates the URLFetcher and sends the request. |
| 321 MessageLoop::current()->RunAllPending(); |
| 322 |
| 323 TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); |
| 324 ASSERT_TRUE(url_fetcher != NULL); |
| 325 EXPECT_TRUE(url_fetcher->original_url().SchemeIsSecure()); |
| 326 } |
| 327 |
| 328 // Test mixing requests from different renderers. |
| 329 TEST_F(TranslationServiceTest, MultipleRVRequests) { |
| 330 const char* const kExpectedRV1_1 = "Bonjour RV1"; |
| 331 const char* const kExpectedRV1_2 = "Encore bonjour RV1"; |
| 332 const char* const kExpectedRV1_3 = "Encore bonjour a nouveau RV1"; |
| 333 const char* const kExpectedRV2 = "Bonjour RV2"; |
| 334 const char* const kExpectedRV3 = "Bonjour RV3"; |
| 335 |
| 336 TextChunks text_chunks; |
| 337 text_chunks.push_back(ASCIIToUTF16("Hello RV1")); |
| 338 text_chunks.push_back(ASCIIToUTF16("Hello again RV1")); |
| 339 translation_service_.Translate(1, 0, 0, text_chunks, "en", "fr", false); |
| 340 text_chunks.clear(); |
| 341 text_chunks.push_back(ASCIIToUTF16("Hello RV2")); |
| 342 translation_service_.Translate(2, 0, 0, text_chunks, "en", "fr", false); |
| 343 text_chunks.clear(); |
| 344 text_chunks.push_back(ASCIIToUTF16("Hello again one more time RV1")); |
| 345 translation_service_.Translate(1, 0, 1, text_chunks, "en", "fr", false); |
| 346 text_chunks.clear(); |
| 347 text_chunks.push_back(ASCIIToUTF16("Hello RV3")); |
| 348 translation_service_.Translate(3, 0, 0, text_chunks, "en", "fr", false); |
| 349 |
| 350 // Run the tasks that create the URLFetcher and send the requests. |
| 351 MessageLoop::current()->RunAllPending(); |
| 352 |
| 353 // We should have 3 pending URL fetchers. (The 2 translate requests for RV1 |
| 354 // should have been grouped in 1.) Simluate the translation server responses. |
| 355 TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(1); |
| 356 ASSERT_TRUE(url_fetcher != NULL); |
| 357 |
| 358 TextChunksList text_chunks_list; |
| 359 text_chunks.clear(); |
| 360 text_chunks.push_back(ASCIIToUTF16(kExpectedRV1_1)); |
| 361 text_chunks.push_back(ASCIIToUTF16(kExpectedRV1_2)); |
| 362 text_chunks_list.push_back(text_chunks); |
| 363 text_chunks.clear(); |
| 364 text_chunks.push_back(ASCIIToUTF16(kExpectedRV1_3)); |
| 365 text_chunks_list.push_back(text_chunks); |
| 366 SimulateSuccessfulResponse(url_fetcher, text_chunks_list); |
| 367 |
| 368 url_fetcher = url_fetcher_factory_.GetFetcherByID(2); |
| 369 ASSERT_TRUE(url_fetcher != NULL); |
| 370 SimulateSimpleSuccessfulResponse(url_fetcher, &kExpectedRV2, 1); |
| 371 |
| 372 url_fetcher = url_fetcher_factory_.GetFetcherByID(3); |
| 373 ASSERT_TRUE(url_fetcher != NULL); |
| 374 SimulateSimpleSuccessfulResponse(url_fetcher, &kExpectedRV3, 1); |
| 375 |
| 376 // This should have triggered 4 ViewMsg_TranslateTextReponse messages. |
| 377 ASSERT_EQ(4U, message_sender_.message_count()); |
| 378 |
| 379 const int kExpectedRoutingID[] = { 1, 1, 2, 3 }; |
| 380 const int kExpectedWorkID[] = { 0, 1, 0, 0 }; |
| 381 const size_t kExpectedStringCount[] = { 2U, 1U, 1U, 1U }; |
| 382 |
| 383 // Test the messages have the expected content. |
| 384 for (size_t i = 0; i < 4; i++) { |
| 385 SCOPED_TRACE(::testing::Message::Message() << "Iteration " << i); |
| 386 int routing_id = 0; |
| 387 int work_id = 0; |
| 388 int error_id = 0; |
| 389 std::vector<string16> translated_text_chunks; |
| 390 message_sender_.GetMessageParameters(i, &routing_id, &work_id, &error_id, |
| 391 &translated_text_chunks); |
| 392 EXPECT_EQ(kExpectedRoutingID[i], routing_id); |
| 393 EXPECT_EQ(kExpectedWorkID[i], work_id); |
| 394 EXPECT_EQ(0, error_id); |
| 395 EXPECT_EQ(kExpectedStringCount[i], translated_text_chunks.size()); |
| 396 // TODO(jcampan): we should compare the strings. |
| 397 } |
| 398 } |
| 399 |
| 400 // Tests sending more than the max size. |
| 401 TEST_F(TranslationServiceTest, MoreThanMaxSizeRequests) { |
| 402 std::string one_kb_string(1024U, 'A'); |
| 403 TextChunks text_chunks; |
| 404 text_chunks.push_back(ASCIIToUTF16(one_kb_string)); |
| 405 // Send 2 small requests, than a big one. |
| 406 translation_service_.Translate(1, 0, 0, text_chunks, "en", "fr", false); |
| 407 translation_service_.Translate(1, 0, 1, text_chunks, "en", "fr", false); |
| 408 // We need a string big enough to be more than 30KB on top of the other 2 |
| 409 // requests, but to be less than 30KB when sent (that sizes includes the |
| 410 // other parameters required by the translation server). |
| 411 std::string twenty_nine_kb_string(29 * 1024, 'G'); |
| 412 text_chunks.clear(); |
| 413 text_chunks.push_back(ASCIIToUTF16(twenty_nine_kb_string)); |
| 414 translation_service_.Translate(1, 0, 2, text_chunks, "en", "fr", false); |
| 415 |
| 416 // Without any task been run, the 2 first requests should have been sent. |
| 417 TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(1); |
| 418 TextChunks query_strings; |
| 419 ExtractQueryStringsFromUploadData(url_fetcher, &query_strings); |
| 420 ASSERT_EQ(2U, query_strings.size()); |
| 421 EXPECT_EQ(one_kb_string, UTF16ToASCII(query_strings[0])); |
| 422 EXPECT_EQ(one_kb_string, UTF16ToASCII(query_strings[1])); |
| 423 |
| 424 // Then when the task runs, the big request is sent. |
| 425 MessageLoop::current()->RunAllPending(); |
| 426 |
| 427 url_fetcher = url_fetcher_factory_.GetFetcherByID(1); |
| 428 query_strings.clear(); |
| 429 ExtractQueryStringsFromUploadData(url_fetcher, &query_strings); |
| 430 ASSERT_EQ(1U, query_strings.size()); |
| 431 EXPECT_EQ(twenty_nine_kb_string, UTF16ToASCII(query_strings[0])); |
| 432 } |
| 433 |
| 434 // Test mixing secure/insecure requests and that secure requests are always sent |
| 435 // over HTTPS. |
| 436 TEST_F(TranslationServiceTest, MixedHTTPAndHTTPS) { |
| 437 const char* kUnsecureMessage = "Hello"; |
| 438 const char* kSecureMessage = "Hello_Secure"; |
| 439 |
| 440 std::vector<string16> text_chunks; |
| 441 text_chunks.push_back(ASCIIToUTF16(kUnsecureMessage)); |
| 442 translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", false); |
| 443 text_chunks.clear(); |
| 444 text_chunks.push_back(ASCIIToUTF16(kSecureMessage)); |
| 445 translation_service_.Translate(0, 0, 0, text_chunks, "en", "fr", true); |
| 446 |
| 447 // Run the task that creates the URLFetcher and send the request. |
| 448 MessageLoop::current()->RunAllPending(); |
| 449 |
| 450 // We only get the last URLFetcher since we id them based on their routing id |
| 451 // which we want to be the same in that test. We'll just check that as |
| 452 // expected the last one is the HTTPS and contains only the secure string. |
| 453 TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); |
| 454 TextChunks query_strings; |
| 455 ExtractQueryStringsFromUploadData(url_fetcher, &query_strings); |
| 456 ASSERT_EQ(1U, query_strings.size()); |
| 457 EXPECT_EQ(kSecureMessage, UTF16ToASCII(query_strings[0])); |
| 458 } |
| OLD | NEW |