using XFESystem.Core; using Xunit; namespace XFESystem.Core.Tests; public class WorkspaceTests { [Theory] [InlineData("/etc/passwd")] [InlineData("C:\\Windows")] [InlineData("X:relative")] [InlineData("X:\\Users\\..\\System")] [InlineData("X:\\Users\\Bad:File")] [InlineData("X:\\Users\\Trailing.")] [InlineData("X:\\Users\\Trailing ")] [InlineData("X:\\Users\\Control\u001b")] public void InvalidNamespaceIsRejected(string path) => Assert.Throws(() => SystemPaths.Normalize(path)); [Fact] public void PublicSystemDirectoriesUseWindowsStyleNames() { var storage = new MemoryWorkspace(false); Assert.False(storage.IsPersistent); Assert.Equal(new[] { "Programs", "System", "Temporary", "Users" }, storage.List(SystemPaths.Root).Select(e => e.Name)); Assert.Equal(SystemPaths.Root, SystemPaths.Parent(SystemPaths.System)); Assert.Equal("X:\\System", SystemPaths.Normalize("x:\\\\System\\")); } [Fact] public void MoveDirectoryPreservesSubtreeAndInvalidMovesAreAtomic() { var storage = new MemoryWorkspace(false); storage.CreateDirectory("X:\\Users\\Default\\Documents\\Folder\\Subfolder"); storage.WriteText("X:\\Users\\Default\\Documents\\Folder\\Subfolder\\Text.txt", "hello 中文"); storage.Move("X:\\Users\\Default\\Documents\\Folder", "X:\\Users\\Default\\Documents\\Renamed"); Assert.Equal("hello 中文", storage.ReadText("X:\\Users\\Default\\Documents\\Renamed\\Subfolder\\Text.txt")); Assert.False(storage.Exists("X:\\Users\\Default\\Documents\\Folder")); Assert.Throws(() => storage.Move("X:\\Users\\Default\\Documents\\Renamed", "X:\\Users\\Default\\Documents\\Renamed\\Child")); Assert.Throws(() => storage.Delete("X:\\Users\\Default\\Documents\\Renamed")); Assert.True(storage.Exists("X:\\Users\\Default\\Documents\\Renamed\\Subfolder\\Text.txt")); } [Fact] public void FileCannotReplaceDirectoryOrCreateOrphan() { var storage = new MemoryWorkspace(false); Assert.Throws(() => storage.WriteText(SystemPaths.Documents, "bad")); Assert.Throws(() => storage.WriteText("X:\\Missing\\Text.txt", "bad")); storage.WriteText(SystemPaths.Combine(SystemPaths.Documents, "Case.txt"), "first"); storage.WriteText(SystemPaths.Combine(SystemPaths.Documents, "case.txt"), "second"); Assert.Single(storage.List(SystemPaths.Documents)); Assert.Equal("second", storage.ReadText(SystemPaths.Combine(SystemPaths.Documents, "CASE.txt"))); } [Fact] public void BinaryProgramsAreSeparateFromTextAndMovesRetainExactBytes() { var storage = new MemoryWorkspace(false); var source = SystemPaths.Combine(SystemPaths.Programs, "Hello.dll"); byte[] image = [0x4D, 0x5A, 0x00, 0xFF]; storage.WriteBytes(source, image); image[0] = 0; Assert.Equal(0x4D, storage.ReadBytes(source)[0]); Assert.Throws(() => storage.ReadText(source)); var target = SystemPaths.Combine(SystemPaths.Programs, "Renamed.dll"); storage.Move(source, target); Assert.False(storage.Exists(source)); Assert.Equal(new byte[] { 0x4D, 0x5A, 0x00, 0xFF }, storage.ReadBytes(target)); Assert.Equal(4, Assert.Single(storage.List(SystemPaths.Programs)).Length); storage.Delete(target); Assert.False(storage.Exists(target)); } [Fact] public void MovingLongDescendantRejectsBeforeRemovingAnySource() { var storage = new MemoryWorkspace(false); var child = "X:\\From\\" + string.Join('\\', Enumerable.Repeat(new string('a', 120), 7)) + "\\File.txt"; storage.CreateDirectory(SystemPaths.Parent(child)); storage.WriteText(child, "preserved"); var parent = "X:\\" + new string('b', 120) + "\\" + new string('c', 120); storage.CreateDirectory(parent); var destination = SystemPaths.Combine(parent, "Renamed"); Assert.Throws(() => storage.Move("X:\\From", destination)); Assert.Equal("preserved", storage.ReadText(child)); Assert.False(storage.Exists(destination)); } }