From f4d627d22efac397ae67e06388aab6b29a1f44e3 Mon Sep 17 00:00:00 2001 From: fanoI Date: Wed, 30 Dec 2015 22:15:19 +0100 Subject: [PATCH] Added new (failing) tests on FAT - Added test to write another file in the same directory - Added test for new method WriteAllLines() - Added test for method WriteAllBytes() / ReadAllBytes() - Added tests to create files in a subdirectory - Added utility method byteArrayAreEquals() --- Tests/Cosmos.Kernel.Tests.Fat/Kernel.cs | 133 +++++++++++++++++- .../Cosmos.System.Plugs/System/IO/FileImpl.cs | 36 ++++- .../System/IO/FileStreamImpl.cs | 89 +++++++++++- .../Cosmos.System/FileSystem/FAT/FatStream.cs | 2 + 4 files changed, 252 insertions(+), 8 deletions(-) diff --git a/Tests/Cosmos.Kernel.Tests.Fat/Kernel.cs b/Tests/Cosmos.Kernel.Tests.Fat/Kernel.cs index 10f106c58f..02be5726eb 100644 --- a/Tests/Cosmos.Kernel.Tests.Fat/Kernel.cs +++ b/Tests/Cosmos.Kernel.Tests.Fat/Kernel.cs @@ -39,10 +39,43 @@ protected override void Run() { Console.WriteLine("Exception occurred"); Console.WriteLine(e.Message); + mDebugger.Send("Exception occurred: " + e.Message); TestController.Failed(); } } + // Utility method to test Byte Array equality if Generics would have worked it could have been done universal + public bool byteArrayAreEquals(byte[] a1, byte[] a2) + { + if (ReferenceEquals(a1, a2)) + { + mDebugger.Send("byte Array a1 and a2 are the same Object"); + return true; + } + + if (a1 == null || a2 == null) + { + mDebugger.Send("a1 or a2 is null so are different"); + return false; + } + + if (a1.Length != a2.Length) { + mDebugger.Send("a1.Length != a2.Length so are different"); + return false; + } + + for (int i = 0; i < a1.Length; i++) + { + if (a1[i] != a2[i]) + { + mDebugger.Send("In position " + i + " a byte is different"); + return false; + } + } + + return true; + } + public void TestPath() { string xMessage; @@ -356,12 +389,104 @@ private void TestFile() // mDebugger.Send("START TEST: Create file:"); - var xFile = File.Create(@"0:\test2.txt"); - Assert.IsTrue(xFile != null, "Failed to create a new file."); - bool xFileExists = File.Exists(@"0:\test2.txt"); - Assert.IsTrue(xFileExists, "Failed to create a new file."); + // Attention! File.Create() returns a FileStream that should be Closed / Disposed on Windows trying to write to the file next gives "File in Use" exception! + using (var xFile = File.Create(@"0:\test2.txt")) + { + Assert.IsTrue(xFile != null, "Failed to create a new file."); + bool xFileExists = File.Exists(@"0:\test2.txt"); + Assert.IsTrue(xFileExists, "Failed to create a new file."); + mDebugger.Send("END TEST"); + mDebugger.Send(""); + } + + // Possible issue: writing to another file in the same directory, the data are mixed with the other files + mDebugger.Send("Write to another file now"); + File.WriteAllText(@"0:\test2.txt", "123"); + mDebugger.Send("Text written"); + xContents = File.ReadAllText(@"0:\test2.txt"); + mDebugger.Send("Contents retrieved after writing"); + mDebugger.Send(xContents); + Assert.IsTrue(xContents == "123", "Contents of test2.txt was written incorrectly!"); mDebugger.Send("END TEST"); mDebugger.Send(""); + + // Now we write in test2.txt using WriteAllLines() + mDebugger.Send("START TEST: WriteAllLines:"); + using (var xFile = File.Create(@"0:\test3.txt")) + { + Assert.IsTrue(xFile != null, "Failed to create a new file."); + bool xFileExists = File.Exists(@"0:\test3.txt"); + Assert.IsTrue(xFileExists, "Failed to create a new file."); + mDebugger.Send("END TEST"); + mDebugger.Send(""); + } + + String[] contents = { "One", "Two", "Three" }; + File.WriteAllLines(@"0:\test3.txt", contents); + mDebugger.Send("Text written"); + // TODO maybe the more correct test is to implement ReadAllLines and then check that two arrays are equals + xContents = File.ReadAllText(@"0:\test3.txt"); + mDebugger.Send("Contents retrieved after writing"); + mDebugger.Send(xContents); + Assert.IsTrue(xContents == "One\nTwo\nThree", "Contents of test3.txt was written incorrectly!"); + mDebugger.Send("END TEST"); + mDebugger.Send(""); + + // + mDebugger.Send("START TEST: Write binary data to file now:"); + using (var xFile = File.Create(@"0:\test.dat")) { + Assert.IsTrue(xFile != null, "Failed to create a new file."); + } + byte[] dataWritten = new byte[] { 0x01, 0x02, 0x03 }; + File.WriteAllBytes(@"0:\test.dat", dataWritten); + mDebugger.Send("Text written"); + byte[] dataRead = File.ReadAllBytes(@"0:\test.dat"); + + Assert.IsTrue(byteArrayAreEquals(dataWritten, dataRead), "Failed to write binary data to a file."); + mDebugger.Send("END TEST"); + mDebugger.Send(""); + + mDebugger.Send("START TEST: Append text to file:"); + string appendedText = "Yet other text."; + File.AppendAllText(@"0:\Kudzu.txt", appendedText); + mDebugger.Send("Text appended"); + xContents = File.ReadAllText(@"0:\Kudzu.txt"); + mDebugger.Send("Contents retrieved after writing"); + mDebugger.Send(xContents); + Assert.IsTrue(xContents == "Test FAT write.\nYet other text.", "Contents of Kudzu.txt was appended incorrectly!"); + mDebugger.Send("END TEST"); + mDebugger.Send(""); + + // This creates a loop? Nothing is printed when VFSManager.CreateStream() method is reached... + mDebugger.Send("START TEST: Create a new directory with a file inside (filestream):"); + var xDirectory = Directory.CreateDirectory(@"0:\testdir"); + Assert.IsTrue(xDirectory != null, "Failed to create a new directory."); + using (var xFile2 = File.Create(@"0:\testdir\file.txt")) + { + String wText = "This a test"; + Byte[] xWriteBuff = wText.GetUtf8Bytes(0, (uint)wText.Length); + xFile2.Write(xWriteBuff, 0, xWriteBuff.Length); + mDebugger.Send("---- Data written"); + xFile2.Position = 0; + Byte[] xReadBuff = new byte[xWriteBuff.Length]; + xFile2.Read(xReadBuff, 0, xWriteBuff.Length); + mDebugger.Send("xWriteBuff " + xWriteBuff.GetUtf8String(0, (uint)xWriteBuff.Length) + " xReadBuff " + xReadBuff.GetUtf8String(0, (uint)xWriteBuff.Length)); + String xWriteBuffAsString = xWriteBuff.GetUtf8String(0, (uint)xWriteBuff.Length); + String xReadBuffAsString = xReadBuff.GetUtf8String(0, (uint)xReadBuff.Length); + Assert.IsTrue(xWriteBuffAsString == xReadBuffAsString, "Failed to write and read file"); + mDebugger.Send("END TEST"); + } + + mDebugger.Send("START TEST: Create a new directory with a file inside (File):"); + var xDirectory2 = Directory.CreateDirectory(@"0:\testdir"); + Assert.IsTrue(xDirectory2 != null, "Failed to create a new directory."); + String WrittenText = "This a test"; + File.WriteAllText(@"0:\testdir\file.txt", WrittenText); + mDebugger.Send("Text written"); + // now read it + xContents = File.ReadAllText(@"0:\testdir\file.txt"); + mDebugger.Send("Contents retrieved"); + Assert.IsTrue(xContents == WrittenText, "Failed to read from file"); } private void TestDirectory() diff --git a/source/Cosmos.System.Plugs/System/IO/FileImpl.cs b/source/Cosmos.System.Plugs/System/IO/FileImpl.cs index b05383e3e5..0c11011366 100644 --- a/source/Cosmos.System.Plugs/System/IO/FileImpl.cs +++ b/source/Cosmos.System.Plugs/System/IO/FileImpl.cs @@ -36,13 +36,44 @@ public static string ReadAllText(string aFile) public static void WriteAllText(string aFile, string aText) { + FileSystemHelpers.Debug("Creating stream with file " + aFile); using (var xFS = new FileStream(aFile, FileMode.Create)) { + FileSystemHelpers.Debug("Converting " + aText + " to UFT8"); var xBuff = aText.GetUtf8Bytes(0, (uint)aText.Length); + FileSystemHelpers.Debug("Writing bytes"); xFS.Write(xBuff, 0, xBuff.Length); + FileSystemHelpers.Debug("Bytes written"); } } + public static void AppendAllText(string aFile, string aText) + { + FileSystemHelpers.Debug("Creating stream in Append Mode with file " + aFile); + using (var xFS = new FileStream(aFile, FileMode.Append)) + { + FileSystemHelpers.Debug("Converting " + aText + " to UFT8"); + var xBuff = aText.GetUtf8Bytes(0, (uint)aText.Length); + FileSystemHelpers.Debug("Writing bytes"); + xFS.Write(xBuff, 0, xBuff.Length); + FileSystemHelpers.Debug("Bytes written"); + } + } + + public static void WriteAllLines(string path, string[] contents) + { + String text = String.Empty; + + for (int i = 0; i < contents.Length; i++) + { + text += contents[i]; + text += '\n'; + } + + FileSystemHelpers.Debug("Writing contents\n" + text); + WriteAllText(path, text); + } + public static byte[] ReadAllBytes(string aFile) { FileSystemHelpers.Debug("In FileImpl.ReadAllText"); @@ -64,9 +95,10 @@ public static void WriteAllBytes(string aFile, byte[] aBytes) { using (var xFS = new FileStream(aFile, FileMode.Create)) { - var xBuff = aBytes; + // This variable is not needed 'aBytes' is already a Byte[] + //var xBuff = aBytes; - xFS.Write(xBuff, 0, xBuff.Length); + xFS.Write(aBytes, 0, aBytes.Length); } } diff --git a/source/Cosmos.System.Plugs/System/IO/FileStreamImpl.cs b/source/Cosmos.System.Plugs/System/IO/FileStreamImpl.cs index ae818f727f..3f34322612 100644 --- a/source/Cosmos.System.Plugs/System/IO/FileStreamImpl.cs +++ b/source/Cosmos.System.Plugs/System/IO/FileStreamImpl.cs @@ -93,14 +93,99 @@ private static Stream InitializeStream(string aPath, FileMode aMode) if (aPath == null) { FileSystemHelpers.Debug("In FileStream.Ctor: Path == null is true"); - throw new Exception("The file path cannot be null."); + throw new ArgumentNullException("The file path cannot be null."); } if (aPath.Length == 0) { FileSystemHelpers.Debug("In FileStream.Ctor: Path.Length == 0 is true"); - throw new Exception("The file path cannot be empty."); + throw new ArgumentException("The file path cannot be empty."); } + + //FileSystemHelpers.Debug("Calling VFSManager.GetFileStream..."); return VFSManager.GetFileStream(aPath); + + // Naive and not working implementation of FileMode. Probably is better to do this at lower level... +#if false + // Before let's see if aPath already exists + bool aPathExists = File.Exists(aPath); + + Stream aStream = null; + + switch (aMode) + { + case FileMode.Append: + // TODO it seems that GetFileStream effectively Creates the file if not exist + aStream = VFSManager.GetFileStream(aPath); + if (aPathExists) + { + FileSystemHelpers.Debug("Append mode with aPath already existing let's seek to end of the file"); + FileSystemHelpers.Debug("Actual aStream Lenght: ", aStream.Length); + aStream.Position = aStream.Length; + //aStream.Seek(0, SeekOrigin.End); + } + else + { + FileSystemHelpers.Debug("Append mode with aPath not existing let's create a new the file"); + } + break; + + case FileMode.Create: + FileSystemHelpers.Debug("Create Mode aPath will be overwritten if existing"); + // TODO it seems that GetFileStream effectively Creates the file if not exist + aStream = VFSManager.GetFileStream(aPath); + break; + + case FileMode.CreateNew: + if (aPathExists) + { + FileSystemHelpers.Debug("CreateNew Mode with aPath already existing"); + throw new IOException("File already existing but CreateNew Requested"); + } + + FileSystemHelpers.Debug("CreateNew Mode with aPath not existing new file created"); + // TODO it seems that GetFileStream effectively Creates the file if it does not exist + aStream = VFSManager.GetFileStream(aPath); + break; + + case FileMode.Open: + if (!aPathExists) + { + FileSystemHelpers.Debug("Open Mode with aPath not existing"); + throw new IOException("File not existing but Open Requested"); + } + + FileSystemHelpers.Debug("Open Mode with aPath existing opening file"); + // TODO it seems that GetFileStream effectively Creates the file if it does not exist + aStream = VFSManager.GetFileStream(aPath); + aStream.Position = 0; + break; + + case FileMode.OpenOrCreate: + FileSystemHelpers.Debug("CreateNew Mode with aPath not existing new file created"); + // TODO it seems that GetFileStream effectively Creates the file if it does not exist + aStream = VFSManager.GetFileStream(aPath); + break; + + case FileMode.Truncate: + if (!aPathExists) + { + FileSystemHelpers.Debug("Truncate Mode with aPath not existing"); + throw new IOException("File not existing but Truncate Requested"); + } + + FileSystemHelpers.Debug("Truncate Mode with aPath existing change its lenght to 0 bytes"); + // TODO it seems that GetFileStream effectively Creates the file if it does not exist + aStream = VFSManager.GetFileStream(aPath); + aStream.SetLength(0); + break; + + default: + FileSystemHelpers.Debug("The mode " + aMode + "is out of range"); + throw new ArgumentOutOfRangeException("The file mode is invalid"); + } + + return aStream; +#endif } } } diff --git a/source/Cosmos.System/FileSystem/FAT/FatStream.cs b/source/Cosmos.System/FileSystem/FAT/FatStream.cs index 0b102ea9bf..b0199c456f 100644 --- a/source/Cosmos.System/FileSystem/FAT/FatStream.cs +++ b/source/Cosmos.System/FileSystem/FAT/FatStream.cs @@ -29,6 +29,8 @@ internal class FatStream : Stream public FatStream(FatDirectoryEntry aEntry) { + FileSystemHelpers.Debug("FatStream with entry " + aEntry); + mDirectoryEntry = aEntry; mFS = mDirectoryEntry.GetFileSystem(); mSize = mDirectoryEntry.mSize;