mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-05-31 20:24:27 -04:00
* Fixed a bug which didn't take sort direction when not changing sort field * Added foundation for Bookmark refactor * Code broken, need to take a break. Issue is Getting bookmark image needs authentication but UI doesn't send. * Implemented the ability to send bookmarked files to the web. Implemented ability to clear bookmarks on disk on a re-occuring basis. * Updated the bookmark design to have it's own card that is self contained. View bookmarks modal has been updated to better lay out the cards. * Refactored download bookmark codes to select files from bookmark directory directly rather than open underlying files. * Wrote the basic logic to kick start the bookmark migration. Added Installed Version into the DB to allow us to know more accurately when to run migrations * Implemented the ability to change the bookmarks directory * Updated all references to BookmarkDirectory to use setting from the DB. Updated Server Settings page to use 2 col for some rows. * Refactored some code to DirectoryService (hasWriteAccess) and fixed up some unit tests from a previous PR. * Treat folders that start with ._ as blacklisted. * Implemented Reset User preferences. Some extra code to prep for the migration. * Implemented a migration for existing bookmarks to using new filesystem based bookmarks
759 lines
32 KiB
C#
759 lines
32 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.IO.Abstractions;
|
|
using System.IO.Abstractions.TestingHelpers;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using API.Services;
|
|
using Microsoft.Extensions.Logging;
|
|
using NSubstitute;
|
|
using Xunit;
|
|
|
|
namespace API.Tests.Services
|
|
{
|
|
|
|
public class DirectoryServiceTests
|
|
{
|
|
private readonly DirectoryService _directoryService;
|
|
private readonly ILogger<DirectoryService> _logger = Substitute.For<ILogger<DirectoryService>>();
|
|
|
|
public DirectoryServiceTests()
|
|
{
|
|
var filesystem = new MockFileSystem()
|
|
{
|
|
|
|
};
|
|
|
|
_directoryService = new DirectoryService(_logger, filesystem);
|
|
}
|
|
|
|
|
|
#region TraverseTreeParallelForEach
|
|
[Fact]
|
|
public void TraverseTreeParallelForEach_JustArchives_ShouldBe28()
|
|
{
|
|
var testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 28; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"{testDirectory}file_{29}.jpg", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = new List<string>();
|
|
var fileCount = ds.TraverseTreeParallelForEach(testDirectory, s => files.Add(s),
|
|
API.Parser.Parser.ArchiveFileExtensions, _logger);
|
|
|
|
Assert.Equal(28, fileCount);
|
|
Assert.Equal(28, files.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void TraverseTreeParallelForEach_DontCountExcludedDirectories_ShouldBe28()
|
|
{
|
|
var testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 28; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"{Path.Join(testDirectory, "@eaDir")}file_{29}.jpg", new MockFileData(""));
|
|
fileSystem.AddFile($"{Path.Join(testDirectory, ".DS_Store")}file_{30}.jpg", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = new List<string>();
|
|
var fileCount = ds.TraverseTreeParallelForEach(testDirectory, s => files.Add(s),
|
|
API.Parser.Parser.ArchiveFileExtensions, _logger);
|
|
|
|
Assert.Equal(28, fileCount);
|
|
Assert.Equal(28, files.Count);
|
|
}
|
|
#endregion
|
|
|
|
#region GetFilesWithCertainExtensions
|
|
[Fact]
|
|
public void GetFilesWithCertainExtensions_ShouldBe10()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"{testDirectory}file_{29}.jpg", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFilesWithExtension(testDirectory, API.Parser.Parser.ArchiveFileExtensions);
|
|
|
|
Assert.Equal(10, files.Length);
|
|
Assert.All(files, s => fileSystem.Path.GetExtension(s).Equals(".zip"));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFilesWithCertainExtensions_OnlyArchives()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"{testDirectory}file_{29}.rar", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFilesWithExtension(testDirectory, ".zip|.rar");
|
|
|
|
Assert.Equal(11, files.Length);
|
|
}
|
|
#endregion
|
|
|
|
#region GetFiles
|
|
[Fact]
|
|
public void GetFiles_ArchiveOnly_ShouldBe10()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"{testDirectory}file_{29}.jpg", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFiles(testDirectory, API.Parser.Parser.ArchiveFileExtensions).ToList();
|
|
|
|
Assert.Equal(10, files.Count());
|
|
Assert.All(files, s => fileSystem.Path.GetExtension(s).Equals(".zip"));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFiles_All_ShouldBe11()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"{testDirectory}file_{29}.jpg", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFiles(testDirectory).ToList();
|
|
|
|
Assert.Equal(11, files.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFiles_All_MixedPathSeparators()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"/manga\\file_{29}.jpg", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFiles(testDirectory).ToList();
|
|
|
|
Assert.Equal(11, files.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFiles_All_TopDirectoryOnly_ShouldBe10()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"{testDirectory}/SubDir/file_{29}.jpg", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFiles(testDirectory).ToList();
|
|
|
|
Assert.Equal(10, files.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFiles_WithSubDirectories_ShouldCountOnlyTopLevel()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"{testDirectory}/SubDir/file_{29}.jpg", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFiles(testDirectory).ToList();
|
|
|
|
Assert.Equal(10, files.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFiles_ShouldNotReturnFilesThatAreExcluded()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
fileSystem.AddFile($"{testDirectory}/._file_{29}.jpg", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFiles(testDirectory).ToList();
|
|
|
|
Assert.Equal(10, files.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFiles_WithCustomRegex_ShouldBe10()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}data-{i}.txt", new MockFileData(""));
|
|
}
|
|
fileSystem.AddFile($"{testDirectory}joe.txt", new MockFileData(""));
|
|
fileSystem.AddFile($"{testDirectory}0d.txt", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFiles(testDirectory, @".*d.*\.txt");
|
|
Assert.Equal(11, files.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFiles_WithCustomRegexThatContainsFolder_ShouldBe10()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file/data-{i}.txt", new MockFileData(""));
|
|
}
|
|
fileSystem.AddFile($"{testDirectory}joe.txt", new MockFileData(""));
|
|
fileSystem.AddFile($"{testDirectory}0d.txt", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var files = ds.GetFiles(testDirectory, @".*d.*\.txt", SearchOption.AllDirectories);
|
|
Assert.Equal(11, files.Count());
|
|
}
|
|
#endregion
|
|
|
|
#region GetTotalSize
|
|
[Fact]
|
|
public void GetTotalSize_ShouldBeGreaterThan0()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file/data-{i}.txt", new MockFileData("abc"));
|
|
}
|
|
fileSystem.AddFile($"{testDirectory}joe.txt", new MockFileData(""));
|
|
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var fileSize = ds.GetTotalSize(fileSystem.AllFiles);
|
|
Assert.True(fileSize > 0);
|
|
}
|
|
#endregion
|
|
|
|
#region CopyFileToDirectory
|
|
[Fact]
|
|
public void CopyFileToDirectory_ShouldCopyFileToNonExistentDirectory()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}file/data-0.txt", new MockFileData("abc"));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.CopyFileToDirectory($"{testDirectory}file/data-0.txt", "/manga/output/");
|
|
Assert.True(fileSystem.FileExists("manga/output/data-0.txt"));
|
|
Assert.True(fileSystem.FileExists("manga/file/data-0.txt"));
|
|
}
|
|
[Fact]
|
|
public void CopyFileToDirectory_ShouldCopyFileToExistingDirectoryAndOverwrite()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}file/data-0.txt", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}output/data-0.txt", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.CopyFileToDirectory($"{testDirectory}file/data-0.txt", "/manga/output/");
|
|
Assert.True(fileSystem.FileExists("/manga/output/data-0.txt"));
|
|
Assert.True(fileSystem.FileExists("/manga/file/data-0.txt"));
|
|
Assert.True(fileSystem.FileInfo.FromFileName("/manga/file/data-0.txt").Length == fileSystem.FileInfo.FromFileName("/manga/output/data-0.txt").Length);
|
|
}
|
|
#endregion
|
|
|
|
#region CopyDirectoryToDirectory
|
|
[Fact]
|
|
public void CopyDirectoryToDirectory_ShouldThrowWhenSourceDestinationDoesntExist()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}file/data-0.txt", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}output/data-0.txt", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var ex = Assert.Throws<DirectoryNotFoundException>(() => ds.CopyDirectoryToDirectory("/comics/", "/manga/output/"));
|
|
Assert.Equal(ex.Message, "Source directory does not exist or could not be found: " + "/comics/");
|
|
}
|
|
|
|
[Fact]
|
|
public void CopyDirectoryToDirectory_ShouldCopyEmptyDirectory()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}file/data-0.txt", new MockFileData("abc"));
|
|
fileSystem.AddDirectory($"{testDirectory}empty/");
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.CopyDirectoryToDirectory($"{testDirectory}empty/", "/manga/output/");
|
|
Assert.Empty(fileSystem.DirectoryInfo.FromDirectoryName("/manga/output/").GetFiles());
|
|
}
|
|
|
|
[Fact]
|
|
public void CopyDirectoryToDirectory_ShouldCopyAllFileAndNestedDirectoriesOver()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}file/data-0.txt", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}data-1.txt", new MockFileData("abc"));
|
|
fileSystem.AddDirectory($"{testDirectory}empty/");
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.CopyDirectoryToDirectory($"{testDirectory}", "/manga/output/");
|
|
Assert.Equal(2, ds.GetFiles("/manga/output/", searchOption: SearchOption.AllDirectories).Count());
|
|
}
|
|
#endregion
|
|
|
|
#region IsDriveMounted
|
|
[Fact]
|
|
public void IsDriveMounted_DriveIsNotMounted()
|
|
{
|
|
const string testDirectory = "c:/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}data-0.txt", new MockFileData("abc"));
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
|
|
Assert.False(ds.IsDriveMounted("d:/manga/"));
|
|
}
|
|
|
|
[Fact]
|
|
public void IsDriveMounted_DriveIsMounted()
|
|
{
|
|
const string testDirectory = "c:/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}data-0.txt", new MockFileData("abc"));
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
|
|
Assert.True(ds.IsDriveMounted("c:/manga/file"));
|
|
}
|
|
#endregion
|
|
|
|
#region IsDirectoryEmpty
|
|
[Fact]
|
|
public void IsDirectoryEmpty_DirectoryIsEmpty()
|
|
{
|
|
const string testDirectory = "c:/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddDirectory(testDirectory);
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
|
|
Assert.True(ds.IsDirectoryEmpty("c:/manga/"));
|
|
}
|
|
|
|
[Fact]
|
|
public void IsDirectoryEmpty_DirectoryIsNotEmpty()
|
|
{
|
|
const string testDirectory = "c:/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}data-0.txt", new MockFileData("abc"));
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
|
|
Assert.False(ds.IsDirectoryEmpty("c:/manga/"));
|
|
}
|
|
#endregion
|
|
|
|
#region ExistOrCreate
|
|
[Fact]
|
|
public void ExistOrCreate_ShouldCreate()
|
|
{
|
|
var fileSystem = new MockFileSystem();
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.ExistOrCreate("c:/manga/output/");
|
|
|
|
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName("c:/manga/output/").Exists);
|
|
}
|
|
#endregion
|
|
|
|
#region ClearAndDeleteDirectory
|
|
[Fact]
|
|
public void ClearAndDeleteDirectory_ShouldDeleteSelfAndAllFilesAndFolders()
|
|
{
|
|
const string testDirectory = "/manga/base/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file/data-{i}.txt", new MockFileData("abc"));
|
|
}
|
|
fileSystem.AddFile($"{testDirectory}data-a.txt", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}data-b.txt", new MockFileData("abc"));
|
|
fileSystem.AddDirectory($"{testDirectory}empty/");
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.ClearAndDeleteDirectory($"{testDirectory}");
|
|
Assert.Empty(ds.GetFiles("/manga/", searchOption: SearchOption.AllDirectories));
|
|
Assert.Empty(ds.FileSystem.DirectoryInfo.FromDirectoryName("/manga/").GetDirectories());
|
|
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName("/manga/").Exists);
|
|
Assert.False(ds.FileSystem.DirectoryInfo.FromDirectoryName("/manga/base").Exists);
|
|
}
|
|
#endregion
|
|
|
|
#region ClearDirectory
|
|
[Fact]
|
|
public void ClearDirectory_ShouldDeleteAllFilesAndFolders_LeaveSelf()
|
|
{
|
|
const string testDirectory = "/manga/base/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file/data-{i}.txt", new MockFileData("abc"));
|
|
}
|
|
fileSystem.AddFile($"{testDirectory}data-a.txt", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}data-b.txt", new MockFileData("abc"));
|
|
fileSystem.AddDirectory($"{testDirectory}file/empty/");
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.ClearDirectory($"{testDirectory}file/");
|
|
Assert.Empty(ds.FileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}file/").GetDirectories());
|
|
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName("/manga/").Exists);
|
|
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}file/").Exists);
|
|
}
|
|
|
|
[Fact]
|
|
public void ClearDirectory_ShouldDeleteFoldersWithOneFileInside()
|
|
{
|
|
const string testDirectory = "/manga/base/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file/data-{i}.txt", new MockFileData("abc"));
|
|
}
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.ClearDirectory($"{testDirectory}");
|
|
Assert.Empty(ds.FileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}").GetDirectories());
|
|
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName(testDirectory).Exists);
|
|
Assert.False(ds.FileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}file/").Exists);
|
|
}
|
|
#endregion
|
|
|
|
#region CopyFilesToDirectory
|
|
[Fact]
|
|
public void CopyFilesToDirectory_ShouldMoveAllFiles()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.CopyFilesToDirectory(new []{$"{testDirectory}file_{0}.zip", $"{testDirectory}file_{1}.zip"}, "/manga/output/");
|
|
Assert.Equal(2, ds.GetFiles("/manga/output/").Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void CopyFilesToDirectory_ShouldMoveAllFiles_InclFilesInNestedFolders()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
fileSystem.AddFile($"{testDirectory}nested/file_11.zip", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.CopyFilesToDirectory(new []{$"{testDirectory}file_{0}.zip", $"{testDirectory}file_{1}.zip", $"{testDirectory}nested/file_11.zip"}, "/manga/output/");
|
|
Assert.Equal(3, ds.GetFiles("/manga/output/").Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void CopyFilesToDirectory_ShouldMoveAllFiles_WithPrepend()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.CopyFilesToDirectory(new []{$"{testDirectory}file_{0}.zip", $"{testDirectory}file_{1}.zip", $"{testDirectory}nested/file_11.zip"},
|
|
"/manga/output/", "mangarocks_");
|
|
Assert.Equal(2, ds.GetFiles("/manga/output/").Count());
|
|
Assert.All(ds.GetFiles("/manga/output/"), filepath => ds.FileSystem.Path.GetFileName(filepath).StartsWith("mangarocks_"));
|
|
}
|
|
|
|
[Fact]
|
|
public void CopyFilesToDirectory_ShouldMoveOnlyFilesThatExist()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
fileSystem.AddFile($"{testDirectory}file_{i}.zip", new MockFileData(""));
|
|
}
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.CopyFilesToDirectory(new []{$"{testDirectory}file_{0}.zip", $"{testDirectory}file_{1}.zip", $"{testDirectory}nested/file_11.zip"},
|
|
"/manga/output/");
|
|
Assert.Equal(2, ds.GetFiles("/manga/output/").Count());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ListDirectory
|
|
[Fact]
|
|
public void ListDirectory_EmptyForNonExistent()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}file_0.zip", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
Assert.Empty(ds.ListDirectory("/comics/"));
|
|
}
|
|
|
|
[Fact]
|
|
public void ListDirectory_ListsAllDirectories()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddDirectory($"{testDirectory}dir1");
|
|
fileSystem.AddDirectory($"{testDirectory}dir2");
|
|
fileSystem.AddDirectory($"{testDirectory}dir3");
|
|
fileSystem.AddFile($"{testDirectory}file_0.zip", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
Assert.Equal(3, ds.ListDirectory(testDirectory).Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void ListDirectory_ListsOnlyNonSystemAndHiddenOnly()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddDirectory($"{testDirectory}dir1");
|
|
var di = fileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}dir1");
|
|
di.Attributes |= FileAttributes.System;
|
|
fileSystem.AddDirectory($"{testDirectory}dir2");
|
|
di = fileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}dir2");
|
|
di.Attributes |= FileAttributes.Hidden;
|
|
fileSystem.AddDirectory($"{testDirectory}dir3");
|
|
fileSystem.AddFile($"{testDirectory}file_0.zip", new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
Assert.Equal(1, ds.ListDirectory(testDirectory).Count());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ReadFileAsync
|
|
|
|
[Fact]
|
|
public async Task ReadFileAsync_ShouldGetBytes()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}file_1.zip", new MockFileData("Hello"));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var bytes = await ds.ReadFileAsync($"{testDirectory}file_1.zip");
|
|
Assert.Equal(Encoding.UTF8.GetBytes("Hello"), bytes);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFileAsync_ShouldReadNothingFromNonExistent()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddFile($"{testDirectory}file_1.zip", new MockFileData("Hello"));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var bytes = await ds.ReadFileAsync($"{testDirectory}file_32123.zip");
|
|
Assert.Empty(bytes);
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region FindHighestDirectoriesFromFiles
|
|
|
|
[Theory]
|
|
[InlineData(new [] {"C:/Manga/"}, new [] {"C:/Manga/Love Hina/Vol. 01.cbz"}, "C:/Manga/Love Hina")]
|
|
[InlineData(new [] {"C:/Manga/Dir 1/", "c://Manga/Dir 2/"}, new [] {"C:/Manga/Dir 1/Love Hina/Vol. 01.cbz"}, "C:/Manga/Dir 1/Love Hina")]
|
|
[InlineData(new [] {"C:/Manga/Dir 1/", "c://Manga/"}, new [] {"D:/Manga/Love Hina/Vol. 01.cbz", "D:/Manga/Vol. 01.cbz"}, "")]
|
|
public void FindHighestDirectoriesFromFilesTest(string[] rootDirectories, string[] files, string expectedDirectory)
|
|
{
|
|
var fileSystem = new MockFileSystem();
|
|
foreach (var directory in rootDirectories)
|
|
{
|
|
fileSystem.AddDirectory(directory);
|
|
}
|
|
foreach (var f in files)
|
|
{
|
|
fileSystem.AddFile(f, new MockFileData(""));
|
|
}
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
|
|
var actual = ds.FindHighestDirectoriesFromFiles(rootDirectories, files);
|
|
var expected = new Dictionary<string, string>();
|
|
if (!string.IsNullOrEmpty(expectedDirectory))
|
|
{
|
|
expected = new Dictionary<string, string> {{expectedDirectory, ""}};
|
|
}
|
|
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetFoldersTillRoot
|
|
|
|
[Theory]
|
|
[InlineData("C:/Manga/", "C:/Manga/Love Hina/Specials/Omake/", "Omake,Specials,Love Hina")]
|
|
[InlineData("C:/Manga/", "C:/Manga/Love Hina/Specials/Omake", "Omake,Specials,Love Hina")]
|
|
[InlineData("C:/Manga", "C:/Manga/Love Hina/Specials/Omake/", "Omake,Specials,Love Hina")]
|
|
[InlineData("C:/Manga", @"C:\Manga\Love Hina\Specials\Omake\", "Omake,Specials,Love Hina")]
|
|
[InlineData(@"/manga/", @"/manga/Love Hina/Specials/Omake/", "Omake,Specials,Love Hina")]
|
|
[InlineData(@"/manga/", @"/manga/", "")]
|
|
[InlineData(@"E:\test", @"E:\test\Sweet X Trouble\Sweet X Trouble - Chapter 001.cbz", "Sweet X Trouble")]
|
|
[InlineData(@"C:\/mount/gdrive/Library/Test Library/Comics/", @"C:\/mount/gdrive/Library/Test Library/Comics\godzilla rivals vs hedorah\vol 1\", "vol 1,godzilla rivals vs hedorah")]
|
|
[InlineData(@"/manga/", @"/manga/Btooom!/Vol.1 Chapter 2/1.cbz", "Vol.1 Chapter 2,Btooom!")]
|
|
[InlineData(@"C:/", @"C://Btooom!/Vol.1 Chapter 2/1.cbz", "Vol.1 Chapter 2,Btooom!")]
|
|
[InlineData(@"C:\\", @"C://Btooom!/Vol.1 Chapter 2/1.cbz", "Vol.1 Chapter 2,Btooom!")]
|
|
[InlineData(@"C://mount/gdrive/Library/Test Library/Comics", @"C://mount/gdrive/Library/Test Library/Comics/Dragon Age/Test", "Test,Dragon Age")]
|
|
[InlineData(@"M:\", @"M:\Toukyou Akazukin\Vol. 01 Ch. 005.cbz", @"Toukyou Akazukin")]
|
|
public void GetFoldersTillRoot_Test(string rootPath, string fullpath, string expectedArray)
|
|
{
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddDirectory(rootPath);
|
|
fileSystem.AddFile(fullpath, new MockFileData(""));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
|
|
var expected = expectedArray.Split(",");
|
|
if (expectedArray.Equals(string.Empty))
|
|
{
|
|
expected = Array.Empty<string>();
|
|
}
|
|
Assert.Equal(expected, ds.GetFoldersTillRoot(rootPath, fullpath));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RemoveNonImages
|
|
|
|
[Fact]
|
|
public void RemoveNonImages()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddDirectory(testDirectory);
|
|
fileSystem.AddFile($"{testDirectory}file/data-0.txt", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}data-1.jpg", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}data-2.png", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}data-3.webp", new MockFileData("abc"));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.RemoveNonImages($"{testDirectory}");
|
|
Assert.False(fileSystem.FileExists($"{testDirectory}file/data-0.txt"));
|
|
Assert.Equal(3, ds.GetFiles($"{testDirectory}", searchOption:SearchOption.AllDirectories).Count());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Flatten
|
|
|
|
[Fact]
|
|
public void Flatten_ShouldDoNothing()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddDirectory(testDirectory);
|
|
fileSystem.AddFile($"{testDirectory}data-1.jpg", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}data-2.png", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}data-3.webp", new MockFileData("abc"));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.Flatten($"{testDirectory}");
|
|
Assert.True(fileSystem.FileExists($"{testDirectory}data-1.jpg"));
|
|
Assert.True(fileSystem.FileExists($"{testDirectory}data-2.png"));
|
|
Assert.True(fileSystem.FileExists($"{testDirectory}data-3.webp"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Flatten_ShouldFlatten()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
fileSystem.AddDirectory(testDirectory);
|
|
fileSystem.AddFile($"{testDirectory}data-1.jpg", new MockFileData("abc"));
|
|
fileSystem.AddFile($"{testDirectory}subdir/data-3.webp", new MockFileData("abc"));
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
ds.Flatten($"{testDirectory}");
|
|
Assert.Equal(2, ds.GetFiles(testDirectory).Count());
|
|
Assert.False(fileSystem.FileExists($"{testDirectory}subdir/data-3.webp"));
|
|
Assert.True(fileSystem.Directory.Exists($"{testDirectory}subdir/"));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CheckWriteAccess
|
|
|
|
[Fact]
|
|
public async Task CheckWriteAccess_ShouldHaveAccess()
|
|
{
|
|
const string testDirectory = "/manga/";
|
|
var fileSystem = new MockFileSystem();
|
|
|
|
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
|
|
var hasAccess = await ds.CheckWriteAccess(ds.FileSystem.Path.Join(testDirectory, "bookmarks"));
|
|
Assert.True(hasAccess);
|
|
|
|
Assert.False(ds.FileSystem.Directory.Exists(ds.FileSystem.Path.Join(testDirectory, "bookmarks")));
|
|
Assert.False(ds.FileSystem.File.Exists(ds.FileSystem.Path.Join(testDirectory, "bookmarks", "test.txt")));
|
|
}
|
|
|
|
|
|
#endregion
|
|
}
|
|
}
|