ManagedFileSystemTests.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. using System;
  2. using System.Diagnostics.CodeAnalysis;
  3. using System.IO;
  4. using System.Runtime.InteropServices;
  5. using AutoFixture;
  6. using AutoFixture.AutoMoq;
  7. using Emby.Server.Implementations.IO;
  8. using Jellyfin.Extensions;
  9. using Xunit;
  10. namespace Jellyfin.Server.Implementations.Tests.IO;
  11. public class ManagedFileSystemTests
  12. {
  13. private readonly IFixture _fixture;
  14. private readonly ManagedFileSystem _sut;
  15. public ManagedFileSystemTests()
  16. {
  17. _fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
  18. _sut = _fixture.Create<ManagedFileSystem>();
  19. }
  20. [Fact]
  21. public void MoveDirectory_SameFileSystem_Correct()
  22. => MoveDirectoryInternal();
  23. [SkippableFact]
  24. public void MoveDirectory_DifferentFileSystem_Correct()
  25. {
  26. const string DestinationParent = "/dev/shm";
  27. Skip.IfNot(Directory.Exists(DestinationParent));
  28. MoveDirectoryInternal(DestinationParent);
  29. }
  30. internal void MoveDirectoryInternal(string? destinationParent = null)
  31. {
  32. const string TempFile0 = "tempfile0";
  33. const string TempFile1 = "tempfile1";
  34. destinationParent ??= Path.GetTempPath();
  35. var sourceDir = Directory.CreateTempSubdirectory();
  36. var destinationDir = Path.Join(destinationParent, Path.GetRandomFileName());
  37. FileHelper.CreateEmpty(Path.Join(sourceDir.FullName, TempFile0));
  38. FileHelper.CreateEmpty(Path.Join(sourceDir.FullName, TempFile1));
  39. _sut.MoveDirectory(sourceDir.FullName, destinationDir);
  40. Assert.True(Directory.Exists(destinationDir));
  41. Assert.True(File.Exists(Path.Join(destinationDir, TempFile0)));
  42. Assert.True(File.Exists(Path.Join(destinationDir, TempFile1)));
  43. Assert.False(Directory.Exists(sourceDir.FullName));
  44. Directory.Delete(destinationDir, true);
  45. }
  46. [SkippableTheory]
  47. [InlineData("/Volumes/Library/Sample/Music/Playlists/", "../Beethoven/Misc/Moonlight Sonata.mp3", "/Volumes/Library/Sample/Music/Beethoven/Misc/Moonlight Sonata.mp3")]
  48. [InlineData("/Volumes/Library/Sample/Music/Playlists/", "../../Beethoven/Misc/Moonlight Sonata.mp3", "/Volumes/Library/Sample/Beethoven/Misc/Moonlight Sonata.mp3")]
  49. [InlineData("/Volumes/Library/Sample/Music/Playlists/", "Beethoven/Misc/Moonlight Sonata.mp3", "/Volumes/Library/Sample/Music/Playlists/Beethoven/Misc/Moonlight Sonata.mp3")]
  50. [InlineData("/Volumes/Library/Sample/Music/Playlists/", "/mnt/Beethoven/Misc/Moonlight Sonata.mp3", "/mnt/Beethoven/Misc/Moonlight Sonata.mp3")]
  51. public void MakeAbsolutePathCorrectlyHandlesRelativeFilePathsOnUnixLike(
  52. string folderPath,
  53. string filePath,
  54. string expectedAbsolutePath)
  55. {
  56. Skip.If(OperatingSystem.IsWindows());
  57. var generatedPath = _sut.MakeAbsolutePath(folderPath, filePath);
  58. Assert.Equal(expectedAbsolutePath, generatedPath);
  59. }
  60. [SkippableTheory]
  61. [InlineData(@"C:\\Volumes\Library\Sample\Music\Playlists\", @"..\Beethoven\Misc\Moonlight Sonata.mp3", @"C:\Volumes\Library\Sample\Music\Beethoven\Misc\Moonlight Sonata.mp3")]
  62. [InlineData(@"C:\\Volumes\Library\Sample\Music\Playlists\", @"..\..\Beethoven\Misc\Moonlight Sonata.mp3", @"C:\Volumes\Library\Sample\Beethoven\Misc\Moonlight Sonata.mp3")]
  63. [InlineData(@"C:\\Volumes\Library\Sample\Music\Playlists\", @"Beethoven\Misc\Moonlight Sonata.mp3", @"C:\Volumes\Library\Sample\Music\Playlists\Beethoven\Misc\Moonlight Sonata.mp3")]
  64. [InlineData(@"C:\\Volumes\Library\Sample\Music\Playlists\", @"D:\\Beethoven\Misc\Moonlight Sonata.mp3", @"D:\\Beethoven\Misc\Moonlight Sonata.mp3")]
  65. public void MakeAbsolutePathCorrectlyHandlesRelativeFilePathsOnWindows(
  66. string folderPath,
  67. string filePath,
  68. string expectedAbsolutePath)
  69. {
  70. Skip.IfNot(OperatingSystem.IsWindows());
  71. var generatedPath = _sut.MakeAbsolutePath(folderPath, filePath);
  72. Assert.Equal(expectedAbsolutePath, generatedPath);
  73. }
  74. [Theory]
  75. [InlineData("ValidFileName", "ValidFileName")]
  76. [InlineData("AC/DC", "AC DC")]
  77. [InlineData("Invalid\0", "Invalid ")]
  78. [InlineData("AC/DC\0KD/A", "AC DC KD A")]
  79. public void GetValidFilename_ReturnsValidFilename(string filename, string expectedFileName)
  80. {
  81. Assert.Equal(expectedFileName, _sut.GetValidFilename(filename));
  82. }
  83. [SkippableFact]
  84. public void GetFileInfo_DanglingSymlink_ExistsFalse()
  85. {
  86. Skip.If(OperatingSystem.IsWindows());
  87. string testFileDir = Path.Combine(Path.GetTempPath(), "jellyfin-test-data");
  88. string testFileName = Path.Combine(testFileDir, Path.GetRandomFileName() + "-danglingsym.link");
  89. Directory.CreateDirectory(testFileDir);
  90. Assert.Equal(0, symlink("thispathdoesntexist", testFileName));
  91. Assert.True(File.Exists(testFileName));
  92. var metadata = _sut.GetFileInfo(testFileName);
  93. Assert.False(metadata.Exists);
  94. }
  95. [SuppressMessage("Naming Rules", "SA1300:ElementMustBeginWithUpperCaseLetter", Justification = "Have to")]
  96. [DllImport("libc", SetLastError = true, CharSet = CharSet.Ansi)]
  97. [DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
  98. private static extern int symlink(string target, string linkpath);
  99. }