a5510a6fca2bd6606f9452ebe92986e254d1c684
[platform/framework/web/crosswalk.git] / src / chrome / browser / spellchecker / spellcheck_platform_mac_unittest.cc
1 // Copyright (c) 2011 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/bind.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/strings/string_util.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/spellchecker/spellcheck_platform_mac.h"
10 #include "chrome/common/spellcheck_result.h"
11 #include "content/public/test/test_utils.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace {
15
16 class SpellcheckMacTest: public testing::Test {
17  public:
18   SpellcheckMacTest()
19       : callback_(base::Bind(&SpellcheckMacTest::CompletionCallback,
20                              base::Unretained(this))),
21         callback_finished_(false) {}
22
23   void WaitForCallback() {
24     content::RunMessageLoop();
25   }
26
27   std::vector<SpellCheckResult> results_;
28   spellcheck_mac::TextCheckCompleteCallback callback_;
29   bool callback_finished_;
30
31  private:
32   void QuitMessageLoop() {
33     CHECK(base::MessageLoop::current() == &message_loop_);
34     base::MessageLoop::current()->Quit();
35   }
36
37   void CompletionCallback(const std::vector<SpellCheckResult>& results) {
38     results_ = results;
39     callback_finished_ = true;
40     message_loop_.PostTask(FROM_HERE,
41                            base::Bind(&SpellcheckMacTest::QuitMessageLoop,
42                                       base::Unretained(this)));
43   }
44
45   base::MessageLoopForUI message_loop_;
46   spellcheck_mac::ScopedEnglishLanguageForTest scoped_language_;
47 };
48
49 // Tests that words are properly ignored. Currently only enabled on OS X as it
50 // is the only platform to support ignoring words. Note that in this test, we
51 // supply a non-zero doc_tag, in order to test that ignored words are matched to
52 // the correct document.
53 TEST_F(SpellcheckMacTest, IgnoreWords_EN_US) {
54   const char* kTestCases[] = {
55     "teh",
56     "morblier",
57     "watre",
58     "noooen",
59   };
60
61   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
62     const base::string16 word(base::ASCIIToUTF16(kTestCases[i]));
63     const int doc_tag = spellcheck_mac::GetDocumentTag();
64
65     // The word should show up as misspelled.
66     EXPECT_FALSE(spellcheck_mac::CheckSpelling(word, doc_tag)) << word;
67
68     // Ignore the word.
69     spellcheck_mac::IgnoreWord(word);
70
71     // The word should now show up as correctly spelled.
72     EXPECT_TRUE(spellcheck_mac::CheckSpelling(word, doc_tag)) << word;
73
74     // Close the docuemnt. Any words that we had previously ignored should no
75     // longer be ignored and thus should show up as misspelled.
76     spellcheck_mac::CloseDocumentWithTag(doc_tag);
77
78     // The word should now show be spelled wrong again
79     EXPECT_FALSE(spellcheck_mac::CheckSpelling(word, doc_tag)) << word;
80   }
81 }  // Test IgnoreWords_EN_US
82
83 TEST_F(SpellcheckMacTest, SpellCheckSuggestions_EN_US) {
84   static const struct {
85     const char* input;           // A string to be tested.
86     const char* suggested_word;  // A suggested word that should occur.
87   } kTestCases[] = {
88     // We need to have separate test cases here, since hunspell and the OS X
89     // spellchecking service occasionally differ on what they consider a valid
90     // suggestion for a given word, although these lists could likely be
91     // integrated somewhat. The test cases for non-Mac are in
92     // chrome/renderer/spellcheck_unittest.cc
93     // These words come from the wikipedia page of the most commonly
94     // misspelled words in english.
95     // (http://en.wikipedia.org/wiki/Commonly_misspelled_words).
96     // However, 10.6 loads multiple dictionaries and enables many non-English
97     // dictionaries by default. As a result, we have removed from the list any
98     // word that is marked as correct because it is correct in another
99     // language.
100     {"absense", "absence"},
101     {"acceptible", "acceptable"},
102     {"accidentaly", "accidentally"},
103     {"acheive", "achieve"},
104     {"acknowlege", "acknowledge"},
105     {"acquaintence", "acquaintance"},
106     {"aquire", "acquire"},
107     {"aquit", "acquit"},
108     {"acrage", "acreage"},
109     {"adultary", "adultery"},
110     {"advertize", "advertise"},
111     {"adviseable", "advisable"},
112     {"alchohol", "alcohol"},
113     {"alege", "allege"},
114     {"allegaince", "allegiance"},
115     {"allmost", "almost"},
116     // Ideally, this test should pass. It works in firefox, but not in hunspell
117     // or OS X.
118     // {"alot", "a lot"},
119     {"amatuer", "amateur"},
120     {"ammend", "amend"},
121     {"amung", "among"},
122     {"anually", "annually"},
123     {"apparant", "apparent"},
124     {"artic", "arctic"},
125     {"arguement", "argument"},
126     {"athiest", "atheist"},
127     {"athelete", "athlete"},
128     {"avrage", "average"},
129     {"awfull", "awful"},
130     {"ballance", "balance"},
131     {"basicly", "basically"},
132     {"becuase", "because"},
133     {"becomeing", "becoming"},
134     {"befor", "before"},
135     {"begining", "beginning"},
136     {"beleive", "believe"},
137     {"bellweather", "bellwether"},
138     {"benifit", "benefit"},
139     {"bouy", "buoy"},
140     {"briliant", "brilliant"},
141     {"burgler", "burglar"},
142     {"camoflage", "camouflage"},
143     {"carefull", "careful"},
144     {"Carribean", "Caribbean"},
145     {"catagory", "category"},
146     {"cauhgt", "caught"},
147     {"cieling", "ceiling"},
148     {"cemetary", "cemetery"},
149     {"certin", "certain"},
150     {"changable", "changeable"},
151     {"cheif", "chief"},
152     {"citezen", "citizen"},
153     {"collaegue", "colleague"},
154     {"colum", "column"},
155     {"comming", "coming"},
156     {"commited", "committed"},
157     {"compitition", "competition"},
158     {"conceed", "concede"},
159     {"congradulate", "congratulate"},
160     {"consciencious", "conscientious"},
161     {"concious", "conscious"},
162     {"concensus", "consensus"},
163     {"contraversy", "controversy"},
164     {"conveniance", "convenience"},
165     {"critecize", "criticize"},
166     {"dacquiri", "daiquiri"},
167     {"decieve", "deceive"},
168     {"dicide", "decide"},
169     {"definate", "definite"},
170     {"definitly", "definitely"},
171     {"desparate", "desperate"},
172     {"develope", "develop"},
173     {"diffrence", "difference"},
174     {"disapear", "disappear"},
175     {"disapoint", "disappoint"},
176     {"disasterous", "disastrous"},
177     {"disipline", "discipline"},
178     {"drunkeness", "drunkenness"},
179     {"dumbell", "dumbbell"},
180     {"easely", "easily"},
181     {"eigth", "eight"},
182     {"embarass", "embarrass"},
183     {"enviroment", "environment"},
184     {"equiped", "equipped"},
185     {"equiptment", "equipment"},
186     {"exagerate", "exaggerate"},
187     {"exellent", "excellent"},
188     {"exsept", "except"},
189     {"exercize", "exercise"},
190     {"exilerate", "exhilarate"},
191     {"existance", "existence"},
192     {"experiance", "experience"},
193     {"experament", "experiment"},
194     {"explaination", "explanation"},
195     {"facinating", "fascinating"},
196     {"firey", "fiery"},
197     {"finaly", "finally"},
198     {"flourescent", "fluorescent"},
199     {"foriegn", "foreign"},
200     {"fourty", "forty"},
201     {"foreward", "forward"},
202     {"freind", "friend"},
203     {"fundemental", "fundamental"},
204     {"guage", "gauge"},
205     {"generaly", "generally"},
206     {"goverment", "government"},
207     {"gratefull", "grateful"},
208     {"garantee", "guarantee"},
209     {"guidence", "guidance"},
210     {"happyness", "happiness"},
211     {"harrass", "harass"},
212     {"heighth", "height"},
213     {"heirarchy", "hierarchy"},
214     {"humerous", "humorous"},
215     {"hygene", "hygiene"},
216     {"hipocrit", "hypocrite"},
217     {"idenity", "identity"},
218     {"ignorence", "ignorance"},
219     {"imaginery", "imaginary"},
220     {"immitate", "imitate"},
221     {"immitation", "imitation"},
222     {"imediately", "immediately"},
223     {"incidently", "incidentally"},
224     {"independant", "independent"},
225     {"indispensible", "indispensable"},
226     {"innoculate", "inoculate"},
227     {"inteligence", "intelligence"},
228     {"intresting", "interesting"},
229     {"interuption", "interruption"},
230     {"irrelevent", "irrelevant"},
231     {"irritible", "irritable"},
232     {"jellous", "jealous"},
233     {"knowlege", "knowledge"},
234     {"labratory", "laboratory"},
235     {"lenght", "length"},
236     {"liason", "liaison"},
237     {"libary", "library"},
238     {"lisence", "license"},
239     {"lonelyness", "loneliness"},
240     {"lieing", "lying"},
241     {"maintenence", "maintenance"},
242     {"manuever", "maneuver"},
243     {"marrige", "marriage"},
244     {"mathmatics", "mathematics"},
245     {"medcine", "medicine"},
246     {"miniture", "miniature"},
247     {"minite", "minute"},
248     {"mischevous", "mischievous"},
249     {"mispell", "misspell"},
250     // Maybe this one should pass, as it works in hunspell, but not in firefox.
251     // {"misterius", "mysterious"},
252     {"naturaly", "naturally"},
253     {"neccessary", "necessary"},
254     {"neice", "niece"},
255     {"nieghbor", "neighbor"},
256     {"nieghbour", "neighbor"},
257     {"niether", "neither"},
258     {"noticable", "noticeable"},
259     {"occassion", "occasion"},
260     {"occasionaly", "occasionally"},
261     {"occurrance", "occurrence"},
262     {"occured", "occurred"},
263     {"ommision", "omission"},
264     {"oppurtunity", "opportunity"},
265     {"outragous", "outrageous"},
266     {"parrallel", "parallel"},
267     {"parliment", "parliament"},
268     {"particurly", "particularly"},
269     {"passtime", "pastime"},
270     {"peculier", "peculiar"},
271     {"percieve", "perceive"},
272     {"pernament", "permanent"},
273     {"perseverence", "perseverance"},
274     {"personaly", "personally"},
275     {"persaude", "persuade"},
276     {"pichure", "picture"},
277     {"peice", "piece"},
278     {"plagerize", "plagiarize"},
279     {"playright", "playwright"},
280     {"plesant", "pleasant"},
281     {"pollitical", "political"},
282     {"posession", "possession"},
283     {"potatos", "potatoes"},
284     {"practicle", "practical"},
285     {"preceed", "precede"},
286     {"predjudice", "prejudice"},
287     {"presance", "presence"},
288     {"privelege", "privilege"},
289     // This one should probably work. It does in FF and Hunspell.
290     // {"probly", "probably"},
291     {"proffesional", "professional"},
292     {"promiss", "promise"},
293     {"pronounciation", "pronunciation"},
294     {"prufe", "proof"},
295     {"psycology", "psychology"},
296     {"publically", "publicly"},
297     {"quanity", "quantity"},
298     {"quarentine", "quarantine"},
299     {"questionaire", "questionnaire"},
300     {"readible", "readable"},
301     {"realy", "really"},
302     {"recieve", "receive"},
303     {"reciept", "receipt"},
304     {"reconize", "recognize"},
305     {"recomend", "recommend"},
306     {"refered", "referred"},
307     {"referance", "reference"},
308     {"relevent", "relevant"},
309     {"religous", "religious"},
310     {"repitition", "repetition"},
311     {"restarant", "restaurant"},
312     {"rythm", "rhythm"},
313     {"rediculous", "ridiculous"},
314     {"sacrefice", "sacrifice"},
315     {"saftey", "safety"},
316     {"sissors", "scissors"},
317     {"secratary", "secretary"},
318     {"seperate", "separate"},
319     {"sargent", "sergeant"},
320     {"shineing", "shining"},
321     {"similer", "similar"},
322     {"sinceerly", "sincerely"},
323     {"speach", "speech"},
324     {"strenght", "strength"},
325     {"succesful", "successful"},
326     {"supercede", "supersede"},
327     {"surelly", "surely"},
328     {"suprise", "surprise"},
329     {"temperture", "temperature"},
330     {"temprary", "temporary"},
331     {"tommorrow", "tomorrow"},
332     {"tounge", "tongue"},
333     {"truely", "truly"},
334     {"twelth", "twelfth"},
335     {"tyrany", "tyranny"},
336     {"underate", "underrate"},
337     {"untill", "until"},
338     {"unuseual", "unusual"},
339     {"upholstry", "upholstery"},
340     {"usible", "usable"},
341     {"useing", "using"},
342     {"usualy", "usually"},
343     {"vaccuum", "vacuum"},
344     {"vegatarian", "vegetarian"},
345     {"vehical", "vehicle"},
346     {"visious", "vicious"},
347     {"villege", "village"},
348     {"wierd", "weird"},
349     {"wellcome", "welcome"},
350     {"wellfare", "welfare"},
351     {"wilfull", "willful"},
352     {"withold", "withhold"},
353     {"writting", "writing"},
354   };
355
356   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
357     const base::string16 word(base::ASCIIToUTF16(kTestCases[i].input));
358     EXPECT_FALSE(spellcheck_mac::CheckSpelling(word, 0)) << word;
359
360     // Check if the suggested words occur.
361     std::vector<base::string16> suggestions;
362     spellcheck_mac::FillSuggestionList(word, &suggestions);
363     bool suggested_word_is_present = false;
364     const base::string16 suggested_word(
365         base::ASCIIToUTF16(kTestCases[i].suggested_word));
366     for (size_t j = 0; j < suggestions.size(); j++) {
367       if (suggestions[j].compare(suggested_word) == 0) {
368         suggested_word_is_present = true;
369         break;
370       }
371     }
372     EXPECT_TRUE(suggested_word_is_present) << suggested_word;
373   }
374 }
375
376 // The OSX spellchecker returns non-spellcheck results when invoked on a
377 // sentence, specifically an NSTextCheckingTypeOrthography result indicating
378 // the language used in that sentence. Test that it is filtered out from
379 // RequestTextCheck results.
380 TEST_F(SpellcheckMacTest, SpellCheckIgnoresOrthography)  {
381   base::string16 test_string(base::ASCIIToUTF16("Icland is awesome."));
382   spellcheck_mac::RequestTextCheck(0, test_string, callback_);
383   WaitForCallback();
384   EXPECT_TRUE(callback_finished_);
385   EXPECT_EQ(1U, results_.size());
386 }
387
388 }  // namespace