OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/glue/webkit_glue.h" | 5 #include "webkit/glue/webkit_glue.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
| 10 #include "base/platform_file.h" |
10 #include "base/sys_string_conversions.h" | 11 #include "base/sys_string_conversions.h" |
11 #include "chrome/browser/chrome_thread.h" | 12 #include "chrome/renderer/spellchecker/spellcheck.h" |
12 #include "chrome/browser/spellchecker.h" | |
13 #include "chrome/browser/spellchecker_platform_engine.h" | |
14 #include "chrome/common/chrome_paths.h" | 13 #include "chrome/common/chrome_paths.h" |
| 14 #include "chrome/common/spellcheck_common.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
16 | 16 |
17 namespace { | 17 namespace { |
18 const FilePath::CharType kTempCustomDictionaryFile[] = | |
19 FILE_PATH_LITERAL("temp_custom_dictionary.txt"); | |
20 } // namespace | |
21 | |
22 class SpellCheckTest : public testing::Test { | |
23 public: | |
24 SpellCheckTest() | |
25 : file_thread_(ChromeThread::FILE, &message_loop_), | |
26 io_thread_(ChromeThread::IO, &message_loop_) {} | |
27 | |
28 protected: | |
29 MessageLoop message_loop_; | |
30 | |
31 private: | |
32 ChromeThread file_thread_; | |
33 ChromeThread io_thread_; // To keep DCHECKs inside spell checker happy. | |
34 }; | |
35 | 18 |
36 // Represents a special initialization function used only for the unit tests | 19 // Represents a special initialization function used only for the unit tests |
37 // in this file. | 20 // in this file. |
38 extern void InitHunspellWithFiles(FILE* file_aff_hunspell, | 21 extern void InitHunspellWithFiles(FILE* file_aff_hunspell, |
39 FILE* file_dic_hunspell); | 22 FILE* file_dic_hunspell); |
40 | 23 |
41 FilePath GetHunspellDirectory() { | 24 FilePath GetHunspellDirectory() { |
42 FilePath hunspell_directory; | 25 FilePath hunspell_directory; |
43 if (!PathService::Get(base::DIR_SOURCE_ROOT, &hunspell_directory)) | 26 if (!PathService::Get(base::DIR_SOURCE_ROOT, &hunspell_directory)) |
44 return FilePath(); | 27 return FilePath(); |
45 | 28 |
46 hunspell_directory = hunspell_directory.AppendASCII("third_party"); | 29 hunspell_directory = hunspell_directory.AppendASCII("third_party"); |
47 hunspell_directory = hunspell_directory.AppendASCII("hunspell"); | 30 hunspell_directory = hunspell_directory.AppendASCII("hunspell"); |
48 hunspell_directory = hunspell_directory.AppendASCII("dictionaries"); | 31 hunspell_directory = hunspell_directory.AppendASCII("dictionaries"); |
49 return hunspell_directory; | 32 return hunspell_directory; |
50 } | 33 } |
51 | 34 |
| 35 class SpellCheckTest : public testing::Test { |
| 36 public: |
| 37 SpellCheckTest() { |
| 38 ReinitializeSpellCheck("en-US"); |
| 39 } |
| 40 |
| 41 void ReinitializeSpellCheck(const std::string& language) { |
| 42 spell_check_.reset(new SpellCheck()); |
| 43 |
| 44 FilePath hunspell_directory = GetHunspellDirectory(); |
| 45 EXPECT_FALSE(hunspell_directory.empty()); |
| 46 base::PlatformFile file = base::CreatePlatformFile( |
| 47 SpellCheckCommon::GetVersionedFileName(language, hunspell_directory), |
| 48 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL); |
| 49 spell_check_->Init( |
| 50 file, std::vector<std::string>(), language); |
| 51 } |
| 52 |
| 53 virtual ~SpellCheckTest() { |
| 54 } |
| 55 |
| 56 SpellCheck* spell_check() { return spell_check_.get(); } |
| 57 |
| 58 private: |
| 59 scoped_ptr<SpellCheck> spell_check_; |
| 60 }; |
| 61 |
52 // Operates unit tests for the webkit_glue::SpellCheckWord() function | 62 // Operates unit tests for the webkit_glue::SpellCheckWord() function |
53 // with the US English dictionary. | 63 // with the US English dictionary. |
54 // The unit tests in this function consist of: | 64 // The unit tests in this function consist of: |
55 // * Tests for the function with empty strings; | 65 // * Tests for the function with empty strings; |
56 // * Tests for the function with a valid English word; | 66 // * Tests for the function with a valid English word; |
57 // * Tests for the function with a valid non-English word; | 67 // * Tests for the function with a valid non-English word; |
58 // * Tests for the function with a valid English word with a preceding | 68 // * Tests for the function with a valid English word with a preceding |
59 // space character; | 69 // space character; |
60 // * Tests for the function with a valid English word with a preceding | 70 // * Tests for the function with a valid English word with a preceding |
61 // non-English word; | 71 // non-English word; |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 // [ROBUSTNESS] Two invalid English words concatenated with a contraction | 279 // [ROBUSTNESS] Two invalid English words concatenated with a contraction |
270 // character. | 280 // character. |
271 {L"ifmmp:ifmmp", false, 0, 11}, | 281 {L"ifmmp:ifmmp", false, 0, 11}, |
272 | 282 |
273 // [REGRESSION] Issue 13432: "Any word of 13 or 14 characters is not | 283 // [REGRESSION] Issue 13432: "Any word of 13 or 14 characters is not |
274 // spellcheck" <http://crbug.com/13432>. | 284 // spellcheck" <http://crbug.com/13432>. |
275 {L"qwertyuiopasd", false, 0, 13}, | 285 {L"qwertyuiopasd", false, 0, 13}, |
276 {L"qwertyuiopasdf", false, 0, 14}, | 286 {L"qwertyuiopasdf", false, 0, 14}, |
277 }; | 287 }; |
278 | 288 |
279 FilePath hunspell_directory = GetHunspellDirectory(); | |
280 ASSERT_FALSE(hunspell_directory.empty()); | |
281 | |
282 scoped_refptr<SpellChecker> spell_checker(new SpellChecker( | |
283 hunspell_directory, "en-US", NULL, FilePath())); | |
284 spell_checker->Initialize(); | |
285 message_loop_.RunAllPending(); | |
286 | |
287 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | 289 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { |
288 size_t input_length = 0; | 290 size_t input_length = 0; |
289 if (kTestCases[i].input != NULL) { | 291 if (kTestCases[i].input != NULL) { |
290 input_length = wcslen(kTestCases[i].input); | 292 input_length = wcslen(kTestCases[i].input); |
291 } | 293 } |
292 int misspelling_start; | 294 int misspelling_start; |
293 int misspelling_length; | 295 int misspelling_length; |
294 bool result = spell_checker->SpellCheckWord( | 296 bool result = spell_check()->SpellCheckWord( |
295 WideToUTF16(kTestCases[i].input).c_str(), | 297 WideToUTF16(kTestCases[i].input).c_str(), |
296 static_cast<int>(input_length), | 298 static_cast<int>(input_length), |
297 0, | 299 0, |
298 &misspelling_start, | 300 &misspelling_start, |
299 &misspelling_length, NULL); | 301 &misspelling_length, NULL); |
300 | 302 |
301 EXPECT_EQ(kTestCases[i].expected_result, result); | 303 EXPECT_EQ(kTestCases[i].expected_result, result); |
302 EXPECT_EQ(kTestCases[i].misspelling_start, misspelling_start); | 304 EXPECT_EQ(kTestCases[i].misspelling_start, misspelling_start); |
303 EXPECT_EQ(kTestCases[i].misspelling_length, misspelling_length); | 305 EXPECT_EQ(kTestCases[i].misspelling_length, misspelling_length); |
304 } | 306 } |
305 } | 307 } |
306 | 308 |
307 TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) { | 309 TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) { |
308 static const struct { | 310 static const struct { |
309 // A string to be tested. | 311 // A string to be tested. |
310 const wchar_t* input; | 312 const wchar_t* input; |
311 // An expected result for this test case. | 313 // An expected result for this test case. |
312 // * true: the input string does not have any invalid words. | 314 // * true: the input string does not have any invalid words. |
313 // * false: the input string has one or more invalid words. | 315 // * false: the input string has one or more invalid words. |
314 bool expected_result; | 316 bool expected_result; |
315 // The position and the length of the first invalid word. | 317 // The position and the length of the first invalid word. |
316 int misspelling_start; | 318 int misspelling_start; |
317 int misspelling_length; | 319 int misspelling_length; |
318 | 320 |
319 // A suggested word that should occur. | 321 // A suggested word that should occur. |
320 const wchar_t* suggested_word; | 322 const wchar_t* suggested_word; |
321 } kTestCases[] = { // A valid English word with a preceding whitespace | 323 } kTestCases[] = { |
322 // We need to have separate test cases here, since hunspell and the OS X | |
323 // spellchecking service occasionally differ on what they consider a valid | |
324 // suggestion for a given word, although these lists could likely be | |
325 // integrated somewhat. | |
326 #if defined(OS_MACOSX) | |
327 // These words come from the wikipedia page of the most commonly | |
328 // misspelled words in english. | |
329 // (http://en.wikipedia.org/wiki/Commonly_misspelled_words). | |
330 {L"absense", false, 0, 0, L"absence"}, | |
331 {L"acceptible", false, 0, 0, L"acceptable"}, | |
332 {L"accidentaly", false, 0, 0, L"accidentally"}, | |
333 {L"accomodate", false, 0, 0, L"accommodate"}, | |
334 {L"acheive", false, 0, 0, L"achieve"}, | |
335 {L"acknowlege", false, 0, 0, L"acknowledge"}, | |
336 {L"acquaintence", false, 0, 0, L"acquaintance"}, | |
337 {L"aquire", false, 0, 0, L"acquire"}, | |
338 {L"aquit", false, 0, 0, L"acquit"}, | |
339 {L"acrage", false, 0, 0, L"acreage"}, | |
340 {L"adress", false, 0, 0, L"address"}, | |
341 {L"adultary", false, 0, 0, L"adultery"}, | |
342 {L"advertize", false, 0, 0, L"advertise"}, | |
343 {L"adviseable", false, 0, 0, L"advisable"}, | |
344 {L"agression", false, 0, 0, L"aggression"}, | |
345 {L"alchohol", false, 0, 0, L"alcohol"}, | |
346 {L"alege", false, 0, 0, L"allege"}, | |
347 {L"allegaince", false, 0, 0, L"allegiance"}, | |
348 {L"allmost", false, 0, 0, L"almost"}, | |
349 // Ideally, this test should pass. It works in firefox, but not in hunspell | |
350 // or OS X. | |
351 // {L"alot", false, 0, 0, L"a lot"}, | |
352 {L"amatuer", false, 0, 0, L"amateur"}, | |
353 {L"ammend", false, 0, 0, L"amend"}, | |
354 {L"amung", false, 0, 0, L"among"}, | |
355 {L"anually", false, 0, 0, L"annually"}, | |
356 {L"apparant", false, 0, 0, L"apparent"}, | |
357 {L"artic", false, 0, 0, L"arctic"}, | |
358 {L"arguement", false, 0, 0, L"argument"}, | |
359 {L"athiest", false, 0, 0, L"atheist"}, | |
360 {L"athelete", false, 0, 0, L"athlete"}, | |
361 {L"avrage", false, 0, 0, L"average"}, | |
362 {L"awfull", false, 0, 0, L"awful"}, | |
363 {L"ballance", false, 0, 0, L"balance"}, | |
364 {L"basicly", false, 0, 0, L"basically"}, | |
365 {L"becuase", false, 0, 0, L"because"}, | |
366 {L"becomeing", false, 0, 0, L"becoming"}, | |
367 {L"befor", false, 0, 0, L"before"}, | |
368 {L"begining", false, 0, 0, L"beginning"}, | |
369 {L"beleive", false, 0, 0, L"believe"}, | |
370 {L"bellweather", false, 0, 0, L"bellwether"}, | |
371 {L"benifit", false, 0, 0, L"benefit"}, | |
372 {L"bouy", false, 0, 0, L"buoy"}, | |
373 {L"briliant", false, 0, 0, L"brilliant"}, | |
374 {L"burgler", false, 0, 0, L"burglar"}, | |
375 {L"camoflage", false, 0, 0, L"camouflage"}, | |
376 {L"carrer", false, 0, 0, L"career"}, | |
377 {L"carefull", false, 0, 0, L"careful"}, | |
378 {L"Carribean", false, 0, 0, L"Caribbean"}, | |
379 {L"catagory", false, 0, 0, L"category"}, | |
380 {L"cauhgt", false, 0, 0, L"caught"}, | |
381 {L"cieling", false, 0, 0, L"ceiling"}, | |
382 {L"cemetary", false, 0, 0, L"cemetery"}, | |
383 {L"certin", false, 0, 0, L"certain"}, | |
384 {L"changable", false, 0, 0, L"changeable"}, | |
385 {L"cheif", false, 0, 0, L"chief"}, | |
386 {L"citezen", false, 0, 0, L"citizen"}, | |
387 {L"collaegue", false, 0, 0, L"colleague"}, | |
388 {L"colum", false, 0, 0, L"column"}, | |
389 {L"comming", false, 0, 0, L"coming"}, | |
390 {L"commited", false, 0, 0, L"committed"}, | |
391 {L"compitition", false, 0, 0, L"competition"}, | |
392 {L"conceed", false, 0, 0, L"concede"}, | |
393 {L"congradulate", false, 0, 0, L"congratulate"}, | |
394 {L"consciencious", false, 0, 0, L"conscientious"}, | |
395 {L"concious", false, 0, 0, L"conscious"}, | |
396 {L"concensus", false, 0, 0, L"consensus"}, | |
397 {L"contraversy", false, 0, 0, L"controversy"}, | |
398 {L"conveniance", false, 0, 0, L"convenience"}, | |
399 {L"critecize", false, 0, 0, L"criticize"}, | |
400 {L"dacquiri", false, 0, 0, L"daiquiri"}, | |
401 {L"decieve", false, 0, 0, L"deceive"}, | |
402 {L"dicide", false, 0, 0, L"decide"}, | |
403 {L"definate", false, 0, 0, L"definite"}, | |
404 {L"definitly", false, 0, 0, L"definitely"}, | |
405 {L"deposite", false, 0, 0, L"deposit"}, | |
406 {L"desparate", false, 0, 0, L"desperate"}, | |
407 {L"develope", false, 0, 0, L"develop"}, | |
408 {L"diffrence", false, 0, 0, L"difference"}, | |
409 {L"dilema", false, 0, 0, L"dilemma"}, | |
410 {L"disapear", false, 0, 0, L"disappear"}, | |
411 {L"disapoint", false, 0, 0, L"disappoint"}, | |
412 {L"disasterous", false, 0, 0, L"disastrous"}, | |
413 {L"disipline", false, 0, 0, L"discipline"}, | |
414 {L"drunkeness", false, 0, 0, L"drunkenness"}, | |
415 {L"dumbell", false, 0, 0, L"dumbbell"}, | |
416 {L"durring", false, 0, 0, L"during"}, | |
417 {L"easely", false, 0, 0, L"easily"}, | |
418 {L"eigth", false, 0, 0, L"eight"}, | |
419 {L"embarass", false, 0, 0, L"embarrass"}, | |
420 {L"enviroment", false, 0, 0, L"environment"}, | |
421 {L"equiped", false, 0, 0, L"equipped"}, | |
422 {L"equiptment", false, 0, 0, L"equipment"}, | |
423 {L"exagerate", false, 0, 0, L"exaggerate"}, | |
424 {L"excede", false, 0, 0, L"exceed"}, | |
425 {L"exellent", false, 0, 0, L"excellent"}, | |
426 {L"exsept", false, 0, 0, L"except"}, | |
427 {L"exercize", false, 0, 0, L"exercise"}, | |
428 {L"exilerate", false, 0, 0, L"exhilarate"}, | |
429 {L"existance", false, 0, 0, L"existence"}, | |
430 {L"experiance", false, 0, 0, L"experience"}, | |
431 {L"experament", false, 0, 0, L"experiment"}, | |
432 {L"explaination", false, 0, 0, L"explanation"}, | |
433 {L"extreem", false, 0, 0, L"extreme"}, | |
434 {L"familier", false, 0, 0, L"familiar"}, | |
435 {L"facinating", false, 0, 0, L"fascinating"}, | |
436 {L"firey", false, 0, 0, L"fiery"}, | |
437 {L"finaly", false, 0, 0, L"finally"}, | |
438 {L"flourescent", false, 0, 0, L"fluorescent"}, | |
439 {L"foriegn", false, 0, 0, L"foreign"}, | |
440 {L"fourty", false, 0, 0, L"forty"}, | |
441 {L"foreward", false, 0, 0, L"forward"}, | |
442 {L"freind", false, 0, 0, L"friend"}, | |
443 {L"fullfil", false, 0, 0, L"fulfill"}, | |
444 {L"fundemental", false, 0, 0, L"fundamental"}, | |
445 {L"guage", false, 0, 0, L"gauge"}, | |
446 {L"generaly", false, 0, 0, L"generally"}, | |
447 {L"goverment", false, 0, 0, L"government"}, | |
448 {L"grammer", false, 0, 0, L"grammar"}, | |
449 {L"gratefull", false, 0, 0, L"grateful"}, | |
450 {L"garantee", false, 0, 0, L"guarantee"}, | |
451 {L"guidence", false, 0, 0, L"guidance"}, | |
452 {L"happyness", false, 0, 0, L"happiness"}, | |
453 {L"harrass", false, 0, 0, L"harass"}, | |
454 {L"heighth", false, 0, 0, L"height"}, | |
455 {L"heirarchy", false, 0, 0, L"hierarchy"}, | |
456 {L"humerous", false, 0, 0, L"humorous"}, | |
457 {L"hygene", false, 0, 0, L"hygiene"}, | |
458 {L"hipocrit", false, 0, 0, L"hypocrite"}, | |
459 {L"idenity", false, 0, 0, L"identity"}, | |
460 {L"ignorence", false, 0, 0, L"ignorance"}, | |
461 {L"imaginery", false, 0, 0, L"imaginary"}, | |
462 {L"immitate", false, 0, 0, L"imitate"}, | |
463 {L"immitation", false, 0, 0, L"imitation"}, | |
464 {L"imediately", false, 0, 0, L"immediately"}, | |
465 {L"incidently", false, 0, 0, L"incidentally"}, | |
466 {L"independant", false, 0, 0, L"independent"}, | |
467 {L"indispensible", false, 0, 0, L"indispensable"}, | |
468 {L"innoculate", false, 0, 0, L"inoculate"}, | |
469 {L"inteligence", false, 0, 0, L"intelligence"}, | |
470 {L"intresting", false, 0, 0, L"interesting"}, | |
471 {L"interuption", false, 0, 0, L"interruption"}, | |
472 {L"irrelevent", false, 0, 0, L"irrelevant"}, | |
473 {L"irritible", false, 0, 0, L"irritable"}, | |
474 {L"iland", false, 0, 0, L"island"}, | |
475 {L"jellous", false, 0, 0, L"jealous"}, | |
476 {L"knowlege", false, 0, 0, L"knowledge"}, | |
477 {L"labratory", false, 0, 0, L"laboratory"}, | |
478 {L"liesure", false, 0, 0, L"leisure"}, | |
479 {L"lenght", false, 0, 0, L"length"}, | |
480 {L"liason", false, 0, 0, L"liaison"}, | |
481 {L"libary", false, 0, 0, L"library"}, | |
482 {L"lisence", false, 0, 0, L"license"}, | |
483 {L"lonelyness", false, 0, 0, L"loneliness"}, | |
484 {L"lieing", false, 0, 0, L"lying"}, | |
485 {L"maintenence", false, 0, 0, L"maintenance"}, | |
486 {L"manuever", false, 0, 0, L"maneuver"}, | |
487 {L"marrige", false, 0, 0, L"marriage"}, | |
488 {L"mathmatics", false, 0, 0, L"mathematics"}, | |
489 {L"medcine", false, 0, 0, L"medicine"}, | |
490 {L"medeval", false, 0, 0, L"medieval"}, | |
491 {L"momento", false, 0, 0, L"memento"}, | |
492 {L"millenium", false, 0, 0, L"millennium"}, | |
493 {L"miniture", false, 0, 0, L"miniature"}, | |
494 {L"minite", false, 0, 0, L"minute"}, | |
495 {L"mischevous", false, 0, 0, L"mischievous"}, | |
496 {L"mispell", false, 0, 0, L"misspell"}, | |
497 // Maybe this one should pass, as it works in hunspell, but not in firefox. | |
498 // {L"misterius", false, 0, 0, L"mysterious"}, | |
499 {L"naturaly", false, 0, 0, L"naturally"}, | |
500 {L"neccessary", false, 0, 0, L"necessary"}, | |
501 {L"neice", false, 0, 0, L"niece"}, | |
502 {L"nieghbor", false, 0, 0, L"neighbor"}, | |
503 {L"nieghbour", false, 0, 0, L"neighbor"}, | |
504 {L"niether", false, 0, 0, L"neither"}, | |
505 {L"noticable", false, 0, 0, L"noticeable"}, | |
506 {L"occassion", false, 0, 0, L"occasion"}, | |
507 {L"occasionaly", false, 0, 0, L"occasionally"}, | |
508 {L"occurrance", false, 0, 0, L"occurrence"}, | |
509 {L"occured", false, 0, 0, L"occurred"}, | |
510 {L"oficial", false, 0, 0, L"official"}, | |
511 {L"offen", false, 0, 0, L"often"}, | |
512 {L"ommision", false, 0, 0, L"omission"}, | |
513 {L"oprate", false, 0, 0, L"operate"}, | |
514 {L"oppurtunity", false, 0, 0, L"opportunity"}, | |
515 {L"orignal", false, 0, 0, L"original"}, | |
516 {L"outragous", false, 0, 0, L"outrageous"}, | |
517 {L"parrallel", false, 0, 0, L"parallel"}, | |
518 {L"parliment", false, 0, 0, L"parliament"}, | |
519 {L"particurly", false, 0, 0, L"particularly"}, | |
520 {L"passtime", false, 0, 0, L"pastime"}, | |
521 {L"peculier", false, 0, 0, L"peculiar"}, | |
522 {L"percieve", false, 0, 0, L"perceive"}, | |
523 {L"pernament", false, 0, 0, L"permanent"}, | |
524 {L"perseverence", false, 0, 0, L"perseverance"}, | |
525 {L"personaly", false, 0, 0, L"personally"}, | |
526 {L"personell", false, 0, 0, L"personnel"}, | |
527 {L"persaude", false, 0, 0, L"persuade"}, | |
528 {L"pichure", false, 0, 0, L"picture"}, | |
529 {L"peice", false, 0, 0, L"piece"}, | |
530 {L"plagerize", false, 0, 0, L"plagiarize"}, | |
531 {L"playright", false, 0, 0, L"playwright"}, | |
532 {L"plesant", false, 0, 0, L"pleasant"}, | |
533 {L"pollitical", false, 0, 0, L"political"}, | |
534 {L"posession", false, 0, 0, L"possession"}, | |
535 {L"potatos", false, 0, 0, L"potatoes"}, | |
536 {L"practicle", false, 0, 0, L"practical"}, | |
537 {L"preceed", false, 0, 0, L"precede"}, | |
538 {L"predjudice", false, 0, 0, L"prejudice"}, | |
539 {L"presance", false, 0, 0, L"presence"}, | |
540 {L"privelege", false, 0, 0, L"privilege"}, | |
541 // This one should probably work. It does in FF and Hunspell. | |
542 // {L"probly", false, 0, 0, L"probably"}, | |
543 {L"proffesional", false, 0, 0, L"professional"}, | |
544 {L"professer", false, 0, 0, L"professor"}, | |
545 {L"promiss", false, 0, 0, L"promise"}, | |
546 {L"pronounciation", false, 0, 0, L"pronunciation"}, | |
547 {L"prufe", false, 0, 0, L"proof"}, | |
548 {L"psycology", false, 0, 0, L"psychology"}, | |
549 {L"publically", false, 0, 0, L"publicly"}, | |
550 {L"quanity", false, 0, 0, L"quantity"}, | |
551 {L"quarentine", false, 0, 0, L"quarantine"}, | |
552 {L"questionaire", false, 0, 0, L"questionnaire"}, | |
553 {L"readible", false, 0, 0, L"readable"}, | |
554 {L"realy", false, 0, 0, L"really"}, | |
555 {L"recieve", false, 0, 0, L"receive"}, | |
556 {L"reciept", false, 0, 0, L"receipt"}, | |
557 {L"reconize", false, 0, 0, L"recognize"}, | |
558 {L"recomend", false, 0, 0, L"recommend"}, | |
559 {L"refered", false, 0, 0, L"referred"}, | |
560 {L"referance", false, 0, 0, L"reference"}, | |
561 {L"relevent", false, 0, 0, L"relevant"}, | |
562 {L"religous", false, 0, 0, L"religious"}, | |
563 {L"repitition", false, 0, 0, L"repetition"}, | |
564 {L"restarant", false, 0, 0, L"restaurant"}, | |
565 {L"rythm", false, 0, 0, L"rhythm"}, | |
566 {L"rediculous", false, 0, 0, L"ridiculous"}, | |
567 {L"sacrefice", false, 0, 0, L"sacrifice"}, | |
568 {L"saftey", false, 0, 0, L"safety"}, | |
569 {L"sissors", false, 0, 0, L"scissors"}, | |
570 {L"secratary", false, 0, 0, L"secretary"}, | |
571 {L"sieze", false, 0, 0, L"seize"}, | |
572 {L"seperate", false, 0, 0, L"separate"}, | |
573 {L"sargent", false, 0, 0, L"sergeant"}, | |
574 {L"shineing", false, 0, 0, L"shining"}, | |
575 {L"similer", false, 0, 0, L"similar"}, | |
576 {L"sinceerly", false, 0, 0, L"sincerely"}, | |
577 {L"speach", false, 0, 0, L"speech"}, | |
578 {L"stoping", false, 0, 0, L"stopping"}, | |
579 {L"strenght", false, 0, 0, L"strength"}, | |
580 {L"succede", false, 0, 0, L"succeed"}, | |
581 {L"succesful", false, 0, 0, L"successful"}, | |
582 {L"supercede", false, 0, 0, L"supersede"}, | |
583 {L"surelly", false, 0, 0, L"surely"}, | |
584 {L"suprise", false, 0, 0, L"surprise"}, | |
585 {L"temperture", false, 0, 0, L"temperature"}, | |
586 {L"temprary", false, 0, 0, L"temporary"}, | |
587 {L"tomatos", false, 0, 0, L"tomatoes"}, | |
588 {L"tommorrow", false, 0, 0, L"tomorrow"}, | |
589 {L"tounge", false, 0, 0, L"tongue"}, | |
590 {L"truely", false, 0, 0, L"truly"}, | |
591 {L"twelth", false, 0, 0, L"twelfth"}, | |
592 {L"tyrany", false, 0, 0, L"tyranny"}, | |
593 {L"underate", false, 0, 0, L"underrate"}, | |
594 {L"untill", false, 0, 0, L"until"}, | |
595 {L"unuseual", false, 0, 0, L"unusual"}, | |
596 {L"upholstry", false, 0, 0, L"upholstery"}, | |
597 {L"usible", false, 0, 0, L"usable"}, | |
598 {L"useing", false, 0, 0, L"using"}, | |
599 {L"usualy", false, 0, 0, L"usually"}, | |
600 {L"vaccuum", false, 0, 0, L"vacuum"}, | |
601 {L"vegatarian", false, 0, 0, L"vegetarian"}, | |
602 {L"vehical", false, 0, 0, L"vehicle"}, | |
603 {L"visious", false, 0, 0, L"vicious"}, | |
604 {L"villege", false, 0, 0, L"village"}, | |
605 {L"wierd", false, 0, 0, L"weird"}, | |
606 {L"wellcome", false, 0, 0, L"welcome"}, | |
607 {L"wellfare", false, 0, 0, L"welfare"}, | |
608 {L"wilfull", false, 0, 0, L"willful"}, | |
609 {L"withold", false, 0, 0, L"withhold"}, | |
610 {L"writting", false, 0, 0, L"writing"}, | |
611 #else | |
612 {L"ello", false, 0, 0, L"hello"}, | 324 {L"ello", false, 0, 0, L"hello"}, |
613 {L"ello", false, 0, 0, L"cello"}, | 325 {L"ello", false, 0, 0, L"cello"}, |
614 {L"wate", false, 0, 0, L"water"}, | 326 {L"wate", false, 0, 0, L"water"}, |
615 {L"wate", false, 0, 0, L"waste"}, | 327 {L"wate", false, 0, 0, L"waste"}, |
616 {L"wate", false, 0, 0, L"sate"}, | 328 {L"wate", false, 0, 0, L"sate"}, |
617 {L"wate", false, 0, 0, L"ate"}, | 329 {L"wate", false, 0, 0, L"ate"}, |
618 {L"jum", false, 0, 0, L"jump"}, | 330 {L"jum", false, 0, 0, L"jump"}, |
619 {L"jum", false, 0, 0, L"hum"}, | 331 {L"jum", false, 0, 0, L"hum"}, |
620 {L"jum", false, 0, 0, L"sum"}, | 332 {L"jum", false, 0, 0, L"sum"}, |
621 {L"jum", false, 0, 0, L"um"}, | 333 {L"jum", false, 0, 0, L"um"}, |
622 #endif // !OS_MACOSX | |
623 // TODO (Sidchat): add many more examples. | 334 // TODO (Sidchat): add many more examples. |
624 }; | 335 }; |
625 | 336 |
626 FilePath hunspell_directory = GetHunspellDirectory(); | |
627 ASSERT_FALSE(hunspell_directory.empty()); | |
628 | |
629 scoped_refptr<SpellChecker> spell_checker(new SpellChecker( | |
630 hunspell_directory, "en-US", NULL, FilePath())); | |
631 spell_checker->Initialize(); | |
632 message_loop_.RunAllPending(); | |
633 | |
634 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | 337 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { |
635 std::vector<string16> suggestions; | 338 std::vector<string16> suggestions; |
636 size_t input_length = 0; | 339 size_t input_length = 0; |
637 if (kTestCases[i].input != NULL) { | 340 if (kTestCases[i].input != NULL) { |
638 input_length = wcslen(kTestCases[i].input); | 341 input_length = wcslen(kTestCases[i].input); |
639 } | 342 } |
640 int misspelling_start; | 343 int misspelling_start; |
641 int misspelling_length; | 344 int misspelling_length; |
642 bool result = spell_checker->SpellCheckWord( | 345 bool result = spell_check()->SpellCheckWord( |
643 WideToUTF16(kTestCases[i].input).c_str(), | 346 WideToUTF16(kTestCases[i].input).c_str(), |
644 static_cast<int>(input_length), | 347 static_cast<int>(input_length), |
645 0, | 348 0, |
646 &misspelling_start, | 349 &misspelling_start, |
647 &misspelling_length, | 350 &misspelling_length, |
648 &suggestions); | 351 &suggestions); |
649 | 352 |
650 // Check for spelling. | 353 // Check for spelling. |
651 EXPECT_EQ(kTestCases[i].expected_result, result); | 354 EXPECT_EQ(kTestCases[i].expected_result, result); |
652 | 355 |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 // Vietnamese | 593 // Vietnamese |
891 "vi-VN", | 594 "vi-VN", |
892 L"Nhi\x1EC7m v\x1EE5 c\x1EE7\x0061 " | 595 L"Nhi\x1EC7m v\x1EE5 c\x1EE7\x0061 " |
893 L"Google la \x0111\x1EC3 t\x1ED5 ch\x1EE9\x0063 " | 596 L"Google la \x0111\x1EC3 t\x1ED5 ch\x1EE9\x0063 " |
894 L"c\x00E1\x0063 th\x00F4ng tin c\x1EE7\x0061 " | 597 L"c\x00E1\x0063 th\x00F4ng tin c\x1EE7\x0061 " |
895 L"th\x1EBF gi\x1EDBi va l\x00E0m cho n\x00F3 universal c\x00F3 " | 598 L"th\x1EBF gi\x1EDBi va l\x00E0m cho n\x00F3 universal c\x00F3 " |
896 L"th\x1EC3 truy c\x1EADp va h\x1EEFu d\x1EE5ng h\x01A1n." | 599 L"th\x1EC3 truy c\x1EADp va h\x1EEFu d\x1EE5ng h\x01A1n." |
897 }, | 600 }, |
898 }; | 601 }; |
899 | 602 |
900 FilePath hunspell_directory = GetHunspellDirectory(); | |
901 ASSERT_FALSE(hunspell_directory.empty()); | |
902 | |
903 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | 603 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { |
904 scoped_refptr<SpellChecker> spell_checker(new SpellChecker( | 604 ReinitializeSpellCheck(kTestCases[i].language); |
905 hunspell_directory, kTestCases[i].language, NULL, FilePath())); | |
906 spell_checker->Initialize(); | |
907 message_loop_.RunAllPending(); | |
908 | |
909 size_t input_length = 0; | 605 size_t input_length = 0; |
910 if (kTestCases[i].input != NULL) | 606 if (kTestCases[i].input != NULL) |
911 input_length = wcslen(kTestCases[i].input); | 607 input_length = wcslen(kTestCases[i].input); |
912 | 608 |
913 int misspelling_start = 0; | 609 int misspelling_start = 0; |
914 int misspelling_length = 0; | 610 int misspelling_length = 0; |
915 bool result = spell_checker->SpellCheckWord( | 611 bool result = spell_check()->SpellCheckWord( |
916 WideToUTF16(kTestCases[i].input).c_str(), | 612 WideToUTF16(kTestCases[i].input).c_str(), |
917 static_cast<int>(input_length), | 613 static_cast<int>(input_length), |
918 0, | 614 0, |
919 &misspelling_start, | 615 &misspelling_start, |
920 &misspelling_length, NULL); | 616 &misspelling_length, NULL); |
921 | 617 |
922 EXPECT_EQ(true, result) << kTestCases[i].language; | 618 EXPECT_EQ(true, result) << kTestCases[i].language; |
923 EXPECT_EQ(0, misspelling_start); | 619 EXPECT_EQ(0, misspelling_start); |
924 EXPECT_EQ(0, misspelling_length); | 620 EXPECT_EQ(0, misspelling_length); |
925 } | 621 } |
926 } | 622 } |
927 | 623 |
928 // This test Adds words to the SpellChecker and veifies that it remembers them. | |
929 TEST_F(SpellCheckTest, DISABLED_SpellCheckAddToDictionary_EN_US) { | |
930 static const struct { | |
931 // A string to be added to SpellChecker. | |
932 const wchar_t* word_to_add; | |
933 } kTestCases[] = { // Words to be added to the SpellChecker. | |
934 {L"Googley"}, | |
935 {L"Googleplex"}, | |
936 {L"Googler"}, | |
937 }; | |
938 | |
939 FilePath custom_dictionary_file(kTempCustomDictionaryFile); | |
940 FilePath hunspell_directory = GetHunspellDirectory(); | |
941 ASSERT_FALSE(hunspell_directory.empty()); | |
942 | |
943 scoped_refptr<SpellChecker> spell_checker(new SpellChecker( | |
944 hunspell_directory, "en-US", NULL, custom_dictionary_file)); | |
945 spell_checker->Initialize(); | |
946 message_loop_.RunAllPending(); | |
947 | |
948 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | |
949 // Add the word to spellchecker. | |
950 spell_checker->AddWord(WideToUTF16(kTestCases[i].word_to_add)); | |
951 | |
952 // Now check whether it is added to Spellchecker. | |
953 std::vector<string16> suggestions; | |
954 size_t input_length = 0; | |
955 if (kTestCases[i].word_to_add != NULL) { | |
956 input_length = wcslen(kTestCases[i].word_to_add); | |
957 } | |
958 int misspelling_start; | |
959 int misspelling_length; | |
960 bool result = spell_checker->SpellCheckWord( | |
961 WideToUTF16(kTestCases[i].word_to_add).c_str(), | |
962 static_cast<int>(input_length), | |
963 0, | |
964 &misspelling_start, | |
965 &misspelling_length, | |
966 &suggestions); | |
967 | |
968 // Check for spelling. | |
969 EXPECT_TRUE(result); | |
970 } | |
971 | |
972 // Now initialize another spellchecker to see that AddToWord is permanent. | |
973 scoped_refptr<SpellChecker> spell_checker_new(new SpellChecker( | |
974 hunspell_directory, "en-US", NULL, custom_dictionary_file)); | |
975 spell_checker->Initialize(); | |
976 message_loop_.RunAllPending(); | |
977 | |
978 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | |
979 // Now check whether it is added to Spellchecker. | |
980 std::vector<string16> suggestions; | |
981 size_t input_length = 0; | |
982 if (kTestCases[i].word_to_add != NULL) { | |
983 input_length = wcslen(kTestCases[i].word_to_add); | |
984 } | |
985 int misspelling_start; | |
986 int misspelling_length; | |
987 bool result = spell_checker_new->SpellCheckWord( | |
988 WideToUTF16(kTestCases[i].word_to_add).c_str(), | |
989 static_cast<int>(input_length), | |
990 0, | |
991 &misspelling_start, | |
992 &misspelling_length, | |
993 &suggestions); | |
994 | |
995 // Check for spelling. | |
996 EXPECT_TRUE(result); | |
997 } | |
998 | |
999 // Remove the temp custom dictionary file. | |
1000 file_util::Delete(custom_dictionary_file, false); | |
1001 } | |
1002 | |
1003 // SpellChecker should suggest custome words for misspelled words. | |
1004 TEST_F(SpellCheckTest, DISABLED_SpellCheckSuggestionsAddToDictionary_EN_US) { | |
1005 static const struct { | |
1006 // A string to be added to SpellChecker. | |
1007 const wchar_t* word_to_add; | |
1008 } kTestCases[] = { // word to be added to SpellChecker | |
1009 {L"Googley"}, | |
1010 {L"Googleplex"}, | |
1011 {L"Googler"}, | |
1012 }; | |
1013 | |
1014 FilePath custom_dictionary_file(kTempCustomDictionaryFile); | |
1015 FilePath hunspell_directory = GetHunspellDirectory(); | |
1016 ASSERT_FALSE(hunspell_directory.empty()); | |
1017 | |
1018 scoped_refptr<SpellChecker> spell_checker(new SpellChecker( | |
1019 hunspell_directory, "en-US", NULL, custom_dictionary_file)); | |
1020 spell_checker->Initialize(); | |
1021 message_loop_.RunAllPending(); | |
1022 | |
1023 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | |
1024 // Add the word to spellchecker. | |
1025 spell_checker->AddWord(WideToUTF16(kTestCases[i].word_to_add)); | |
1026 } | |
1027 | |
1028 // Now check to see whether the custom words are suggested for | |
1029 // misspelled but similar words. | |
1030 static const struct { | |
1031 // A string to be tested. | |
1032 const wchar_t* input; | |
1033 // An expected result for this test case. | |
1034 // * true: the input string does not have any invalid words. | |
1035 // * false: the input string has one or more invalid words. | |
1036 bool expected_result; | |
1037 // The position and the length of the first invalid word. | |
1038 int misspelling_start; | |
1039 int misspelling_length; | |
1040 | |
1041 // A suggested word that should occur. | |
1042 const wchar_t* suggested_word; | |
1043 } kTestCasesToBeTested[] = { | |
1044 {L"oogley", false, 0, 0, L"Googley"}, | |
1045 {L"oogler", false, 0, 0, L"Googler"}, | |
1046 {L"oogleplex", false, 0, 0, L"Googleplex"}, | |
1047 }; | |
1048 | |
1049 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCasesToBeTested); ++i) { | |
1050 std::vector<string16> suggestions; | |
1051 size_t input_length = 0; | |
1052 if (kTestCasesToBeTested[i].input != NULL) { | |
1053 input_length = wcslen(kTestCasesToBeTested[i].input); | |
1054 } | |
1055 int misspelling_start; | |
1056 int misspelling_length; | |
1057 bool result = spell_checker->SpellCheckWord( | |
1058 WideToUTF16(kTestCasesToBeTested[i].input).c_str(), | |
1059 static_cast<int>(input_length), | |
1060 0, | |
1061 &misspelling_start, | |
1062 &misspelling_length, | |
1063 &suggestions); | |
1064 | |
1065 // Check for spelling. | |
1066 EXPECT_EQ(result, kTestCasesToBeTested[i].expected_result); | |
1067 | |
1068 // Check if the suggested words occur. | |
1069 bool suggested_word_is_present = false; | |
1070 for (int j=0; j < static_cast<int>(suggestions.size()); j++) { | |
1071 if (suggestions.at(j).compare( | |
1072 WideToUTF16(kTestCasesToBeTested[i].suggested_word)) == | |
1073 0) { | |
1074 suggested_word_is_present = true; | |
1075 break; | |
1076 } | |
1077 } | |
1078 | |
1079 EXPECT_TRUE(suggested_word_is_present); | |
1080 } | |
1081 | |
1082 // Remove the temp custom dictionary file. | |
1083 file_util::Delete(custom_dictionary_file, false); | |
1084 } | |
1085 | |
1086 TEST_F(SpellCheckTest, GetAutoCorrectionWord_EN_US) { | 624 TEST_F(SpellCheckTest, GetAutoCorrectionWord_EN_US) { |
1087 static const struct { | 625 static const struct { |
1088 // A misspelled word. | 626 // A misspelled word. |
1089 const char* input; | 627 const char* input; |
1090 | 628 |
1091 // An expected result for this test case. | 629 // An expected result for this test case. |
1092 // Should be an empty string if there are no suggestions for auto correct. | 630 // Should be an empty string if there are no suggestions for auto correct. |
1093 const char* expected_result; | 631 const char* expected_result; |
1094 } kTestCases[] = { | 632 } kTestCases[] = { |
1095 {"teh", "the"}, | 633 {"teh", "the"}, |
1096 {"moer", "more"}, | 634 {"moer", "more"}, |
1097 {"watre", "water"}, | 635 {"watre", "water"}, |
1098 {"noen", ""}, | 636 {"noen", ""}, |
1099 {"what", ""}, | 637 {"what", ""}, |
1100 }; | 638 }; |
1101 | 639 spell_check()->EnableAutoSpellCorrect(true); |
1102 FilePath hunspell_directory = GetHunspellDirectory(); | |
1103 ASSERT_FALSE(hunspell_directory.empty()); | |
1104 | |
1105 scoped_refptr<SpellChecker> spell_checker(new SpellChecker( | |
1106 hunspell_directory, "en-US", NULL, FilePath())); | |
1107 spell_checker->EnableAutoSpellCorrect(true); | |
1108 spell_checker->Initialize(); | |
1109 message_loop_.RunAllPending(); | |
1110 | 640 |
1111 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | 641 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { |
1112 string16 misspelled_word(UTF8ToUTF16(kTestCases[i].input)); | 642 string16 misspelled_word(UTF8ToUTF16(kTestCases[i].input)); |
1113 string16 expected_autocorrect_word( | 643 string16 expected_autocorrect_word( |
1114 UTF8ToUTF16(kTestCases[i].expected_result)); | 644 UTF8ToUTF16(kTestCases[i].expected_result)); |
1115 string16 autocorrect_word = spell_checker->GetAutoCorrectionWord( | 645 string16 autocorrect_word = spell_check()->GetAutoCorrectionWord( |
1116 misspelled_word, 0); | 646 misspelled_word, 0); |
1117 | 647 |
1118 // Check for spelling. | 648 // Check for spelling. |
1119 EXPECT_EQ(expected_autocorrect_word, autocorrect_word); | 649 EXPECT_EQ(expected_autocorrect_word, autocorrect_word); |
1120 } | 650 } |
1121 } | 651 } |
1122 | 652 |
1123 #if defined(OS_MACOSX) | 653 } // namespace |
1124 // Tests that words are properly ignored. Currently only enabled on OS X as it | |
1125 // is the only platform to support ignoring words. Note that in this test, we | |
1126 // supply a non-zero doc_tag, in order to test that ignored words are matched to | |
1127 // the correct document. | |
1128 TEST_F(SpellCheckTest, IgnoreWords_EN_US) { | |
1129 static const struct { | |
1130 // A misspelled word. | |
1131 const char* input; | |
1132 bool input_result; | |
1133 } kTestCases[] = { | |
1134 {"teh", false}, | |
1135 {"moer", false}, | |
1136 {"watre", false}, | |
1137 {"noen", false}, | |
1138 }; | |
1139 | |
1140 FilePath hunspell_directory = GetHunspellDirectory(); | |
1141 ASSERT_FALSE(hunspell_directory.empty()); | |
1142 | |
1143 scoped_refptr<SpellChecker> spell_checker(new SpellChecker( | |
1144 hunspell_directory, "en-US", NULL, FilePath())); | |
1145 spell_checker->Initialize(); | |
1146 message_loop_.RunAllPending(); | |
1147 | |
1148 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | |
1149 string16 word(UTF8ToUTF16(kTestCases[i].input)); | |
1150 std::vector<string16> suggestions; | |
1151 size_t input_length = 0; | |
1152 if (kTestCases[i].input != NULL) { | |
1153 input_length = word.length(); | |
1154 } | |
1155 int misspelling_start; | |
1156 int misspelling_length; | |
1157 | |
1158 int doc_tag = SpellCheckerPlatform::GetDocumentTag(); | |
1159 bool result = spell_checker->SpellCheckWord(word.c_str(), | |
1160 static_cast<int>(input_length), | |
1161 doc_tag, | |
1162 &misspelling_start, | |
1163 &misspelling_length, | |
1164 &suggestions); | |
1165 | |
1166 // The word should show up as misspelled. | |
1167 EXPECT_EQ(kTestCases[i].input_result, result); | |
1168 | |
1169 // Ignore the word. | |
1170 SpellCheckerPlatform::IgnoreWord(word); | |
1171 | |
1172 // Spellcheck again. | |
1173 result = spell_checker->SpellCheckWord(word.c_str(), | |
1174 static_cast<int>(input_length), | |
1175 doc_tag, | |
1176 &misspelling_start, | |
1177 &misspelling_length, | |
1178 &suggestions); | |
1179 | |
1180 // The word should now show up as correctly spelled. | |
1181 EXPECT_EQ(!(kTestCases[i].input_result), result); | |
1182 | |
1183 // Close the docuemnt. Any words that we had previously ignored should no | |
1184 // longer be ignored and thus should show up as misspelled. | |
1185 SpellCheckerPlatform::CloseDocumentWithTag(doc_tag); | |
1186 | |
1187 // Spellcheck one more time. | |
1188 result = spell_checker->SpellCheckWord(word.c_str(), | |
1189 static_cast<int>(input_length), | |
1190 doc_tag, | |
1191 &misspelling_start, | |
1192 &misspelling_length, | |
1193 &suggestions); | |
1194 | |
1195 // The word should now show be spelled wrong again | |
1196 EXPECT_EQ(kTestCases[i].input_result, result); | |
1197 } | |
1198 } // Test IgnoreWords_EN_US | |
1199 #endif // OS_MACOSX | |
OLD | NEW |