diff options
-rw-r--r-- | indra/llvfs/lldir.h | 18 | ||||
-rw-r--r-- | indra/llvfs/tests/lldir_test.cpp | 171 |
2 files changed, 188 insertions, 1 deletions
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 4f63c04aab..0730b0fa79 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -74,7 +74,23 @@ class LLDir // pure virtual functions virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0; - virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) = 0; + + /// Walk the files in a directory, with file pattern matching + virtual BOOL getNextFileInDir(const std::string &dirname, ///< directory path - must end in trailing slash! + const std::string &mask, ///< file pattern string (use "*" for all) + std::string &fname, ///< found file name + BOOL wrap ///< DEPRECATED - set to FALSE + ) = 0; + /**< + * @returns true if a file was found, false if the entire directory has been scanned. + * + * @note that this function is NOT thread safe + * + * This function may not be used to scan part of a directory, then start a new search of a different + * directory, and then restart the first search where it left off. + * + * @todo this really should be rewritten as an iterator object. + */ virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) = 0; virtual std::string getCurPath() = 0; virtual BOOL fileExists(const std::string &filename) const = 0; diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp index bcffa449c8..3247e0ab83 100644 --- a/indra/llvfs/tests/lldir_test.cpp +++ b/indra/llvfs/tests/lldir_test.cpp @@ -256,5 +256,176 @@ namespace tut gDirUtilp->getExtension(dottedPathExt), "ext"); } + + std::string makeTestFile( const std::string& dir, const std::string& file ) + { + std::string delim = gDirUtilp->getDirDelimiter(); + std::string path = dir + delim + file; + LLFILE* handle = LLFile::fopen( path, "w" ); + ensure("failed to open test file '"+path+"'", handle != NULL ); + ensure("failed to write to test file '"+path+"'", !fputs("test file", handle) ); + fclose(handle); + return path; + } + + std::string makeTestDir( const std::string& dirbase ) + { + int counter; + std::string uniqueDir; + bool foundUnused; + std::string delim = gDirUtilp->getDirDelimiter(); + + for (counter=0, foundUnused=false; !foundUnused; counter++ ) + { + char counterStr[3]; + sprintf(counterStr, "%02d", counter); + uniqueDir = dirbase + counterStr; + foundUnused = ! ( LLFile::isdir(uniqueDir) || LLFile::isfile(uniqueDir) ); + } + ensure("test directory '" + uniqueDir + "' creation failed", !LLFile::mkdir(uniqueDir)); + + return uniqueDir + delim; // HACK - apparently, the trailing delimiter is needed... + } + + template<> template<> + void LLDirTest_object_t::test<5>() + // getNextFileInDir + { + std::string delim = gDirUtilp->getDirDelimiter(); + std::string dirTemp = LLFile::tmpdir(); + + // Create the same 5 file names of the two directories + const char* filenames[5] = { "file1.abc", "file2.abc", "file1.xyz", "file2.xyz", "file1.mno" }; + std::string dir1 = makeTestDir(dirTemp + "getNextFileInDir"); + std::string dir2 = makeTestDir(dirTemp + "getNextFileInDir"); + std::string dir1files[5]; + std::string dir2files[5]; + for (int i=0; i<5; i++) + { + dir1files[i] = makeTestFile(dir1, filenames[i]); + dir2files[i] = makeTestFile(dir2, filenames[i]); + } + + // Scan dir1 and see if each of the 5 files is found exactly once + std::string scan1result; + int found1 = 0; + bool filesFound1[5] = { false, false, false, false, false }; + // std::cerr << "searching '"+dir1+"' for *\n"; + while ( found1 <= 5 && gDirUtilp->getNextFileInDir(dir1, "*", scan1result, false) ) + { + found1++; + // std::cerr << " found '"+scan1result+"'\n"; + int check; + for (check=0; check < 5 && ! ( scan1result == filenames[check] ); check++) + { + } + // check is now either 5 (not found) or the index of the matching name + if (check < 5) + { + ensure( "found file '"+(std::string)filenames[check]+"' twice", ! filesFound1[check] ); + filesFound1[check] = true; + } + else + { + ensure( "found unknown file '"+(std::string)filenames[check]+"'", false); + } + } + ensure("wrong number of files found in '"+dir1+"'", found1 == 5); + + // Scan dir2 and see if only the 2 *.xyz files are found + std::string scan2result; + int found2 = 0; + bool filesFound2[5] = { false, false, false, false, false }; + // std::cerr << "searching '"+dir2+"' for *.xyz\n"; + + while ( found2 <= 5 && gDirUtilp->getNextFileInDir(dir2, "*.xyz", scan2result, false) ) + { + found2++; + // std::cerr << " found '"+scan2result+"'\n"; + int check; + for (check=0; check < 5 && ! ( scan2result == filenames[check] ); check++) + { + } + // check is now either 5 (not found) or the index of the matching name + if (check < 5) + { + ensure( "found file '"+(std::string)filenames[check]+"' twice", ! filesFound2[check] ); + filesFound2[check] = true; + } + else // check is 5 - should not happen + { + ensure( "found unknown file '"+(std::string)filenames[check]+"'", false); + } + } + ensure("wrong files found in '"+dir2+"'", + !filesFound2[0] && !filesFound2[1] && filesFound2[2] && filesFound2[3] && !filesFound2[4] ); + + + // Scan dir2 and see if only the 1 *.mno file is found + std::string scan3result; + int found3 = 0; + bool filesFound3[5] = { false, false, false, false, false }; + // std::cerr << "searching '"+dir2+"' for *.mno\n"; + + while ( found3 <= 5 && gDirUtilp->getNextFileInDir(dir2, "*.mno", scan3result, false) ) + { + found3++; + // std::cerr << " found '"+scan3result+"'\n"; + int check; + for (check=0; check < 5 && ! ( scan3result == filenames[check] ); check++) + { + } + // check is now either 5 (not found) or the index of the matching name + if (check < 5) + { + ensure( "found file '"+(std::string)filenames[check]+"' twice", ! filesFound3[check] ); + filesFound3[check] = true; + } + else // check is 5 - should not happen + { + ensure( "found unknown file '"+(std::string)filenames[check]+"'", false); + } + } + ensure("wrong files found in '"+dir2+"'", + !filesFound3[0] && !filesFound3[1] && !filesFound3[2] && !filesFound3[3] && filesFound3[4] ); + + + // Scan dir1 and see if any *.foo files are found + std::string scan4result; + int found4 = 0; + bool filesFound4[5] = { false, false, false, false, false }; + // std::cerr << "searching '"+dir1+"' for *.foo\n"; + + while ( found4 <= 5 && gDirUtilp->getNextFileInDir(dir1, "*.foo", scan4result, false) ) + { + found4++; + // std::cerr << " found '"+scan4result+"'\n"; + int check; + for (check=0; check < 5 && ! ( scan4result == filenames[check] ); check++) + { + } + // check is now either 5 (not found) or the index of the matching name + if (check < 5) + { + ensure( "found file '"+(std::string)filenames[check]+"' twice", ! filesFound4[check] ); + filesFound4[check] = true; + } + else // check is 5 - should not happen + { + ensure( "found unknown file '"+(std::string)filenames[check]+"'", false); + } + } + ensure("wrong files found in '"+dir1+"'", + !filesFound4[0] && !filesFound4[1] && !filesFound4[2] && !filesFound4[3] && !filesFound4[4] ); + + // clean up all test files and directories + for (int i=0; i<5; i++) + { + LLFile::remove(dir1files[i]); + LLFile::remove(dir2files[i]); + } + LLFile::rmdir(dir1); + LLFile::rmdir(dir2); + } } |