1 /* Copyright (c) 2007 Eric Scott Albright
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19  * THE SOFTWARE.
20  */
21 
22 #ifndef __ENCHANTDICTIONARYTESTFIXTURE
23 #define __ENCHANTDICTIONARYTESTFIXTURE
24 
25 #include "EnchantBrokerTestFixture.h"
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <string>
32 #include <vector>
33 
34 static EnchantDict*
MockProviderRequestEmptyMockDictionary(EnchantProvider *,const char *)35 MockProviderRequestEmptyMockDictionary(EnchantProvider *, const char *)
36 {
37     EnchantDict* dict = g_new0(EnchantDict, 1);
38     dict->user_data = NULL;
39     dict->check = NULL;
40     dict->suggest = NULL;
41     dict->add_to_personal = NULL;
42     dict->add_to_session = NULL;
43     dict->store_replacement = NULL;
44 
45     return dict;
46 }
47 
EmptyDictionary_ProviderConfiguration(EnchantProvider * me,const char *)48 static void EmptyDictionary_ProviderConfiguration (EnchantProvider * me, const char *)
49 {
50      me->request_dict = MockProviderRequestEmptyMockDictionary;
51      me->dispose_dict = MockProviderDisposeDictionary;
52 }
53 
54 
55 static char**
MockDictionarySuggest(EnchantDict *,const char * const word,size_t len,size_t * out_n_suggs)56 MockDictionarySuggest (EnchantDict * ,
57                        const char *const word,
58 		               size_t len,
59                        size_t * out_n_suggs)
60 {
61     *out_n_suggs = 4;
62 
63     char **sugg_arr = g_new0 (char *, *out_n_suggs + 1);
64     for(size_t i=0; i<*out_n_suggs;++i){
65         if(len == -1) {
66             sugg_arr[i] = g_strdup (word);
67         }
68         else {
69             sugg_arr[i] = g_strndup (word, (gsize)len);
70         }
71         sugg_arr[i][0] = 'a' + (char)i;
72     }
73     return sugg_arr;
74 }
75 
76 static EnchantDict*
MockProviderRequestBasicMockDictionary(EnchantProvider * me,const char * tag)77 MockProviderRequestBasicMockDictionary(EnchantProvider *me, const char *tag)
78 {
79 
80     EnchantDict* dict = MockProviderRequestEmptyMockDictionary(me, tag);
81     dict->suggest = MockDictionarySuggest;
82     return dict;
83 }
84 
85 
BasicDictionary_ProviderConfiguration(EnchantProvider * me,const char *)86 static void BasicDictionary_ProviderConfiguration (EnchantProvider * me, const char *)
87 {
88      me->request_dict = MockProviderRequestBasicMockDictionary;
89      me->dispose_dict = MockProviderDisposeDictionary;
90 }
91 
92 struct EnchantDictionaryTestFixture : EnchantBrokerTestFixture
93 {
94     EnchantDict* _dict;
95     EnchantDict* _pwl;
96     std::string _pwlFileName;
97     std::string origLangEnv;
98     bool hasLangEnv;
99     std::string languageTag;
100 
101     //Setup
102     EnchantDictionaryTestFixture(ConfigureHook userConfiguration=BasicDictionary_ProviderConfiguration, const std::string& languageTag="qaa"):
EnchantBrokerTestFixtureEnchantDictionaryTestFixture103         EnchantBrokerTestFixture(userConfiguration),
104         languageTag(languageTag)
105     {
106         InitializeTestDictionary();
107         _pwl = RequestPersonalDictionary();
108         _pwlFileName = GetLastPersonalDictionaryFileName();
109 
110         hasLangEnv = (g_getenv("LANG") != NULL);
111         if(hasLangEnv)
112         {
113             origLangEnv = std::string(g_getenv("LANG"));
114         }
115     }
116 
117     //Teardown
~EnchantDictionaryTestFixtureEnchantDictionaryTestFixture118     ~EnchantDictionaryTestFixture(){
119         FreeTestDictionary();
120         FreeDictionary(_pwl);
121         ResetLocale();
122     }
123 
SetLocaleEnchantDictionaryTestFixture124     void SetLocale(const std::string& locale)
125     {
126         g_setenv("LANG", locale.c_str(), TRUE);
127     }
128 
ResetLocaleEnchantDictionaryTestFixture129     void ResetLocale()
130     {
131         if(hasLangEnv)
132         {
133             g_setenv("LANG", origLangEnv.c_str(), TRUE);
134         }
135         else{
136             g_unsetenv("LANG");
137         }
138     }
139 
ReloadTestDictionaryEnchantDictionaryTestFixture140     void ReloadTestDictionary()
141     {
142         FreeTestDictionary();
143         InitializeTestDictionary();
144     }
145 
InitializeTestDictionaryEnchantDictionaryTestFixture146     void InitializeTestDictionary()
147     {
148         _dict = enchant_broker_request_dict(_broker, languageTag.c_str());
149     }
150 
FreeTestDictionaryEnchantDictionaryTestFixture151     void FreeTestDictionary()
152     {
153         FreeDictionary(_dict);
154     }
155 
PersonalWordListFileHasContentsEnchantDictionaryTestFixture156     bool PersonalWordListFileHasContents()
157     {
158         return FileHasContents(GetPersonalDictFileName());
159     }
160 
ExcludeFileHasContentsEnchantDictionaryTestFixture161     bool ExcludeFileHasContents()
162     {
163         return FileHasContents(GetExcludeDictFileName());
164     }
165 
BrokerPWLFileHasContentsEnchantDictionaryTestFixture166 	bool BrokerPWLFileHasContents()
167     {
168         return FileHasContents(_pwlFileName);
169     }
170 
FileHasContentsEnchantDictionaryTestFixture171     bool FileHasContents(const std::string & filename)
172     {
173         bool hasContents = false;
174         int fd = g_open(filename.c_str(), O_RDONLY, S_IREAD );
175         if(fd == -1){
176             return false;
177         }
178 
179         char c;
180         while(read(fd, &c, 1) == 1 && !hasContents){
181             switch(c)
182             {
183             case '\n':
184             case '\r':
185             case ' ':
186                 break;
187             default:
188                 hasContents = true;
189             }
190         }
191         close(fd);
192 
193         return hasContents;
194     }
195 
GetPersonalDictFileNameEnchantDictionaryTestFixture196     std::string GetPersonalDictFileName(){
197         return AddToPath(GetTempUserEnchantDir(), "qaa.dic");
198     }
199 
GetExcludeDictFileNameEnchantDictionaryTestFixture200     std::string GetExcludeDictFileName(){
201         return AddToPath(GetTempUserEnchantDir(), "qaa.exc");
202     }
203 
SetErrorOnMockDictionaryEnchantDictionaryTestFixture204     void SetErrorOnMockDictionary(const std::string& error)
205     {
206         enchant_dict_set_error(_dict, error.c_str());
207     }
208 
FreeStringListEnchantDictionaryTestFixture209     void FreeStringList(char** list)
210     {
211         if(list)
212         {
213             enchant_dict_free_string_list(_dict, list);
214         }
215     }
216 
FreePwlStringListEnchantDictionaryTestFixture217     void FreePwlStringList(char** list)
218     {
219         if(list)
220         {
221             enchant_dict_free_string_list(_pwl, list);
222         }
223     }
224 
IsWordInSessionEnchantDictionaryTestFixture225     bool IsWordInSession(const std::string& word){
226         return enchant_dict_is_added(_dict, word.c_str(), word.size())!=0;
227     }
228 
IsWordInDictionaryEnchantDictionaryTestFixture229     bool IsWordInDictionary(const std::string& word){
230         return enchant_dict_check(_dict, word.c_str(), word.size())==0;
231     }
232 
RemoveWordFromDictionaryEnchantDictionaryTestFixture233     void RemoveWordFromDictionary(const std::string& word)
234     {
235         enchant_dict_remove(_dict, word.c_str(), word.size());
236     }
237 
AddWordToDictionaryEnchantDictionaryTestFixture238     void AddWordToDictionary(const std::string& word)
239     {
240 	enchant_dict_add(_dict, word.c_str(), word.size());
241     }
242 
AddWordsToDictionaryEnchantDictionaryTestFixture243     void AddWordsToDictionary(const std::vector<std::string>& sWords)
244     {
245         for(std::vector<std::string>::const_iterator itWord = sWords.begin();
246                                                               itWord != sWords.end();
247                                                               ++itWord){
248             AddWordToDictionary(*itWord);
249         }
250     }
251 
ExternalAddWordToDictionaryEnchantDictionaryTestFixture252     void ExternalAddWordToDictionary(const std::string& word)
253     {
254         ExternalAddWordToFile(word, GetPersonalDictFileName());
255     }
256 
ExternalAddWordToExcludeEnchantDictionaryTestFixture257     void ExternalAddWordToExclude(const std::string& word)
258     {
259         ExternalAddWordToFile(word, GetExcludeDictFileName());
260     }
261 
ExternalAddWordToFileEnchantDictionaryTestFixture262     static void ExternalAddWordToFile(const std::string& word, const std::string& filename)
263     {
264         sleep(1); // FAT systems have a 2 second resolution
265                      // NTFS is appreciably faster but no specs on what it is exactly
266                      // c runtime library's time_t has a 1 second resolution
267         FILE * f = g_fopen(filename.c_str(), "a");
268 	if(f)
269 	{
270             fputc('\n', f);
271             fputs(word.c_str(), f);
272             fclose(f);
273 	}
274     }
275 
ExternalAddNewLineToDictionaryEnchantDictionaryTestFixture276     void ExternalAddNewLineToDictionary()
277     {
278         sleep(1); // FAT systems have a 2 second resolution
279                      // NTFS is appreciably faster but no specs on what it is exactly
280                      // c runtime library's time_t has a 1 second resolution
281         FILE * f = g_fopen(GetPersonalDictFileName().c_str(), "a");
282         if(f)
283         {
284             fputc('\n', f);
285             fclose(f);
286         }
287     }
288 
ExternalAddWordsToDictionaryEnchantDictionaryTestFixture289     void ExternalAddWordsToDictionary(const std::vector<std::string>& sWords)
290     {
291         sleep(1); // FAT systems have a 2 second resolution
292                      // NTFS is appreciably faster but no specs on what it is exactly
293                      // c runtime library's time_t has a 1 second resolution
294         FILE * f = g_fopen(GetPersonalDictFileName().c_str(), "a");
295         if(f)
296         {
297             for (std::vector<std::string>::const_iterator itWord = sWords.begin();
298                 itWord != sWords.end(); ++itWord)
299             {
300                 if (itWord != sWords.begin()) {
301                     fputc('\n', f);
302                 }
303                 fputs(itWord->c_str(), f);
304             }
305             fclose(f);
306         }
307     }
308 
309     std::vector<std::string> GetExpectedSuggestions(const std::string& s, size_t begin = 0)
310     {
311         size_t cSuggestions;
312         char** expectedSuggestions = MockDictionarySuggest (_dict,
313                                                             s.c_str(),
314 		                                                    s.size(),
315                                                             &cSuggestions);
316 
317         std::vector<std::string> result;
318         if(expectedSuggestions != NULL && begin < cSuggestions){
319             result.insert(result.begin(), expectedSuggestions+begin, expectedSuggestions+cSuggestions);
320             g_strfreev(expectedSuggestions);
321         }
322 
323         return result;
324     }
325 
326 
GetSuggestionsFromWordEnchantDictionaryTestFixture327     std::vector<std::string> GetSuggestionsFromWord(const std::string& word)
328     {
329         std::vector<std::string> result;
330 
331         size_t cSuggestions;
332         char** suggestions = enchant_dict_suggest(_dict, word.c_str(), word.size(), &cSuggestions);
333 
334         if(suggestions != NULL){
335             result.insert(result.begin(), suggestions, suggestions+cSuggestions);
336         }
337 
338         FreeStringList(suggestions);
339 
340         return result;
341     }
342 
GetSuggestionsEnchantDictionaryTestFixture343     std::vector<std::string> GetSuggestions(const std::string& s)
344     {
345         return GetSuggestionsFromWord("helo");
346     }
347 };
348 
349 #endif
350