summaryrefslogtreecommitdiffstats
path: root/fastos/src/tests/filetest.cpp
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /fastos/src/tests/filetest.cpp
Publish
Diffstat (limited to 'fastos/src/tests/filetest.cpp')
-rw-r--r--fastos/src/tests/filetest.cpp907
1 files changed, 907 insertions, 0 deletions
diff --git a/fastos/src/tests/filetest.cpp b/fastos/src/tests/filetest.cpp
new file mode 100644
index 00000000000..24483076ed0
--- /dev/null
+++ b/fastos/src/tests/filetest.cpp
@@ -0,0 +1,907 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <memory>
+#include <vespa/fastos/fastos.h>
+#include "tests.h"
+
+namespace {
+
+ // Create the named file, and write it's filename into it.
+ // Return true on success
+ bool createFile(const char* fileName) {
+ FastOS_StatInfo statInfo;
+ FastOS_File cf(fileName);
+ return ( cf.OpenWriteOnly() &&
+ cf.CheckedWrite(fileName, strlen(fileName)) &&
+ cf.Close() &&
+ FastOS_File::Stat(fileName, &statInfo) &&
+ statInfo._isRegular );
+ }
+
+ bool createFile(const char* fileName,
+ const unsigned int size) {
+ FastOS_File cf(fileName);
+ bool success = false;
+ if (cf.OpenWriteOnlyTruncate()) {
+ auto buf = std::make_unique<char[]>(size); // Could be dangerous..
+ if (buf) {
+ memset(buf.get(), 0, size); // dont write uninitialized bytes since valgrind will complain
+ if (cf.CheckedWrite(buf.get(), size)) {
+ success = true;
+ }
+ }
+ cf.Close();
+ }
+ return success;
+ }
+}
+
+
+class FileTest : public BaseTest
+{
+private:
+ virtual bool useProcessStarter() const { return true; }
+public:
+ static const char * roFilename;
+ static const char * woFilename;
+ static const char * rwFilename;
+
+ void DirectoryTest()
+ {
+ TestHeader ("Directory management (remove & empty) test");
+
+ const char *dirName = "tmpTestDir";
+ char file1[1024];
+ char file2[1024];
+ char file3[1024];
+ char file4[1024];
+ char file5[1024];
+ char subdir1[1024];
+ char subdir2[1024];
+ sprintf(file1, "%s%sfile1", dirName, FastOS_File::GetPathSeparator());
+ sprintf(file2, "%s%sfile2", dirName, FastOS_File::GetPathSeparator());
+ sprintf(file3, "%s%sfile2", dirName, FastOS_File::GetPathSeparator());
+ sprintf(subdir1, "%s%sdir1", dirName, FastOS_File::GetPathSeparator());
+ sprintf(subdir2, "%s%sdir2", dirName, FastOS_File::GetPathSeparator());
+ sprintf(file4, "%s%sfile4", subdir2, FastOS_File::GetPathSeparator());
+ sprintf(file5, "%s%sfile5", subdir2, FastOS_File::GetPathSeparator());
+
+ FastOS_StatInfo statInfo;
+
+ bool success = false;
+
+ // Don't run at all if the directory already exists
+ assert(!FastOS_File::Stat(dirName, &statInfo));
+
+ FastOS_File::MakeDirectory(dirName);
+
+ // Verify that we succeed with an empty directory
+ FastOS_File::EmptyDirectory(dirName);
+ success = FastOS_File::Stat(dirName, &statInfo);
+ Progress(success, "Removing empty directory.");
+
+ // Verify that we can empty a directory with files in it
+ createFile(file1);
+ createFile(file2);
+ createFile(file3);
+ FastOS_File::EmptyDirectory(dirName);
+ success =
+ !FastOS_File::Stat(file1, &statInfo) &&
+ !FastOS_File::Stat(file2, &statInfo) &&
+ !FastOS_File::Stat(file3, &statInfo) &&
+ FastOS_File::Stat(dirName, &statInfo);
+ Progress(success, "Deleting dir with files in it.");
+
+ // Verify that we can empty a directory with files and directories in it
+ createFile(file1);
+ createFile(file2);
+ createFile(file3);
+ FastOS_File::MakeDirectory(subdir1);
+ FastOS_File::MakeDirectory(subdir2);
+ createFile(file4);
+ createFile(file5);
+ FastOS_File::EmptyDirectory(dirName);
+ success = FastOS_File::Stat(dirName, &statInfo) &&
+ !FastOS_File::Stat(file1, &statInfo) &&
+ !FastOS_File::Stat(file2, &statInfo) &&
+ !FastOS_File::Stat(file3, &statInfo) &&
+ !FastOS_File::Stat(file4, &statInfo) &&
+ !FastOS_File::Stat(file5, &statInfo) &&
+ !FastOS_File::Stat(subdir1, &statInfo) &&
+ !FastOS_File::Stat(subdir2, &statInfo);
+ Progress(success, "Emptying directory with files and folders in it.");
+
+ // Verify that we don't empty the directory if we find a file to keep
+ createFile(file1);
+ createFile(file2);
+ createFile(file3);
+ FastOS_File::MakeDirectory(subdir1);
+ FastOS_File::MakeDirectory(subdir2);
+ createFile(file4);
+ createFile(file5);
+ FastOS_File::EmptyDirectory(dirName, "file1");
+ success = FastOS_File::Stat(dirName, &statInfo);
+ Progress(success, "Emptying dir with keepfile in it.");
+ // Verify that all but the file to keep are removed
+ success = FastOS_File::Stat(file1, &statInfo) &&
+ !FastOS_File::Stat(file2, &statInfo) &&
+ !FastOS_File::Stat(file3, &statInfo) &&
+ !FastOS_File::Stat(file4, &statInfo) &&
+ !FastOS_File::Stat(file5, &statInfo) &&
+ !FastOS_File::Stat(subdir1, &statInfo) &&
+ !FastOS_File::Stat(subdir2, &statInfo);
+ Progress(success, "Looking for keepfile.");
+
+ // Verify that we don't empty the sub-directory if we find a file to keep
+ createFile(file1);
+ createFile(file2);
+ createFile(file3);
+ FastOS_File::MakeDirectory(subdir1);
+ FastOS_File::MakeDirectory(subdir2);
+ createFile(file4);
+ createFile(file5);
+ FastOS_File::EmptyDirectory(dirName, "file4");
+ success = FastOS_File::Stat(dirName, &statInfo);
+ Progress(success, "Emptying file with nested keepfile.");
+ // Verify that all but the file to keep are removed
+ success = !FastOS_File::Stat(file1, &statInfo) &&
+ !FastOS_File::Stat(file2, &statInfo) &&
+ !FastOS_File::Stat(file3, &statInfo) &&
+ FastOS_File::Stat(file4, &statInfo) &&
+ !FastOS_File::Stat(file5, &statInfo) &&
+ !FastOS_File::Stat(subdir1, &statInfo) &&
+ FastOS_File::Stat(subdir2, &statInfo);
+ // Progress(success, "Looking for nested keepfile."); // Unsupported for now.
+
+
+ FastOS_File::EmptyAndRemoveDirectory(dirName);
+
+ FastOS_File::MakeDirectory(dirName);
+
+ // Verify that we can remove an empty directory
+ FastOS_File::EmptyAndRemoveDirectory(dirName);
+ success = !FastOS_File::Stat(dirName, &statInfo);
+ Progress(success, "Deleting empty directory.");
+
+ // Verify that we can remove a directory with files in it
+ FastOS_File::MakeDirectory(dirName);
+ createFile(file1);
+ createFile(file2);
+ createFile(file3);
+ FastOS_File::EmptyAndRemoveDirectory(dirName);
+ success = !FastOS_File::Stat(dirName, &statInfo);
+ Progress(success, "Deleting a directory with files in it.");
+
+ // Verify that we can remove a directory with files and directories in it
+ FastOS_File::MakeDirectory(dirName);
+ createFile(file1);
+ createFile(file2);
+ createFile(file3);
+ FastOS_File::MakeDirectory(subdir1);
+ FastOS_File::MakeDirectory(subdir2);
+ createFile(file4);
+ createFile(file5);
+ FastOS_File::EmptyAndRemoveDirectory(dirName);
+ success = !FastOS_File::Stat(dirName, &statInfo);
+ Progress(success, "Deleting directory with files and directories in it.");
+
+ }
+
+ void MoveFileTest() {
+ TestHeader ("Moving files (across volumes too) test");
+
+ const char *dirName = "tmpTestDir";
+ char file1[1024];
+ char file2[1024];
+ char file3[1024];
+ sprintf(file1, "%s%sfile1", dirName, FastOS_File::GetPathSeparator());
+ sprintf(file2, "%s%sfile2", dirName, FastOS_File::GetPathSeparator());
+ sprintf(file3, "%stmp%sfile3", FastOS_File::GetPathSeparator(),
+ FastOS_File::GetPathSeparator());
+
+ FastOS_File::MakeDirectory(dirName);
+ createFile(file1);
+
+ FastOS_StatInfo statInfo;
+ // Move file to new name in same dir.
+ FastOS_File::MoveFile(file1, file2);
+ Progress(FastOS_File::Stat(file2, &statInfo), "Moving one within a directory.");
+
+ // Move file to /tmp.
+ FastOS_File::MoveFile(file2, file3);
+ Progress(FastOS_File::Stat(file3, &statInfo), "Moving to /tmp/");
+
+ // Clean up
+ FastOS_File::Delete(file3);
+ FastOS_File::EmptyAndRemoveDirectory(dirName);
+ }
+
+ void GetCurrentDirTest ()
+ {
+ TestHeader ("Get Current Directory Test");
+
+ std::string currentDir = FastOS_File::getCurrentDirectory();
+
+ Progress(!currentDir.empty(),
+ "Current dir: %s", !currentDir.empty() ?
+ currentDir.c_str() : "<failed>");
+
+ bool dirrc = FastOS_File::SetCurrentDirectory("..");
+
+ std::string parentDir;
+
+ if (dirrc) {
+ parentDir = FastOS_File::getCurrentDirectory();
+ }
+
+ Progress(dirrc && strcmp(currentDir.c_str(), parentDir.c_str()) != 0,
+ "Parent dir: %s", !parentDir.empty() ?
+ parentDir.c_str() : "<failed>");
+
+ dirrc = FastOS_File::SetCurrentDirectory(currentDir.c_str());
+
+ Progress(dirrc, "Changed back to working directory.");
+
+ PrintSeparator();
+ }
+
+ void MemoryMapTest ()
+ {
+ TestHeader ("Memory Map Test");
+
+ int i;
+ const int bufSize = 1000;
+
+ FastOS_File file("generated/memorymaptest");
+
+ bool rc = file.OpenReadWrite();
+ Progress(rc, "Opening file 'generated/memorymaptest'");
+
+ if(rc)
+ {
+ char *buffer = new char [bufSize];
+ for (i = 0; i < bufSize; i++)
+ buffer[i] = i % 256;
+
+ ssize_t wroteB = file.Write2(buffer, bufSize);
+ Progress(wroteB == bufSize, "Writing %d bytes to file", bufSize);
+
+ file.Close();
+
+ file.enableMemoryMap(0);
+
+ rc = file.OpenReadOnly();
+
+ Progress(rc, "Opening file 'generated/memorymaptest' read-only");
+ if(rc)
+ {
+ bool mmapEnabled;
+ char *mmapBuffer = NULL;
+
+ mmapEnabled = file.IsMemoryMapped();
+ mmapBuffer = static_cast<char *>(file.MemoryMapPtr(0));
+
+ Progress(rc, "Memory mapping %s",
+ mmapEnabled ? "enabled" : "disabled");
+ Progress(rc, "Map address: 0x%p", mmapBuffer);
+
+ if (mmapEnabled)
+ {
+ rc = 0;
+ for (i = 0; i < bufSize; i++)
+ rc |= (mmapBuffer[i] == i % 256);
+
+ Progress(rc, "Reading %d bytes from memory map", bufSize);
+ }
+ }
+ delete [] buffer;
+ }
+ PrintSeparator();
+ }
+
+ void DirectIOTest ()
+ {
+ TestHeader ("Direct Disk IO Test");
+
+ int i;
+ const int bufSize = 40000;
+
+ FastOS_File file("generated/diotest");
+
+ bool rc = file.OpenWriteOnly();
+ Progress(rc, "Opening file 'generated/diotest' write-only");
+
+ if(rc)
+ {
+ char *buffer = new char [bufSize];
+
+ for(i=0; i<bufSize; i++)
+ buffer[i] = 'A' + (i % 17);
+
+ ssize_t wroteB = file.Write2(buffer, bufSize);
+ Progress(wroteB == bufSize, "Writing %d bytes to file", bufSize);
+
+ file.Close();
+
+ if(rc)
+ {
+ file.EnableDirectIO();
+
+ rc = file.OpenReadOnly();
+ Progress(rc, "Opening file 'generated/diotest' read-only");
+ if(rc)
+ {
+ bool dioEnabled;
+ size_t memoryAlignment=0;
+ size_t transferGranularity=0;
+ size_t transferMaximum=0;
+
+ dioEnabled = file.GetDirectIORestrictions(memoryAlignment,
+ transferGranularity,
+ transferMaximum);
+
+ Progress(rc, "DirectIO %s", dioEnabled ? "enabled" : "disabled");
+ Progress(rc, "Memory alignment: %u bytes", memoryAlignment);
+ Progress(rc, "Transfer granularity: %u bytes", transferGranularity);
+ Progress(rc, "Transfer maximum: %u bytes", transferMaximum);
+
+ if(dioEnabled)
+ {
+ int eachRead = (8192 + transferGranularity - 1) / transferGranularity;
+
+ char *buffer2 = new char [(eachRead * transferGranularity +
+ memoryAlignment - 1)];
+ char *alignPtr = buffer2;
+ unsigned int align =
+ static_cast<unsigned int>
+ (reinterpret_cast<unsigned long>(alignPtr) &
+ (memoryAlignment - 1));
+ if(align != 0)
+ alignPtr = &alignPtr[memoryAlignment - align];
+
+ int residue = bufSize;
+ int pos=0;
+ while(residue > 0)
+ {
+ int readThisTime = eachRead * transferGranularity;
+ if(readThisTime > residue)
+ readThisTime = residue;
+
+ file.ReadBuf(alignPtr, readThisTime, pos);
+
+ for(i=0; i<readThisTime; i++)
+ {
+ rc = (alignPtr[i] == 'A' + ((i+pos) % 17));
+ if(!rc)
+ {
+ Progress(false, "Read error at offset %d", i);
+ break;
+ }
+ }
+ residue -= readThisTime;
+ pos += readThisTime;
+
+ if(!rc)
+ break;
+ }
+ if(rc)
+ {
+ Progress(true, "Read success");
+
+ rc = file.SetPosition(1);
+ Progress(rc, "SetPosition(1)");
+ if(rc)
+ {
+ const int attemptReadBytes = 173;
+ ssize_t readB = file.Read(buffer, attemptReadBytes);
+ Progress(readB == attemptReadBytes,
+ "Read %d bytes successfully",
+ readB);
+ for(i = 0; i < attemptReadBytes; i++)
+ {
+ rc = (buffer[i] == 'A' + ((i+ 1) % 17));
+ if(!rc)
+ {
+ Progress(false, "Read error at offset %d", i);
+ break;
+ }
+ }
+ }
+ if (rc) {
+ rc = file.SetPosition(1);
+ Progress(rc, "SetPosition(1)");
+ if(rc)
+ {
+ const int attemptReadBytes = 4096;
+ ssize_t readB = file.Read(buffer,
+ attemptReadBytes);
+ Progress(readB == attemptReadBytes,
+ "Read %d bytes successfully",
+ readB);
+ for(i = 0; i < attemptReadBytes; i++)
+ {
+ rc = (buffer[i] == 'A' + ((i+ 1) % 17));
+ if(!rc)
+ {
+ Progress(false,
+ "Read error at offset %d", i);
+ break;
+ }
+ }
+ }
+ }
+ }
+ delete [] buffer2;
+ }
+ else
+ {
+ memset(buffer, 0, bufSize);
+
+ ssize_t readBytes = file.Read(buffer, bufSize);
+ Progress(readBytes == bufSize,
+ "Reading %d bytes from file", bufSize);
+
+ for(i=0; i<bufSize; i++)
+ {
+ rc = (buffer[i] == 'A' + (i % 17));
+ if(!rc)
+ {
+ Progress(false, "Read error at offset %d", i);
+ break;
+ }
+ }
+ if(rc)
+ Progress(true, "Read success");
+ }
+ }
+ }
+ delete [] buffer;
+ }
+
+ PrintSeparator();
+ }
+
+ void ReadOnlyTest ()
+ {
+ TestHeader("Read-Only Test");
+
+ FastOS_File *myFile = new FastOS_File(roFilename);
+
+ if(myFile->OpenReadOnly())
+ {
+ int64_t filesize;
+ filesize = myFile->GetSize();
+
+ printf("%s: File size: %ld\n",
+ (filesize == 27) ? okString : failString,
+ static_cast<long>(filesize));
+
+ char dummyData[6] = "Dummy";
+ bool writeResult = myFile->CheckedWrite(dummyData, 6);
+
+ if(writeResult)
+ printf("FAILED: Should not be able to write a file opened for read-only access.\n");
+ else
+ {
+ char dummyData2[28];
+ printf("%s: Write failed with read-only access.\n", okString);
+
+ bool rc = myFile->SetPosition(1);
+ Progress(rc, "Setting position to 1");
+
+ if(rc)
+ {
+ ssize_t readBytes;
+ int64_t filePosition;
+ readBytes = myFile->Read(dummyData2, 28);
+
+ Progress(readBytes == 26, "Attempting to read 28 bytes, should get 26. Got: %d", readBytes);
+
+ filePosition = myFile->GetPosition();
+ Progress(filePosition == 27, "File position should now be 27. Was: %d", int(filePosition));
+
+ readBytes = myFile->Read(dummyData2, 6);
+ Progress(readBytes == 0, "We should now get 0 bytes. Read: %d bytes", readBytes);
+
+ filePosition = myFile->GetPosition();
+ Progress(filePosition == 27, "File position should now be 27. Was: %d", int(filePosition));
+ }
+ }
+ }
+ else
+ printf("%s: Unable to open file 'hello.txt'.\n", failString);
+
+ delete(myFile);
+ PrintSeparator();
+ }
+
+ void WriteOnlyTest ()
+ {
+ TestHeader("Write-Only Test");
+
+ FastOS_File *myFile = new FastOS_File(woFilename);
+
+ if(myFile->OpenWriteOnly())
+ {
+
+ int64_t filesize;
+ filesize = myFile->GetSize();
+
+ printf("%s: File size: %ld\n",
+ (filesize == 0) ? okString : failString,
+ static_cast<long>(filesize));
+
+ char dummyData[6] = "Dummy";
+ bool writeResult = myFile->CheckedWrite(dummyData, 6);
+
+ if(!writeResult)
+ {
+ printf("%s: Should be able to write to file opened for write-only access.\n", failString);
+ }
+ else
+ {
+ printf("%s: Write 6 bytes ok.\n", okString);
+
+ int64_t filePosition = myFile->GetPosition();
+ if(filePosition == 6)
+ {
+ printf("%s: Fileposition is now 6.\n", okString);
+
+ if(myFile->SetPosition(0))
+ {
+ printf("%s: SetPosition(0) success.\n", okString);
+ filePosition = myFile->GetPosition();
+
+ if(filePosition == 0)
+ {
+ printf("%s: Fileposition is now 0.\n", okString);
+
+ int readBytes = myFile->Read(dummyData, 6);
+
+ if(readBytes != 6)
+ {
+ printf("%s: Trying to read a write-only file should fail and it did.\n", okString);
+ printf("%s: Return code was: %d.\n", okString, readBytes);
+ }
+ else
+ printf("%s: Read on a file with write-only access should fail, but it didn't.\n", failString);
+ }
+ else
+ printf("%s: Fileposition should be 6, but was %ld.\n",
+ failString,
+ static_cast<long>(filePosition));
+ }
+ else
+ printf("%s: SetPosition(0) failed\n", failString);
+ }
+ else
+ printf("%s: Fileposition should be 6, but was %ld.\n",
+ failString,
+ static_cast<long>(filePosition));
+ }
+
+ bool closeResult = myFile->Close();
+ printf("%s: Close file.\n", closeResult ? okString : failString);
+ }
+ else
+ {
+ printf("%s: Unable to open file 'hello.txt'.\n", failString);
+ }
+
+
+ bool deleteResult = myFile->Delete();
+
+ printf("%s: Delete file '%s'.\n", deleteResult ? okString : failString, woFilename);
+
+
+ delete(myFile);
+ PrintSeparator();
+ }
+
+ void ReadWriteTest ()
+ {
+ TestHeader("Read/Write Test");
+
+ FastOS_File *myFile = new FastOS_File(rwFilename);
+
+ if(myFile->OpenExisting())
+ {
+ printf("%s: OpenExisting() should not work when '%s' does not exist.\n", failString, rwFilename);
+
+ myFile->Close();
+ }
+ else
+ printf("%s: OpenExisting() should fail when '%s' does not exist, and it did.\n", okString, rwFilename);
+
+
+ if(myFile->OpenReadWrite())
+ {
+ int64_t filesize;
+
+ filesize = myFile->GetSize();
+
+ printf("%s: File size: %ld\n",
+ (filesize == 0) ? okString : failString,
+ static_cast<long>(filesize));
+
+ char dummyData[6] = "Dummy";
+
+ bool writeResult = myFile->CheckedWrite(dummyData, 6);
+
+ if(!writeResult)
+ printf("%s: Should be able to write to file opened for read/write access.\n", failString);
+ else
+ {
+ printf("%s: Write 6 bytes ok.\n", okString);
+
+ int64_t filePosition = myFile->GetPosition();
+
+ if(filePosition == 6)
+ {
+ printf("%s: Fileposition is now 6.\n", okString);
+
+ if(myFile->SetPosition(0))
+ {
+ printf("%s: SetPosition(0) success.\n", okString);
+ filePosition = myFile->GetPosition();
+
+ if(filePosition == 0)
+ {
+ printf("%s: Fileposition is now 0.\n", okString);
+
+ char dummyData2[7];
+ int readBytes = myFile->Read(dummyData2, 6);
+
+ if(readBytes == 6)
+ {
+ printf("%s: Reading 6 bytes worked.\n", okString);
+
+ int cmpResult = memcmp(dummyData, dummyData2, 6);
+
+ printf("%s: Comparing the written and read result.\n",
+ (cmpResult == 0) ? okString : failString);
+
+ bool rc = myFile->SetPosition(1);
+ Progress(rc, "Setting position to 1");
+
+ if(rc)
+ {
+ readBytes = myFile->Read(dummyData2, 7);
+
+ Progress(readBytes == 5, "Attempting to read 7 bytes, should get 5. Got: %d", readBytes);
+
+ filePosition = myFile->GetPosition();
+ Progress(filePosition == 6, "File position should now be 6. Was: %d", int(filePosition));
+
+ readBytes = myFile->Read(dummyData2, 6);
+ Progress(readBytes == 0, "We should not be able to read any more. Read: %d bytes", readBytes);
+
+ filePosition = myFile->GetPosition();
+ Progress(filePosition == 6, "File position should now be 6. Was: %d", int(filePosition));
+ }
+ }
+ else
+ printf("%s: Reading 6 bytes failed.\n", failString);
+ }
+ else
+ printf("%s: Fileposition should be 6, but was %ld.\n",
+ failString,
+ static_cast<long>(filePosition));
+ }
+ else
+ printf("%s: SetPosition(0) failed\n", failString);
+ }
+ else
+ printf("%s: Fileposition should be 6, but was %ld.\n",
+ failString,
+ static_cast<long>(filePosition));
+ }
+
+ bool closeResult = myFile->Close();
+
+ printf("%s: Close file.\n", closeResult ? okString : failString);
+ }
+ else
+ printf("%s: Unable to open file 'hello.txt'.\n", failString);
+
+ bool deleteResult = myFile->Delete();
+ printf("%s: Delete file '%s'.\n", deleteResult ? okString : failString, rwFilename);
+
+ delete(myFile);
+ PrintSeparator();
+ }
+
+ void ScanDirectoryTest()
+ {
+ TestHeader("DirectoryScan Test");
+
+ FastOS_DirectoryScan *scanDir = new FastOS_DirectoryScan(".");
+
+ while(scanDir->ReadNext())
+ {
+ const char *name = scanDir->GetName();
+ bool isDirectory = scanDir->IsDirectory();
+ bool isRegular = scanDir->IsRegular();
+
+ printf("%-30s %s\n", name,
+ isDirectory ? "DIR" : (isRegular ? "FILE" : "UNKN"));
+ }
+
+ delete(scanDir);
+ PrintSeparator();
+ }
+
+ void ReadBufTest ()
+ {
+ TestHeader("ReadBuf Test");
+
+ FastOS_File file("hello.txt");
+
+ char buffer[20];
+
+ if(file.OpenReadOnly())
+ {
+ int64_t position = file.GetPosition();
+ Progress(position == 0, "File pointer should be 0 after opening file");
+
+ file.Read(buffer, 4);
+ buffer[4] = '\0';
+ position = file.GetPosition();
+ Progress(position == 4, "File pointer should be 4 after reading 4 bytes");
+ Progress(strcmp(buffer, "This") == 0, "[This]=[%s]", buffer);
+
+ file.ReadBuf(buffer, 6, 8);
+ buffer[6] = '\0';
+ position = file.GetPosition();
+ Progress(position == 4, "File pointer should still be 4 after ReadBuf");
+ Progress(strcmp(buffer, "a test") == 0, "[a test]=[%s]", buffer);
+
+ file.Close();
+ }
+
+ PrintSeparator();
+ }
+
+ void DiskFreeSpaceTest ()
+ {
+ TestHeader("DiskFreeSpace Test");
+
+ int64_t freeSpace = FastOS_File::GetFreeDiskSpace("hello.txt");
+ ProgressI64(freeSpace != -1, "DiskFreeSpace using file (hello.txt): %"
+ PRId64 " MB.", freeSpace == -1 ? -1 : freeSpace/(1024*1024));
+ freeSpace = FastOS_File::GetFreeDiskSpace(".");
+ ProgressI64(freeSpace != -1, "DiskFreeSpace using dir (.): %"
+ PRId64 " MB.", freeSpace == -1 ? -1 : freeSpace/(1024*1024));
+ PrintSeparator();
+ }
+
+ void MaxLengthTest ()
+ {
+ TestHeader ("Max Lengths Test");
+
+ int maxval = FastOS_File::GetMaximumFilenameLength(".");
+ Progress(maxval > 5 && maxval < (512*1024),
+ "Maximum filename length = %d", maxval);
+
+ maxval = FastOS_File::GetMaximumPathLength(".");
+ Progress(maxval > 5 && maxval < (512*1024),
+ "Maximum path length = %d", maxval);
+
+ PrintSeparator();
+ }
+
+ void CopyFileTest ()
+ {
+ FastOS_StatInfo statInfo;
+ TestHeader("CopyFile Test");
+ const char *dirName = "tmpDir";
+ char file1[1024];
+ char file2[1024];
+ char file3[1024];
+ char file4[1024];
+ char file5[1024];
+ sprintf(file1, "%s%sfile1", dirName, FastOS_File::GetPathSeparator());
+ sprintf(file2, "%s%sfile2", dirName, FastOS_File::GetPathSeparator());
+ sprintf(file3, "%s%sfile3", dirName, FastOS_File::GetPathSeparator());
+ sprintf(file4, "%s%sfile4", dirName, FastOS_File::GetPathSeparator());
+ sprintf(file5, "%s%sfile5", dirName, FastOS_File::GetPathSeparator());
+
+ FastOS_File::EmptyAndRemoveDirectory(dirName);
+ FastOS_File::MakeDirectory(dirName);
+ printf("Creating files to copy. Some of them are quite large...\n\n");
+ createFile(file1);
+ createFile(file3, 20*1024*1024); // 20MB file.
+ createFile(file4, 1024*1024); // 1MB file, i.e. exact size of buffer.
+ createFile(file5, 1024*1024 + 100); // 1.001MB file
+
+ FastOS_File::Stat(file4, &statInfo);
+ unsigned int sizeOfFile4 = statInfo._size;
+
+ FastOS_File::Stat(file5, &statInfo);
+ unsigned int sizeOfFile5 = statInfo._size;
+
+ // Tests start here.
+ bool copyOK = FastOS_File::CopyFile(file1, file2);
+ Progress(copyOK,
+ "File copy from %s to %s.", file1, file2);
+
+ FastOS_File::Delete(file2);
+ copyOK = FastOS_File::CopyFile(file3, file2);
+ Progress(copyOK,
+ "File copy from %s to %s.", file3, file2);
+ FastOS_File::Stat(file2, &statInfo);
+ Progress(statInfo._size == 20*1024*1024,
+ "Size of copied file is 20MB.");
+
+ copyOK = FastOS_File::CopyFile(file3, file3);
+ Progress(!copyOK,
+ "File copy onto itself should fail.");
+
+ FastOS_File::Delete(file1);
+ copyOK = FastOS_File::CopyFile(file1, file2);
+ Progress(!copyOK,
+ "File copy of a missing file should fail.");
+
+ copyOK = FastOS_File::CopyFile(file4, file2);
+ Progress(copyOK,
+ "Copying a smaller file onto a larger one.");
+ FastOS_File::Stat(file2, &statInfo);
+ Progress(statInfo._size == sizeOfFile4,
+ "Size of copied file should be %u bytes.", sizeOfFile4);
+
+ copyOK = FastOS_File::CopyFile(file4, file1);
+ Progress(copyOK,
+ "Copying a file with exact size of buffer.");
+ FastOS_File::Stat(file1, &statInfo);
+ Progress(statInfo._size == sizeOfFile4,
+ "Size of copied file should be %u bytes.", sizeOfFile4);
+
+ copyOK = FastOS_File::CopyFile(file5, file1);
+ Progress(copyOK,
+ "Copying a file with size %u bytes.", sizeOfFile5);
+ FastOS_File::Stat(file1, &statInfo);
+ Progress(statInfo._size == sizeOfFile5,
+ "Size of copied file should be %u bytes.", sizeOfFile5);
+
+
+ FastOS_File::EmptyAndRemoveDirectory("./tmpDir");
+ PrintSeparator();
+ }
+
+ int Main ()
+ {
+ printf("This test should be run in the 'test/workarea' directory.\n\n");
+ printf("grep for the string '%s' to detect failures.\n\n", failString);
+
+ DirectoryTest();
+ MoveFileTest();
+ CopyFileTest();
+ GetCurrentDirTest();
+ DirectIOTest();
+ MaxLengthTest();
+ DiskFreeSpaceTest();
+ ReadOnlyTest();
+ WriteOnlyTest();
+ ReadWriteTest();
+ ScanDirectoryTest();
+ ReadBufTest();
+ MemoryMapTest();
+
+ PrintSeparator();
+ printf("END OF TEST (%s)\n", _argv[0]);
+
+ return 0;
+ }
+};
+
+const char *FileTest::roFilename = "hello.txt";
+const char *FileTest::woFilename = "generated/writeonlytest.txt";
+const char *FileTest::rwFilename = "generated/readwritetest.txt";
+
+
+int main (int argc, char **argv)
+{
+ FileTest app;
+
+ setvbuf(stdout, NULL, _IOLBF, 8192);
+ return app.Entry(argc, argv);
+}