using System; using System.IO; using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; using NzbDrone.Test.Common; using NzbDrone.Test.Common.Categories; namespace NzbDrone.Common.Test { [TestFixture] public class PathExtensionFixture : TestBase { private string _parent = @"C:\Test".AsOsAgnostic(); private IAppFolderInfo GetIAppDirectoryInfo() { var fakeEnvironment = new Mock(); fakeEnvironment.SetupGet(c => c.AppDataFolder).Returns(@"C:\Lidarr\".AsOsAgnostic()); fakeEnvironment.SetupGet(c => c.TempFolder).Returns(@"C:\Temp\".AsOsAgnostic()); return fakeEnvironment.Object; } [TestCase(@"c:\test\", @"c:\test")] [TestCase(@"c:\\test\\", @"c:\test")] [TestCase(@"C:\\Test\\", @"C:\Test")] [TestCase(@"C:\\Test\\Test\", @"C:\Test\Test")] [TestCase(@"\\Testserver\Test\", @"\\Testserver\Test")] [TestCase(@"\\Testserver\\Test\", @"\\Testserver\Test")] [TestCase(@"\\Testserver\Test\file.ext", @"\\Testserver\Test\file.ext")] [TestCase(@"\\Testserver\Test\file.ext\\", @"\\Testserver\Test\file.ext")] [TestCase(@"\\Testserver\Test\file.ext \\", @"\\Testserver\Test\file.ext")] [TestCase(@"//CAPITAL//lower// ", @"\\CAPITAL\lower")] public void Clean_Path_Windows(string dirty, string clean) { WindowsOnly(); var result = dirty.CleanFilePath(); result.Should().Be(clean); } [TestCase(@"/", @"/")] [TestCase(@"/test/", @"/test")] [TestCase(@"//test/", @"/test")] [TestCase(@"//test//", @"/test")] [TestCase(@"//test// ", @"/test")] [TestCase(@"//test//other// ", @"/test/other")] [TestCase(@"//test//other//file.ext ", @"/test/other/file.ext")] [TestCase(@"//CAPITAL//lower// ", @"/CAPITAL/lower")] public void Clean_Path_Linux(string dirty, string clean) { PosixOnly(); var result = dirty.CleanFilePath(); result.Should().Be(clean); } [TestCase(@"C:\", @"C:\")] [TestCase(@"C:\\", @"C:\")] [TestCase(@"C:\Test", @"C:\Test\\")] [TestCase(@"C:\\\\\Test", @"C:\Test\\")] [TestCase(@"C:\Test\\\\", @"C:\Test\\")] [TestCase(@"\\Server\pool", @"\\Server\pool")] [TestCase(@"\\Server\pool\", @"\\Server\pool")] [TestCase(@"\\Server\pool", @"\\Server\pool\")] [TestCase(@"\\Server\pool\", @"\\Server\pool\")] [TestCase(@"\\smallcheese\DRIVE_G\TV-C\Simspsons", @"\\smallcheese\DRIVE_G\TV-C\Simspsons")] public void paths_should_be_equal(string first, string second) { first.AsOsAgnostic().PathEquals(second.AsOsAgnostic()).Should().BeTrue(); } [TestCase(@"c:\", @"C:\")] public void should_be_equal_windows_only(string first, string second) { WindowsOnly(); first.PathEquals(second.AsOsAgnostic()).Should().BeTrue(); } [TestCase(@"C:\Test", @"C:\Test2\")] [TestCase(@"C:\Test\Test", @"C:\TestTest\")] public void paths_should_not_be_equal(string first, string second) { first.AsOsAgnostic().PathEquals(second.AsOsAgnostic()).Should().BeFalse(); } [Test] public void should_return_false_when_not_a_child() { var path = @"C:\Another Folder".AsOsAgnostic(); _parent.IsParentPath(path).Should().BeFalse(); } [Test] public void should_return_true_when_folder_is_parent_of_another_folder() { var path = @"C:\Test\Music".AsOsAgnostic(); _parent.IsParentPath(path).Should().BeTrue(); } [Test] public void should_return_true_when_folder_is_parent_of_a_file() { var path = @"C:\Test\30.Rock.S01E01.Pilot.avi".AsOsAgnostic(); _parent.IsParentPath(path).Should().BeTrue(); } [TestCase(@"C:\Test\", @"C:\Test\mydir")] [TestCase(@"C:\Test\", @"C:\Test\mydir\")] [TestCase(@"C:\Test", @"C:\Test\30.Rock.S01E01.Pilot.avi")] [TestCase(@"C:\", @"C:\Test\30.Rock.S01E01.Pilot.avi")] public void path_should_be_parent(string parentPath, string childPath) { parentPath.AsOsAgnostic().IsParentPath(childPath.AsOsAgnostic()).Should().BeTrue(); } [TestCase(@"C:\Test2\", @"C:\Test")] [TestCase(@"C:\Test\Test\", @"C:\Test\")] [TestCase(@"C:\Test\", @"C:\Test")] [TestCase(@"C:\Test\", @"C:\Test\")] public void path_should_not_be_parent(string parentPath, string childPath) { parentPath.AsOsAgnostic().IsParentPath(childPath.AsOsAgnostic()).Should().BeFalse(); } [TestCase(@"C:\test\", @"C:\Test\mydir")] [TestCase(@"C:\test", @"C:\Test\mydir\")] public void path_should_be_parent_on_windows_only(string parentPath, string childPath) { var expectedResult = OsInfo.IsWindows; parentPath.IsParentPath(childPath).Should().Be(expectedResult); } [TestCase(@"C:\Test\mydir", @"C:\Test")] [TestCase(@"C:\Test\", @"C:\")] [TestCase(@"C:\", null)] [TestCase(@"\\server\share", null)] [TestCase(@"\\server\share\test", @"\\server\share")] public void path_should_return_parent_windows(string path, string parentPath) { WindowsOnly(); path.GetParentPath().Should().Be(parentPath); } [TestCase(@"/", null)] [TestCase(@"/test", "/")] public void path_should_return_parent_mono(string path, string parentPath) { PosixOnly(); path.GetParentPath().Should().Be(parentPath); } [Test] public void path_should_return_parent_for_oversized_path() { PosixOnly(); // This test will fail on Windows if long path support is not enabled: https://www.howtogeek.com/266621/how-to-make-windows-10-accept-file-paths-over-260-characters/ // It will also fail if the app isn't configured to use long path (such as resharper): https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/ var path = @"C:\media\2e168617-f2ae-43fb-b88c-3663af1c8eea\downloads\sabnzbd\lidarr\Some.Real.Big.Thing\With.Alot.Of.Nested.Directories\Some.Real.Big.Thing\With.Alot.Of.Nested.Directories\Some.Real.Big.Thing\With.Alot.Of.Nested.Directories\Some.Real.Big.Thing\With.Alot.Of.Nested.Directories\Some.Real.Big.Thing\With.Alot.Of.Nested.Directories".AsOsAgnostic(); var parentPath = @"C:\media\2e168617-f2ae-43fb-b88c-3663af1c8eea\downloads\sabnzbd\lidarr\Some.Real.Big.Thing\With.Alot.Of.Nested.Directories\Some.Real.Big.Thing\With.Alot.Of.Nested.Directories\Some.Real.Big.Thing\With.Alot.Of.Nested.Directories\Some.Real.Big.Thing\With.Alot.Of.Nested.Directories\Some.Real.Big.Thing".AsOsAgnostic(); path.GetParentPath().Should().Be(parentPath); } [Test] [Ignore("Parent, not Grandparent")] public void should_not_be_parent_when_it_is_grandparent() { var path = Path.Combine(_parent, "parent", "child"); _parent.IsParentPath(path).Should().BeFalse(); } [Test] public void normalize_path_exception_empty() { Assert.Throws(() => "".CleanFilePath()); ExceptionVerification.ExpectedWarns(1); } [Test] public void normalize_path_exception_null() { string nullPath = null; Assert.Throws(() => nullPath.CleanFilePath()); ExceptionVerification.ExpectedWarns(1); } [Test] public void get_actual_casing_for_none_existing_file_return_partially_fixed_result() { WindowsOnly(); "C:\\WINDOWS\\invalidfile.exe".GetActualCasing().Should().Be("C:\\Windows\\invalidfile.exe"); } [Test] public void get_actual_casing_for_none_existing_folder_return_partially_fixed_result() { WindowsOnly(); "C:\\WINDOWS\\SYSTEM32\\FAKEFOLDER\\invalidfile.exe".GetActualCasing().Should().Be("C:\\Windows\\System32\\FAKEFOLDER\\invalidfile.exe"); } [Test] public void get_actual_casing_should_return_actual_casing_for_local_file_in_windows() { WindowsOnly(); var path = Directory.GetDirectories("C:\\")[3]; path.ToUpper().GetActualCasing().Should().Be(path); path.ToLower().GetActualCasing().Should().Be(path); } [Test] public void get_actual_casing_should_return_actual_casing_for_local_dir_in_windows() { WindowsOnly(); var path = Directory.GetCurrentDirectory().Replace("c:\\", "C:\\").Replace("d:\\", "D:\\").Replace("system32", "System32"); path.ToUpper().GetActualCasing().Should().Be(path); path.ToLower().GetActualCasing().Should().Be(path); } [Test] public void get_actual_casing_should_return_original_value_in_linux() { PosixOnly(); var path = Directory.GetCurrentDirectory(); path.GetActualCasing().Should().Be(path); path.GetActualCasing().Should().Be(path); } [Test] [Explicit] [ManualTest] public void get_actual_casing_should_return_original_casing_for_shares() { var path = @"\\server\Pool\Apps"; path.GetActualCasing().Should().Be(path); } [Test] public void AppDataDirectory_path_test() { GetIAppDirectoryInfo().GetAppDataPath().Should().BeEquivalentTo(@"C:\Lidarr\".AsOsAgnostic()); } [Test] public void Config_path_test() { GetIAppDirectoryInfo().GetConfigPath().Should().BeEquivalentTo(@"C:\Lidarr\Config.xml".AsOsAgnostic()); } [Test] public void Sandbox() { GetIAppDirectoryInfo().GetUpdateSandboxFolder().Should().BeEquivalentTo(@"C:\Temp\lidarr_update\".AsOsAgnostic()); } [Test] public void GetUpdatePackageFolder() { GetIAppDirectoryInfo().GetUpdatePackageFolder().Should().BeEquivalentTo(@"C:\Temp\lidarr_update\Lidarr\".AsOsAgnostic()); } [Test] public void GetUpdateClientFolder() { GetIAppDirectoryInfo().GetUpdateClientFolder().Should().BeEquivalentTo(@"C:\Temp\lidarr_update\Lidarr\Lidarr.Update\".AsOsAgnostic()); } [Test] public void GetUpdateClientExePath() { GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\lidarr_update\Lidarr.Update".AsOsAgnostic().ProcessNameToExe()); } [Test] public void GetUpdateLogFolder() { GetIAppDirectoryInfo().GetUpdateLogFolder().Should().BeEquivalentTo(@"C:\Lidarr\UpdateLogs\".AsOsAgnostic()); } [Test] public void GetAncestorFolders_should_return_all_ancestors_in_path_Windows() { WindowsOnly(); var path = @"C:\Test\Music\Artist Title"; var result = path.GetAncestorFolders(); result.Count.Should().Be(4); result[0].Should().Be(@"C:\"); result[1].Should().Be(@"Test"); result[2].Should().Be(@"Music"); result[3].Should().Be(@"Artist Title"); } [Test] public void GetAncestorFolders_should_return_all_ancestors_in_path_Linux() { PosixOnly(); var path = @"/Test/Music/Artist Title"; var result = path.GetAncestorFolders(); result.Count.Should().Be(4); result[0].Should().Be(@"/"); result[1].Should().Be(@"Test"); result[2].Should().Be(@"Music"); result[3].Should().Be(@"Artist Title"); } } }