summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Albright <eric_albright@sil.org>2008-05-02 06:02:12 +0000
committerEric Albright <eric_albright@sil.org>2008-05-02 06:02:12 +0000
commit0ed48af1f728561b45969096c698e900a600028e (patch)
tree515de40a8deb904efb97a90330c5c77f4585bfb7
parentf04f81e52d73fce51d5f2451bd0a2825b8c15caa (diff)
downloadenchant-0ed48af1f728561b45969096c698e900a600028e.tar.gz
Fixes case where if a personal dictionary was edited such that it didn't end with a trailing new line, adding a word would not work correctly.
git-svn-id: svn+ssh://svn.abisource.com/svnroot/enchant/trunk@23735 bcba8976-2d24-0410-9c9c-aab3bd5fdfd6
-rw-r--r--src/pwl.c5
-rw-r--r--unittests/EnchantDictionaryTestFixture.h35
-rw-r--r--unittests/EnchantTestFixture.h8
-rw-r--r--unittests/pwl/enchant_pwl_tests.cpp102
4 files changed, 134 insertions, 16 deletions
diff --git a/src/pwl.c b/src/pwl.c
index a0e364e..7138710 100644
--- a/src/pwl.c
+++ b/src/pwl.c
@@ -388,8 +388,11 @@ void enchant_pwl_add(EnchantPWL *pwl,
if(g_stat(pwl->filename, &stats)==0)
pwl->file_changed = stats.st_mtime;
- fwrite (word, sizeof(char), len, f);
+ /* we write the new line first since we can't guarantee
+ that the file was terminated by a new line before
+ and we are just appending to the end of the file */
fwrite ("\n", sizeof(char), 1, f);
+ fwrite (word, sizeof(char), len, f);
enchant_unlock_file (f);
fclose (f);
}
diff --git a/unittests/EnchantDictionaryTestFixture.h b/unittests/EnchantDictionaryTestFixture.h
index 25d621a..a31d299 100644
--- a/unittests/EnchantDictionaryTestFixture.h
+++ b/unittests/EnchantDictionaryTestFixture.h
@@ -184,8 +184,16 @@ struct EnchantDictionaryTestFixture : EnchantBrokerTestFixture
}
char c;
- if(read(fd, &c, 1) == 1){
- hasContents = true;
+ while(read(fd, &c, 1) == 1 && !hasContents){
+ switch(c)
+ {
+ case '\n':
+ case '\r':
+ case ' ':
+ break;
+ default:
+ hasContents = true;
+ }
}
close(fd);
@@ -258,8 +266,21 @@ struct EnchantDictionaryTestFixture : EnchantBrokerTestFixture
FILE * f = g_fopen(filename.c_str(), "at");
if(f)
{
- fputs(word.c_str(), f);
fputc('\n', f);
+ fputs(word.c_str(), f);
+ fclose(f);
+ }
+ }
+
+ void ExternalAddNewLineToDictionary()
+ {
+ Sleep(1000); // FAT systems have a 2 second resolution
+ // NTFS is appreciably faster but no specs on what it is exactly
+ // c runtime library's time_t has a 1 second resolution
+ FILE * f = g_fopen(GetPersonalDictFileName().c_str(), "at");
+ if(f)
+ {
+ fputc('\n', f);
fclose(f);
}
}
@@ -273,9 +294,13 @@ struct EnchantDictionaryTestFixture : EnchantBrokerTestFixture
if(f)
{
for(std::vector<const std::string>::const_iterator
- itWord = sWords.begin(); itWord != sWords.end(); ++itWord) {
+ itWord = sWords.begin();
+ itWord != sWords.end(); ++itWord)
+ {
+ if(itWord != sWords.begin()){
+ fputc('\n', f);
+ }
fputs(itWord->c_str(), f);
- fputc('\n', f);
}
fclose(f);
}
diff --git a/unittests/EnchantTestFixture.h b/unittests/EnchantTestFixture.h
index 64daae4..e0d860d 100644
--- a/unittests/EnchantTestFixture.h
+++ b/unittests/EnchantTestFixture.h
@@ -32,7 +32,7 @@
#include <shlwapi.h>
#endif
#include <io.h>
-
+#include <assert.h>
#include <glib.h>
#include <string>
@@ -143,7 +143,7 @@ struct EnchantTestFixture
{
std::string toTheSideDir = dir + OUT_OF_THE_WAY;
- if(!DirExists(toTheSideDir))
+ if(DirExists(dir) && !DirExists(toTheSideDir))
{
MoveDir(dir, toTheSideDir);
}
@@ -156,6 +156,7 @@ struct EnchantTestFixture
std::string toTheSideDir = dir + OUT_OF_THE_WAY;
if(DirExists(toTheSideDir))
{
+ DeleteDirAndFiles(dir);
MoveDir(toTheSideDir, dir);
}
}
@@ -167,12 +168,13 @@ struct EnchantTestFixture
static bool DirExists(const std::string& dir)
{
- return g_file_test(dir.c_str(), G_FILE_TEST_IS_DIR);
+ return g_file_test(dir.c_str(), G_FILE_TEST_IS_DIR) != 0;
}
static void MoveDir(const std::string& from, const std::string& to)
{
int result = g_rename(from.c_str(), to.c_str());
+ assert(result);
if(result)
{
perror("failed");
diff --git a/unittests/pwl/enchant_pwl_tests.cpp b/unittests/pwl/enchant_pwl_tests.cpp
index 24fcc35..bf76103 100644
--- a/unittests/pwl/enchant_pwl_tests.cpp
+++ b/unittests/pwl/enchant_pwl_tests.cpp
@@ -152,6 +152,7 @@ TEST_FIXTURE(EnchantPwl_TestFixture,
sNewWords.push_back("grow");
sNewWords.push_back("another");
+ ExternalAddNewLineToDictionary();
ExternalAddWordsToDictionary(sNewWords);
for(std::vector<const std::string>::const_iterator itWord = sNewWords.begin(); itWord != sNewWords.end(); ++itWord){
@@ -190,10 +191,21 @@ TEST_FIXTURE(EnchantPwl_TestFixture,
TEST_FIXTURE(EnchantPwl_TestFixture,
IsWordInDictionary_DictionaryBeginsWithBOM_Successful)
{
- std::string Utf8Bom ("\xef\xbb\xbf");
- ExternalAddWordToDictionary(Utf8Bom + "cat");
+ char* Utf8Bom = "\xef\xbb\xbf";
+
+ Sleep(1000); // FAT systems have a 2 second resolution
+ // NTFS is appreciably faster but no specs on what it is exactly
+ // c runtime library's time_t has a 1 second resolution
+ FILE * f = g_fopen(GetPersonalDictFileName().c_str(), "at");
+ if(f)
+ {
+ fputs(Utf8Bom, f);
+ fputs("cat", f);
+ fclose(f);
+ }
+
- ReloadTestDictionary();
+ ReloadTestDictionary();
CHECK( IsWordInDictionary("cat") );
}
@@ -225,6 +237,41 @@ TEST_FIXTURE(EnchantPwl_TestFixture,
}
}
+/////////////////////////////////////////////////////////////////////////////////////////////////
+// Last word in Dictionary terminated By EOF instead of NL
+TEST_FIXTURE(EnchantPwl_TestFixture,
+ IsWordInDictionary_LastWordNotTerminatedByNL_WordsAppendedOkay)
+{
+ std::vector<const std::string> sWords;
+ sWords.push_back("cat");
+ sWords.push_back("hat");
+ sWords.push_back("that");
+ sWords.push_back("bat");
+ sWords.push_back("tot");
+
+ Sleep(1000); // FAT systems have a 2 second resolution
+ // NTFS is appreciably faster but no specs on what it is exactly
+ // c runtime library's time_t has a 1 second resolution
+ FILE * f = g_fopen(GetPersonalDictFileName().c_str(), "at");
+ if(f)
+ {
+ fputs(sWords[0].c_str(), f);
+ fclose(f);
+ }
+
+ for(std::vector<const std::string>::const_iterator itWord = sWords.begin() +1;
+ itWord != sWords.end();
+ ++itWord)
+ {
+ AddWordToDictionary(*itWord);
+ }
+
+ for(std::vector<const std::string>::const_iterator itWord = sWords.begin();
+ itWord != sWords.end();
+ ++itWord){
+ CHECK( IsWordInDictionary(*itWord) );
+ }
+}
////////////////////////////////////////////////////////////////////////////////////////////////
// Pwl Bugs
@@ -441,7 +488,7 @@ TEST_FIXTURE(EnchantPwl_TestFixture,
CHECK_ARRAY_EQUAL(expected, suggestions, expected.size());
}
}
-
+
/////////////////////////////////////////////////////////////////////////////////////////////////
// Capitalization
TEST_FIXTURE(EnchantPwl_TestFixture,
@@ -1088,14 +1135,32 @@ TEST_FIXTURE(EnchantPwl_TestFixture,
TEST_FIXTURE(EnchantPwl_TestFixture,
PwlRemove_ItemRemovedFromBeginningOfFileWithBOM)
{
- std::string Utf8Bom ("\xef\xbb\xbf");
+ char* Utf8Bom = "\xef\xbb\xbf";
std::vector<const std::string> sWords;
- sWords.push_back(Utf8Bom + "hello");
+ sWords.push_back("hello");
sWords.push_back("cat");
sWords.push_back("hat");
- ExternalAddWordsToDictionary(sWords);
+ Sleep(1000); // FAT systems have a 2 second resolution
+ // NTFS is appreciably faster but no specs on what it is exactly
+ // c runtime library's time_t has a 1 second resolution
+ FILE * f = g_fopen(GetPersonalDictFileName().c_str(), "at");
+ if(f)
+ {
+ fputs(Utf8Bom, f);
+ for(std::vector<const std::string>::const_iterator
+ itWord = sWords.begin();
+ itWord != sWords.end();
+ ++itWord)
+ {
+ if(itWord != sWords.begin()){
+ fputc('\n', f);
+ }
+ fputs(itWord->c_str(), f);
+ }
+ fclose(f);
+ }
RemoveWordFromDictionary("hello");
@@ -1132,6 +1197,29 @@ TEST_FIXTURE(EnchantPwl_TestFixture,
}
TEST_FIXTURE(EnchantPwl_TestFixture,
+ PwlRemove_ItemRemovedFromEndOfFile_ExternalSetup)
+{
+ std::vector<const std::string> sWords;
+ sWords.push_back("cat");
+ sWords.push_back("hat");
+ sWords.push_back("that");
+ sWords.push_back("bat");
+ sWords.push_back("tot");
+
+ std::vector<const std::string>::const_iterator removed = sWords.insert(sWords.end(), "hello");
+ ExternalAddWordsToDictionary(sWords);
+
+ RemoveWordFromDictionary("hello");
+
+ ReloadTestDictionary(); // to see what actually persisted
+
+ for(std::vector<const std::string>::const_iterator itWord = sWords.begin(); itWord != removed; ++itWord){
+ CHECK( IsWordInDictionary(*itWord) );
+ }
+ CHECK(!IsWordInDictionary(*removed) );
+}
+
+TEST_FIXTURE(EnchantPwl_TestFixture,
PwlRemove_FileHasProperSubset_ItemRemovedFromFile)
{
std::vector<const std::string> sWords;