public void Delete() { // Arrange PermutationSetup permutation = new PermutationSetup(); permutation.Add(blockpool_1TB); permutation.Add(blockpool_Pseudo); permutation.Add(case_ms); //permutation.Add(decor_fs); permutation.Add(case_decor_ms); permutation.Add(case_vfs_ms); permutation.Add(case_vfs_2ms); //permutation.Add(vfs_fsms); permutation.Add(init); // Act & Assert foreach (Scenario scenario in permutation.Scenarios) { using (Run run = scenario.Run().Initialize()) { IFileSystem fs = run.Parameters["Class"] as IFileSystem; fs.Observe("**", observer = new Observer()); observer.events.Clear(); try { fs.Delete(""); Assert.Fail(); } catch (IOException) { } try { fs.Delete("."); Assert.Fail(); } catch (IOException) { } try { fs.Delete(".."); Assert.Fail(); } catch (IOException) { } // Delete file fs.Delete("/tmp/../tmp/helloworld.txt"); Assert.IsFalse(fs.Exists("/tmp/helloworld.txt")); Assert.IsTrue(DateTimeOffset.UtcNow - fs.GetEntry("/tmp").LastModified < TimeSpan.FromSeconds(2)); Assert.IsTrue(observer.Last is IDeleteEvent); Assert.IsTrue(DateTimeOffset.UtcNow - observer.Last.EventTime < TimeSpan.FromSeconds(2)); Assert.AreEqual(fs, observer.Last.Observer.FileSystem); Assert.AreEqual("/tmp/helloworld.txt", observer.Last.Path); // Delete dir Assert.IsTrue(fs.Exists("/tmp")); try { fs.Delete("/tmp", false); Assert.Fail(); } catch (IOException) { } // Delete dir tree Assert.IsTrue(fs.Browse("/").Any(e => e.Path == "/tmp/")); Assert.IsTrue(fs.Exists("/tmp")); Assert.IsTrue(fs.Exists("/tmp/")); fs.Delete("/tmp", true); Assert.IsFalse(fs.Browse("/").Any(e => e.Path == "/tmp/")); Assert.IsFalse(fs.Exists("/tmp")); Assert.IsFalse(fs.Exists("/tmp/")); Assert.IsFalse(fs.Exists("/tmp/helloworld_100.txt")); Assert.IsTrue(observer.events.Count >= 4); Assert.IsTrue(observer.Last is IDeleteEvent); Assert.IsTrue(DateTimeOffset.UtcNow - observer.Last.EventTime < TimeSpan.FromSeconds(2)); Assert.AreEqual(fs, observer.Last.Observer.FileSystem); fs.Observe("**", observer = new Observer()); observer.events.Clear(); } } }
public void Browse() { // Arrange PermutationSetup permutation = new PermutationSetup(); permutation.Add(blockpool_1TB); permutation.Add(blockpool_Pseudo); permutation.Add(case_ms); //permutation.Add(decor_fs); permutation.Add(case_decor_ms); permutation.Add(case_vfs_ms); permutation.Add(case_vfs_2ms); //permutation.Add(vfs_fsms); permutation.Add(init); // Act & Assert foreach (Scenario scenario in permutation.Scenarios) { using (Run run = scenario.Run().Initialize()) { IFileSystem ram = run.Parameters["Class"] as IFileSystem; Assert.IsTrue(ram.Browse("/tmp/").Count >= 3); Assert.IsTrue(ram.Browse("c:").Any(e => e.Path == "c:/dir/")); Assert.IsTrue(ram.Browse("c:/dir").Any(e => e.Path == "c:/dir/dir/")); Assert.IsTrue(ram.Browse("./c:/dir").Any(e => e.Path == "c:/dir/dir/")); Assert.IsTrue(ram.Browse("./c:/../c:/dir").Any(e => e.Path == "c:/dir/dir/")); Assert.IsTrue(ram.Browse("/tmp").Any(e => e.Path == "/tmp/helloworld.txt")); Assert.IsTrue(ram.Browse(".//tmp").Any(e => e.Path == "/tmp/helloworld.txt")); Assert.IsTrue(ram.Browse(".//tmp/.").Any(e => e.Path == "/tmp/helloworld.txt")); Assert.IsTrue(ram.Browse(".//tmp/../tmp").Any(e => e.Path == "/tmp/helloworld.txt")); } } }
public void CreateDirectory() { // Arrange PermutationSetup permutation = new PermutationSetup(); permutation.Add(blockpool_1TB); permutation.Add(blockpool_Pseudo); permutation.Add(case_ms); //permutation.Add(decor_fs); permutation.Add(case_decor_ms); permutation.Add(case_vfs_ms); permutation.Add(case_vfs_2ms); //permutation.Add(vfs_fsms); permutation.Add(init); // Act & Assert foreach (Scenario scenario in permutation.Scenarios) { using (Run run = scenario.Run().Initialize()) { IFileSystem fs = run.Parameters["Class"] as IFileSystem; fs.Observe("**", observer = new Observer()); observer.events.Clear(); // root Assert.IsNotNull(fs.GetEntry("")); Assert.IsFalse(fs.Browse("").Any(e => e.Path == "dir1/")); fs.CreateDirectory("dir1/../dir2/../dir3/../dir4"); Assert.IsTrue(fs.Browse("").Any(e => e.Path == "dir1/")); Assert.IsTrue(fs.Exists("dir1/")); Assert.IsTrue(fs.Exists("dir2/")); Assert.IsTrue(fs.Exists("dir3")); Assert.IsTrue(fs.Exists("dir4")); try { fs.CreateDirectory("../dir"); Assert.Fail(); } catch (IOException) { } fs.Observe("**", observer = new Observer()); observer.events.Clear(); } } }
/// <summary> /// Vists tree structure of filesystem. /// /// Starts at <paramref name="path"/> if provided, otherwise starts at root "". /// <paramref name="depth"/> sets maximum visit depths. /// /// "" /// ├──"" /// │ ├──"mnt" /// │ ├──"tmp" /// │ │ └──"helloworld.txt" /// │ └──"usr" /// │ └──"lex" /// └──"c:" /// └──"dir" /// └──"dir" /// /// /// Any thrown exceptions are printed into the line that produced the error. /// </summary> /// <param name="filesystem"></param> /// <param name="path"></param> /// <param name="depth">maximum visit depth</param> /// <param name="option">(optional) operation specific option; capability constraint, a session, security token or credential. Used for authenticating, authorizing or restricting the operation.</param> /// <exception cref="Exception">any exception that GetEntry or Browse can throw</exception> /// <exception cref="IOException">If Browse returns an entry whose path is not under parent entry's path</exception> public static IEnumerable <Line> VisitTree(this IFileSystem filesystem, string path = "", int depth = Int32.MaxValue, IOption option = null) { List <Line> queue = new List <Line>(); IEntry entry = filesystem.GetEntry(path, option); if (entry == null) { yield break; } queue.Add(new Line(entry, 0, 0UL)); while (queue.Count > 0) { // Next entry int lastIx = queue.Count - 1; Line line = queue[lastIx]; queue.RemoveAt(lastIx); // Children if (line.Entry.IsDirectory() && line.Level < depth) { int startIndex = queue.Count; try { // Browse IDirectoryContent content = filesystem.Browse(line.Entry.Path, option); // Assert children don't refer to the parent of the parent foreach (IEntry child in content) { if (line.Entry.Path.StartsWith(child.Path)) { throw new IOException($"{child.Path} cannot be child of {line.Entry.Path}"); } } // Bitmask when this level continues ulong levelContinuesBitMask = line.LevelContinuesBitMask | (line.Level < 64 ? 1UL << line.Level : 0UL); // Add children in reverse order foreach (IEntry child in content) { queue.Add(new Line(child, line.Level + 1, levelContinuesBitMask)); } // Sort the entries that were added if (content.Count > 1) { sorter.QuickSortInverse(ref queue, startIndex, queue.Count - 1); } // Last entry doesn't continue on its level. if (content.Count >= 1) { queue[startIndex] = queue[startIndex].NewLevelContinuesBitMask(line.LevelContinuesBitMask); } } catch (Exception e) { // Add error to be yielded along line.Error = e; } } // yield line yield return(line); } }
public void Open() { // Arrange PermutationSetup permutation = new PermutationSetup(); permutation.Add(blockpool_1TB); permutation.Add(blockpool_Pseudo); permutation.Add(case_ms); //permutation.Add(decor_fs); permutation.Add(case_decor_ms); permutation.Add(case_vfs_ms); permutation.Add(case_vfs_2ms); //permutation.Add(vfs_fsms); permutation.Add(init); // Act & Assert foreach (Scenario scenario in permutation.Scenarios) { using (Run run = scenario.Run().Initialize()) { IFileSystem fs = run.Parameters["Class"] as IFileSystem; fs.Observe("**", observer = new Observer()); observer.events.Clear(); // Open // Points to directory try { fs.Open("/tmp", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); Assert.Fail(); } catch (IOException) { } // File doesn't exist try { fs.Open("/tmp/nonexisting.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); Assert.Fail(); } catch (IOException) { } // Access Control tests try { using (Stream s = fs.Open("/tmp/helloworld.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.None)) using (Stream s2 = fs.Open("/tmp/helloworld.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { } Assert.Fail(); } catch (IOException) { } try { using (Stream s = fs.Open("/tmp/helloworld.txt", FileMode.Open, FileAccess.Write, FileShare.Write)) using (Stream s2 = fs.Open("/tmp/helloworld.txt", FileMode.Open, FileAccess.Read, FileShare.Read)) { }// Should not open Assert.Fail(); } catch (IOException) { } // OpenOrCreate // Invalid filename "", ".", ".." -> fail try { fs.Open("/tmp/", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write); Assert.Fail(); } catch (IOException) { } try { fs.Open("/tmp/.", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write); Assert.Fail(); } catch (IOException) { } try { fs.Open("/tmp/..", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write); Assert.Fail(); } catch (IOException) { } // File already exists (with open stream) -> same file { // Wipe events observer.events.Clear(); // Open handle to same file string path = "/tmp/file1.txt"; Assert.IsFalse(fs.Browse("/tmp").Any(e => e.Path == path)); Stream s1 = fs.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); Stream s2 = fs.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); int len = HelloWorld.Length; s1.Write(HelloWorld); byte[] data = new byte[len]; s2.Read(data); for (int i = 0; i < len; i++) { Assert.AreEqual(HelloWorld[i], data[i]); } // Assert event Assert.IsTrue(observer.events[0] is ICreateEvent); Assert.IsTrue(observer.events[1] is IChangeEvent); Assert.IsTrue(observer.events[0].Path == path); Assert.IsTrue(observer.events[1].Path == path); // Assert parent cache is flushed and children updated Assert.IsTrue(fs.Browse("/tmp").Any(e => e.Path == path)); // Assert entry is ok Assert.IsTrue(fs.GetEntry(path).Path == path); // Wipe events observer.events.Clear(); } // CreateNew - // Invalid filename "", ".", ".." -> fail try { fs.Open("/tmp/", FileMode.CreateNew, FileAccess.Write, FileShare.Write); Assert.Fail(); } catch (IOException) { } try { fs.Open("/tmp/.", FileMode.CreateNew, FileAccess.Write, FileShare.Write); Assert.Fail(); } catch (IOException) { } try { fs.Open("/tmp/..", FileMode.CreateNew, FileAccess.Write, FileShare.Write); Assert.Fail(); } catch (IOException) { } { string path = "/tmp/file2.txt"; Assert.IsFalse(fs.Browse("/tmp").Any(e => e.Path == path)); Stream s1 = fs.Open(path, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite); // File already exists -> fail try { Stream s2 = fs.Open(path, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite); Assert.Fail(); } catch (IOException) { } // Assert event Assert.IsTrue(observer.events[0] is ICreateEvent); Assert.IsTrue(observer.events[0].Path == path); // Assert parent cache is flushed and children updated Assert.IsTrue(fs.Browse("/tmp").Any(e => e.Path == path)); // Assert entry is ok Assert.IsTrue(fs.GetEntry(path).Path == path); // Wipe events observer.events.Clear(); } // Create // Invalid filename "", ".", ".." -> fail try { fs.Open("/tmp/", FileMode.Create, FileAccess.Write, FileShare.Write); Assert.Fail(); } catch (IOException) { } try { fs.Open("/tmp/.", FileMode.Create, FileAccess.Write, FileShare.Write); Assert.Fail(); } catch (IOException) { } try { fs.Open("/tmp/..", FileMode.Create, FileAccess.Write, FileShare.Write); Assert.Fail(); } catch (IOException) { } // File already exists (with open stream) -> previous file is unlinked { // Open handle to same file string path = "/tmp/file3.txt"; Assert.IsFalse(fs.Browse("/tmp").Any(e => e.Path == path)); Stream s1 = fs.Open(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); s1.Write(HelloWorld); s1.Dispose(); int len = HelloWorld.Length; // Replace other file Stream s2 = fs.Open(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); byte[] data = new byte[(int)s2.Length]; s2.Read(data); Assert.AreEqual(0L, s2.Length); // Assert event Assert.IsTrue(observer.events[0] is ICreateEvent); Assert.IsTrue(observer.events[1] is IChangeEvent); Assert.IsTrue(observer.events[0].Path == path); Assert.IsTrue(observer.events[1].Path == path); // Assert parent cache is flushed and children updated Assert.IsTrue(fs.Browse("/tmp").Any(e => e.Path == path)); // Assert entry is ok Assert.IsTrue(fs.GetEntry(path).Path == path); // Wipe events observer.events.Clear(); } fs.Observe("**", observer = new Observer()); observer.events.Clear(); } } }
public void Move() { // Arrange PermutationSetup permutation = new PermutationSetup(); permutation.Add(blockpool_1TB); permutation.Add(blockpool_Pseudo); permutation.Add(case_ms); //permutation.Add(decor_fs); permutation.Add(case_decor_ms); permutation.Add(case_vfs_ms); permutation.Add(case_vfs_2ms); //permutation.Add(vfs_fsms); permutation.Add(init); // Act & Assert foreach (Scenario scenario in permutation.Scenarios) { using (Run run = scenario.Run().Initialize()) { IFileSystem fs = run.Parameters["Class"] as IFileSystem; fs.Observe("**", observer = new Observer()); observer.events.Clear(); // Rename to same file fs.Move("/tmp/helloworld.txt", "/tmp/../tmp/helloworld.txt"); Assert.IsTrue(observer.events.Count == 0); // Move to non-existing dir try { fs.Move("/tmp/helloworld.txt", "/nonexisting/helloworld.txt"); Assert.Fail(); } catch (IOException) { } // Move non-existing file try { fs.Move("/tmp/nonexisting.txt", "/tmp/somefile.txt"); Assert.Fail(); } catch (IOException) { } // Move over to directory try { fs.Move("/tmp/helloworld.txt", "c:"); Assert.Fail(); } catch (IOException) { } // Move a file Assert.IsFalse(fs.Browse("c:").Any(e => e.Path == "c:/helloworld.txt")); Assert.IsTrue(fs.Browse("/tmp").Any(e => e.Path == "/tmp/helloworld.txt")); fs.Move("/tmp/helloworld.txt", "c:/helloworld.txt"); Assert.IsTrue(fs.Browse("c:").Any(e => e.Path == "c:/helloworld.txt")); Assert.IsFalse(fs.Browse("/tmp").Any(e => e.Path == "/tmp/helloworld.txt")); Assert.IsTrue(observer.Last is IRenameEvent); Assert.IsTrue(DateTimeOffset.UtcNow - observer.Last.EventTime < TimeSpan.FromSeconds(2)); Assert.AreEqual(fs, observer.Last.Observer.FileSystem); // Move whole tree Assert.IsFalse(fs.Browse("c:").Any(e => e.Path == "c:/tmp/")); Assert.IsTrue(fs.Browse("/").Any(e => e.Path == "/tmp/")); fs.Move("/tmp/", "c:/tmp/"); Assert.IsTrue(fs.Browse("c:").Any(e => e.Path == "c:/tmp/")); Assert.IsFalse(fs.Browse("/").Any(e => e.Path == "/tmp/")); Assert.IsNull(fs.GetEntry("/tmp/")); Assert.IsTrue(fs.Browse("c:/tmp/").Count >= 3); Assert.IsTrue(observer.Last is IRenameEvent); Assert.IsTrue(DateTimeOffset.UtcNow - observer.Last.EventTime < TimeSpan.FromSeconds(2)); Assert.AreEqual(fs, observer.Last.Observer.FileSystem); Assert.IsTrue(observer.Last.Path.StartsWith("/tmp/")); Assert.IsTrue(observer.Last.NewPath().StartsWith("c:/tmp/")); fs.Observe("**", observer = new Observer()); observer.events.Clear(); } } }