diff --git a/BasicNodes/BasicNodes.csproj b/BasicNodes/BasicNodes.csproj index 1ee7afc4..8b948ea9 100644 --- a/BasicNodes/BasicNodes.csproj +++ b/BasicNodes/BasicNodes.csproj @@ -24,6 +24,7 @@ This plugin is required for FileFlows to work. + diff --git a/BasicNodes/File/FileSizeCompare.cs b/BasicNodes/File/FileSizeCompare.cs index 7b046e32..c333c33b 100644 --- a/BasicNodes/File/FileSizeCompare.cs +++ b/BasicNodes/File/FileSizeCompare.cs @@ -27,7 +27,7 @@ public class FileSizeCompare : Node if (result.IsFailed) { // try get from variables - if (args.Variables.ContainsKey("file.Orig.Size") && args.Variables["file.Orig.Size"] is long tSize && tSize > 0) + if (args.Variables.TryGetValue("file.Orig.Size", out object? value) && value is long tSize && tSize > 0) { origSize = tSize; } diff --git a/BasicNodes/File/HasHardLinks.cs b/BasicNodes/File/HasHardLinks.cs index 77a6e270..9bc154dc 100644 --- a/BasicNodes/File/HasHardLinks.cs +++ b/BasicNodes/File/HasHardLinks.cs @@ -134,22 +134,22 @@ public class HasHardLinks: Node if(string.IsNullOrWhiteSpace(error) == false) args.Logger?.ILog("Error Output: " + error); - if (int.TryParse(output.Trim(), out var linkCount)) + if (int.TryParse(output.Trim(), out var linkCount) == false) { - if (linkCount > 0) - { - args.Logger?.ILog($"The file has {linkCount} hard links."); - if (linkCount >= count) - return true; - } - args.Logger?.ILog("The file does not have the required number of hard links."); + + args.Logger?.ILog("Failed to retrieve link count."); return false; } + + --linkCount; - if(string.IsNullOrWhiteSpace(error)) - args.Logger?.ELog(error); - - args.Logger?.ILog("Failed to retrieve link count."); + if (linkCount > 0) + { + args.Logger?.ILog($"The file has {linkCount} hard links."); + if (linkCount >= count) + return true; + } + args.Logger?.ILog("The file does not have the required number of hard links."); return false; } catch (Exception ex) @@ -184,26 +184,28 @@ public class HasHardLinks: Node string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); process.WaitForExit(); - - if(string.IsNullOrWhiteSpace(output) == false) + + if (string.IsNullOrWhiteSpace(output) == false) args.Logger?.ILog("Standard Output: " + output); - if(string.IsNullOrWhiteSpace(error) == false) + if (string.IsNullOrWhiteSpace(error) == false) args.Logger?.ILog("Error Output: " + error); - if (int.TryParse(output.Trim(), out var linkCount)) + if (int.TryParse(output.Trim(), out var linkCount) == false) { - if (linkCount > 0) - { - args.Logger?.ILog($"The file has {linkCount} hard links."); - if (linkCount >= count) - return true; - } - args.Logger?.ILog("The file does not have hard links."); - return false; + args.Logger?.ILog("The file does not have the required number of hard links."); + return false; } + + linkCount -= 1; // every file has at least one hard link we want the additional hard links - args.Logger?.ILog("The file does not have the required number of hard links."); - return false; + if (linkCount > 0) + { + args.Logger?.ILog($"The file has {linkCount} hard links."); + if (linkCount >= count) + return true; + } + args.Logger?.ILog("The file does not have hard links."); + return false; } catch (Exception ex) { diff --git a/BasicNodes/Tests/CopyTests.cs b/BasicNodes/Tests/CopyTests.cs deleted file mode 100644 index 1b361806..00000000 --- a/BasicNodes/Tests/CopyTests.cs +++ /dev/null @@ -1,78 +0,0 @@ -using FileFlows.Plugin; - -#if(DEBUG) - -namespace BasicNodes.Tests; - -using FileFlows.BasicNodes.File; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System.Text.RegularExpressions; - -[TestClass] -public class CopyTests -{ - List> Mappings = new List> - { - new KeyValuePair("/usr/local/bin/ffmpeg", @"C:\Users\username\AppData\Roaming\FileFlows\Tools\ffmpeg.exe"), - new KeyValuePair("/mnt/tempNAS/media/dvd/sorted", @"\\192.168.1.22\Media\dvd\sorted"), - new KeyValuePair("/mnt/tempNAS/media/dvd/output", @"\\192.168.1.22\Media\dvd\output"), - }; - char DirectorySeperatorChar = System.IO.Path.DirectorySeparatorChar; - - [TestMethod] - public void CopyTests_Dir_Mapping() - { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"c:\test\testfile.mkv", logger, false, string.Empty, null); - args.PathMapper = s => Map(s); - - CopyFile node = new (); - node.CopyFolder = true; - node.DestinationPath = "/mnt/tempNAS/media/dvd/output"; - node.DestinationFile = "{file.Orig.FileName}p.DVD.x264.slow.CRF16{ext}"; - var result = node.Execute(args); - Assert.AreEqual(2, result); - } - - [TestMethod] - public void CopyTests_Dir_DateReplacements() - { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"D:\videos\testfiles\bigbuckbunny_480p_30s.mp4", logger, false, string.Empty, null); - args.PathMapper = s => Map(s); - - CopyFile node = new(); - node.CopyFolder = true; - node.DestinationPath = @"D:\videos\converted"; - node.DestinationFile = "{file.Orig.FileName}-{file.Create.Month:00}-{file.Create.Year}{ext!}"; - var result = node.Execute(args); - Assert.AreEqual(1, result); - } - - string Map(string path) - { - if (string.IsNullOrEmpty(path)) - return string.Empty; - if (Mappings != null && Mappings.Count > 0) - { - // convert all \ to / for now - path = path.Replace("\\", "/"); - foreach (var mapping in Mappings) - { - if (string.IsNullOrEmpty(mapping.Value) || string.IsNullOrEmpty(mapping.Key)) - continue; - string pattern = Regex.Escape(mapping.Key.Replace("\\", "/")); - string replacement = mapping.Value.Replace("\\", "/"); - path = Regex.Replace(path, "^" + pattern, replacement, RegexOptions.IgnoreCase); - } - // now convert / to path charcter - if (DirectorySeperatorChar != '/') - path = path.Replace('/', DirectorySeperatorChar); - if (path.StartsWith("//")) // special case for SMB paths - path = path.Replace('/', '\\'); - } - return path; - } -} - -#endif \ No newline at end of file diff --git a/BasicNodes/Tests/ExecutorTests.cs b/BasicNodes/Tests/ExecutorTests.cs index 4c23426a..65fe28ac 100644 --- a/BasicNodes/Tests/ExecutorTests.cs +++ b/BasicNodes/Tests/ExecutorTests.cs @@ -1,35 +1,45 @@ #if(DEBUG) -namespace BasicNodes.Tests +using FileFlows.BasicNodes.File; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Text.RegularExpressions; +using FileFlows.Plugin; +using Moq; + +namespace BasicNodes.Tests; + +[TestClass] +public class ExecutorTests : TestBase { - using FileFlows.BasicNodes.File; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System.Text.RegularExpressions; + private Mock mockProcessHelper = new(); - [TestClass] - public class ExecutorTests + protected override void TestStarting() { - [TestMethod] - public void Executor_OutputVariable() + mockProcessHelper.Setup(x => x.ExecuteShellCommand(It.IsAny())).Returns(Task.FromResult(new ProcessResult() { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"c:\test\testfile.mkv", logger, false, string.Empty, null); + ExitCode = 0, + Completed = true, + Output = "this is the output", + StandardOutput = "this is the standard output", + StandardError = "this is the standard error" + })); + } - Executor node = new Executor(); - string file = @"D:\Videos\dummy.mkv"; - node.FileName = @"C:\utils\ffmpeg\ffmpeg.exe"; - node.Arguments = "-i \"" + file + "\""; - node.OutputVariable = "ExecOutput"; - var result = node.Execute(args); - Assert.IsTrue(args.Variables.ContainsKey("ExecOutput")); - string output = args.Variables["ExecOutput"] as string; - Assert.IsNotNull(output); - } - [TestMethod] - public void Executor_VariablePattern_Tests() - { - Assert.IsFalse(Regex.IsMatch(string.Empty, Executor.VariablePattern)); - } + [TestMethod] + public void Executor_OutputVariable() + { + var args = new NodeParameters(@"c:\test\testfile.mkv", Logger, false, string.Empty, MockFileService.Object); + args.Process = mockProcessHelper.Object; + + Executor node = new Executor(); + string file = @"D:\Videos\dummy.mkv"; + node.FileName = @"C:\utils\ffmpeg\ffmpeg.exe"; + node.Arguments = "-i \"" + file + "\""; + node.OutputVariable = "ExecOutput"; + var result = node.Execute(args); + Assert.IsTrue(args.Variables.ContainsKey("ExecOutput")); + string output = args.Variables["ExecOutput"] as string; + Assert.IsNotNull(output); } } diff --git a/BasicNodes/Tests/FileSizeCompareTests.cs b/BasicNodes/Tests/FileSizeCompareTests.cs index 8ec357c2..adbe9dac 100644 --- a/BasicNodes/Tests/FileSizeCompareTests.cs +++ b/BasicNodes/Tests/FileSizeCompareTests.cs @@ -1,116 +1,114 @@ #if(DEBUG) using System.IO; +using FileFlows.BasicNodes.File; +using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace BasicNodes.Tests +namespace BasicNodes.Tests; + +[TestClass] +public class FileSizeCompareTests : TestBase { - using FileFlows.BasicNodes.File; - using Microsoft.VisualStudio.TestTools.UnitTesting; - - [TestClass] - public class FileSizeCompareTests + private string CreateFile(int size) { - private string CreateFile(int size) - { - string tempFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - System.IO.File.WriteAllText(tempFile, new string('a', size)); - return tempFile; + string tempFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".tmp"); + System.IO.File.WriteAllText(tempFile, new string('a', size * 1000)); + return tempFile; + } + + [TestMethod] + public void FileSize_Shrunk() + { + string tempFile = CreateFile(2); + var args = new FileFlows.Plugin.NodeParameters(tempFile, Logger, false, string.Empty, new LocalFileService()); + args.InitFile(tempFile); - } - [TestMethod] - public void FileSize_Shrunk() - { - string tempFile = CreateFile(2); - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(tempFile, logger, false, string.Empty, null); + string wfFile = CreateFile(1); + args.SetWorkingFile(wfFile); - string wfFile = CreateFile(1); - args.SetWorkingFile(wfFile); + FileSizeCompare node = new(); + int result = node.Execute(args); + Assert.AreEqual(1, result); + } - FileSizeCompare node = new(); - int result = node.Execute(args); - Assert.AreEqual(1, result); - } + [TestMethod] + public void FileSize_Grew() + { + string tempFile = CreateFile(2); + var args = new FileFlows.Plugin.NodeParameters(tempFile, Logger, false, string.Empty, new LocalFileService()); + args.InitFile(tempFile); - [TestMethod] - public void FileSize_Grew() - { - string tempFile = CreateFile(2); - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(tempFile, logger, false, string.Empty, null); + string wfFile = CreateFile(20); + args.SetWorkingFile(wfFile); - string wfFile = CreateFile(20); - args.SetWorkingFile(wfFile); + FileSizeCompare node = new (); + int result = node.Execute(args); + Assert.AreEqual(3, result); + } - FileSizeCompare node = new (); - int result = node.Execute(args); - Assert.AreEqual(3, result); - } + [TestMethod] + public void FileSize_SameSize() + { + string tempFile = CreateFile(2); + var args = new FileFlows.Plugin.NodeParameters(tempFile, Logger, false, string.Empty, new LocalFileService()); + args.InitFile(tempFile); - [TestMethod] - public void FileSize_SameSize() - { - string tempFile = CreateFile(2); - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(tempFile, logger, false, string.Empty, null); + string wfFile = CreateFile(2); + args.SetWorkingFile(wfFile); - string wfFile = CreateFile(2); - args.SetWorkingFile(wfFile); - - FileSizeCompare node = new(); - int result = node.Execute(args); - Assert.AreEqual(2, result); - } + FileSizeCompare node = new(); + int result = node.Execute(args); + Assert.AreEqual(2, result); + } - [TestMethod] - public void FileSize_Shrunk_OriginalDeleted() - { - string tempFile = CreateFile(2); - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(tempFile, logger, false, string.Empty, null); - Assert.IsTrue(args.WorkingFileSize > 0); - System.IO.File.Delete(tempFile); + [TestMethod] + public void FileSize_Shrunk_OriginalDeleted() + { + string tempFile = CreateFile(2); + var args = new FileFlows.Plugin.NodeParameters(tempFile, Logger, false, string.Empty, new LocalFileService()); + args.InitFile(tempFile); + Assert.IsTrue(args.WorkingFileSize > 0); + System.IO.File.Delete(tempFile); - string wfFile = CreateFile(1); - args.SetWorkingFile(wfFile); + string wfFile = CreateFile(1); + args.SetWorkingFile(wfFile); - FileSizeCompare node = new(); - int result = node.Execute(args); - Assert.AreEqual(1, result); - } + FileSizeCompare node = new(); + int result = node.Execute(args); + Assert.AreEqual(1, result); + } - [TestMethod] - public void FileSize_Grew_OriginalDeleted() - { - string tempFile = CreateFile(2); - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(tempFile, logger, false, string.Empty, null); - System.IO.File.Delete(tempFile); + [TestMethod] + public void FileSize_Grew_OriginalDeleted() + { + string tempFile = CreateFile(2); + var args = new FileFlows.Plugin.NodeParameters(tempFile, Logger, false, string.Empty, new LocalFileService()); + args.InitFile(tempFile); + System.IO.File.Delete(tempFile); - string wfFile = CreateFile(20); - args.SetWorkingFile(wfFile); + string wfFile = CreateFile(20); + args.SetWorkingFile(wfFile); - FileSizeCompare node = new(); - int result = node.Execute(args); - Assert.AreEqual(3, result); - } + FileSizeCompare node = new(); + int result = node.Execute(args); + Assert.AreEqual(3, result); + } - [TestMethod] - public void FileSize_SameSize_OriginalDeleted() - { - string tempFile = CreateFile(2); - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(tempFile, logger, false, string.Empty, null); - System.IO.File.Delete(tempFile); + [TestMethod] + public void FileSize_SameSize_OriginalDeleted() + { + string tempFile = CreateFile(2); + var args = new FileFlows.Plugin.NodeParameters(tempFile, Logger, false, string.Empty, new LocalFileService()); + args.InitFile(tempFile); + System.IO.File.Delete(tempFile); - string wfFile = CreateFile(2); - args.SetWorkingFile(wfFile); + string wfFile = CreateFile(2); + args.SetWorkingFile(wfFile); - FileSizeCompare node = new(); - int result = node.Execute(args); - Assert.AreEqual(2, result); - } + FileSizeCompare node = new(); + int result = node.Execute(args); + Assert.AreEqual(2, result); } } diff --git a/BasicNodes/Tests/HasHardLinksTest.cs b/BasicNodes/Tests/HasHardLinksTest.cs index 289d8a51..f885c790 100644 --- a/BasicNodes/Tests/HasHardLinksTest.cs +++ b/BasicNodes/Tests/HasHardLinksTest.cs @@ -1,18 +1,87 @@ #if(DEBUG) -namespace BasicNodes.Tests; +using System.Diagnostics; +using System.IO; using FileFlows.BasicNodes.File; using Microsoft.VisualStudio.TestTools.UnitTesting; +namespace BasicNodes.Tests; + [TestClass] -public class HasHardLinksTest +public class HasHardLinksTest : TestBase { + private string? testFile; + + + protected override void TestCleanUp() + { + // Clean up the original file and any hard links created + if (string.IsNullOrEmpty(testFile) == false && System.IO.File.Exists(testFile)) + { + try + { + // Delete the original file + System.IO.File.Delete(testFile); + + // Delete the hard links + for (int i = 1; ; i++) + { + var linkName = $"{testFile}_link{i}"; + if (System.IO.File.Exists(linkName)) + System.IO.File.Delete(linkName); + else + break; // Stop if the link doesn't exist + } + } + catch (Exception ex) + { + // Log or handle the cleanup exception if necessary + Logger.ILog($"Failed to clean up files: {ex.Message}"); + } + } + } + public static void CreateHardLinkFile(string filename, int hardlinks = 1) + { + // Ensure the file exists + System.IO.File.WriteAllText(filename, "Test content"); + + // Create the specified number of hard links + for (int i = 1; i <= hardlinks; i++) + { + string linkName = $"{filename}_link{i}"; + + // Use the `ln` command to create a hard link + Process process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "ln", + Arguments = $"{filename} {linkName}", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + process.Start(); + process.WaitForExit(); + + if (process.ExitCode != 0) + { + string error = process.StandardError.ReadToEnd(); + throw new InvalidOperationException($"Failed to create hard link: {error}"); + } + } + } + [TestMethod] public void HasHardLink() { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"/home/john/temp/test.file", logger, false, string.Empty, new LocalFileService());; + testFile = Path.GetTempFileName(); + CreateHardLinkFile(testFile, 2); + + var args = new FileFlows.Plugin.NodeParameters(testFile, Logger, false, string.Empty, MockFileService.Object); HasHardLinks element = new (); @@ -23,8 +92,8 @@ public class HasHardLinksTest [TestMethod] public void NoHardLinks() { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"/home/john/temp/other.test", logger, false, string.Empty, new LocalFileService());; + testFile = Path.GetTempFileName(); + var args = new FileFlows.Plugin.NodeParameters(testFile, Logger, false, string.Empty, MockFileService.Object); HasHardLinks element = new (); diff --git a/BasicNodes/Tests/MoveTests.cs b/BasicNodes/Tests/MoveTests.cs index 8a582f5a..9fa9c5e3 100644 --- a/BasicNodes/Tests/MoveTests.cs +++ b/BasicNodes/Tests/MoveTests.cs @@ -1,33 +1,31 @@  #if(DEBUG) -namespace BasicNodes.Tests; +using System.IO; using FileFlows.Plugin; using FileFlows.BasicNodes.File; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System.Text.RegularExpressions; +namespace BasicNodes.Tests; [TestClass] -public class MoveTests +public class MoveTests : TestBase { - [TestMethod] public void MoveTests_Variable_Filename() { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", logger, false, string.Empty, null); + var args = new NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", Logger, false, string.Empty, new LocalFileService()); string dest = MoveFile.GetDestinationPath(args, @"D:\test", "{file.Name}"); Assert.AreEqual(@"D:/test/tv4a-starwarsrebels.s01e15-1080p.mkv", dest); } + [TestMethod] public void MoveTests_Variable_FilenameExt() { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", logger, false, string.Empty, null); + var args = new NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", Logger, false, string.Empty, new LocalFileService()); // ensure we dont double up the extension after FF-154 string dest = MoveFile.GetDestinationPath(args, @"D:\test", "{file.Name}{file.Extension}"); @@ -38,20 +36,22 @@ public class MoveTests [TestMethod] public void MoveTests_Variable_FilenameNoExtension() { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", logger, false, string.Empty, null); + var tempFileNoExtension = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + var tempFile = tempFileNoExtension + ".tmp"; + System.IO.File.WriteAllText(tempFile, "this is a temp file"); + var args = new NodeParameters(tempFile, Logger, false, string.Empty, new LocalFileService()); + args.InitFile(tempFile); // ensure we dont double up the extension after FF-154 - string dest = MoveFile.GetDestinationPath(args, @"D:\test", "{file.NameNoExtension}"); + string dest = MoveFile.GetDestinationPath(args, Path.GetTempPath(), "{file.NameNoExtension}"); - Assert.AreEqual(@"D:/test/tv4a-starwarsrebels.mkv", dest); + Assert.AreEqual(tempFileNoExtension, dest); } [TestMethod] public void MoveTests_Variable_Ext() { - var logger = new TestLogger(); - var args = new NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", logger, false, string.Empty, null); + var args = new NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", Logger, false, string.Empty, new LocalFileService()); // ensure we dont double up the extension after FF-154 string dest = MoveFile.GetDestinationPath(args, @"D:\test", "{file.Name}{ext}"); @@ -62,18 +62,17 @@ public class MoveTests [TestMethod] public void MoveTests_Variable_Original_Filename() { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", logger, false, string.Empty, null); + var args = new NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", Logger, false, string.Empty, new LocalFileService()); string dest = MoveFile.GetDestinationPath(args, @"D:\test", "{file.Orig.FileName}"); Assert.AreEqual(@"D:/test/tv4a-starwarsrebels.s01e15-1080p.mkv", dest); } + [TestMethod] public void MoveTests_Variable_Original_FilenameExt() { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", logger, false, string.Empty, null); + var args = new NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", Logger, false, string.Empty, new LocalFileService()); // ensure we dont double up the extension after FF-154 string dest = MoveFile.GetDestinationPath(args, @"D:\test", "{file.Orig.FileName}{file.Orig.Extension}"); @@ -83,8 +82,8 @@ public class MoveTests [TestMethod] public void MoveTests_Variable_Original_NoExtension() { - var logger = new TestLogger(); - var args = new FileFlows.Plugin.NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", logger, false, string.Empty, null); + + var args = new NodeParameters(@"/home/user/test/tv4a-starwarsrebels.s01e15-1080p.mkv", Logger, false, string.Empty, new LocalFileService()); // ensure we dont double up the extension after FF-154 string dest = MoveFile.GetDestinationPath(args, @"D:\test", "{file.Orig.FileNameNoExtension}"); @@ -95,8 +94,8 @@ public class MoveTests [TestMethod] public void MoveTests_MoveFolder() { - var logger = new TestLogger(); - var args = new NodeParameters(@"\\tower\downloads\downloaded\tv\The.Walking.Dead.Dead.City.S01E04\some-file.mkv", logger, false, string.Empty, null); + + var args = new NodeParameters(@"\\tower\downloads\downloaded\tv\The.Walking.Dead.Dead.City.S01E04\some-file.mkv", Logger, false, string.Empty, new LocalFileService()); args.RelativeFile = @"The.Walking.Dead.Dead.City.S01E04\some-file.mkv"; string dest = MoveFile.GetDestinationPath(args, @"\\tower\downloads\converted\tv", null, moveFolder:true); @@ -111,14 +110,12 @@ public class MoveTests [TestMethod] public void MoveTests_AdditionalFiles() { - var logger = new TestLogger(); - var args = new NodeParameters(@"/home/john/Videos/move-me/dir/basic.mkv", logger, false, string.Empty, null); + var args = new NodeParameters(@"/home/john/Videos/move-me/dir/basic.mkv", Logger, false, string.Empty, new LocalFileService()); var ele = new MoveFile(); ele.AdditionalFiles = new[] { "*.srt" }; ele.DestinationPath = "/home/john/Videos/converted"; var result = ele.Execute(args); - var log = logger.ToString(); Assert.AreEqual(1, result); } } diff --git a/BasicNodes/Tests/WriteTextTests.cs b/BasicNodes/Tests/WriteTextTests.cs index 48c97465..197868a6 100644 --- a/BasicNodes/Tests/WriteTextTests.cs +++ b/BasicNodes/Tests/WriteTextTests.cs @@ -12,7 +12,7 @@ public class WriteTextTests : TestBase [TestMethod] public void WorkingFile_Csv() { - var args = new FileFlows.Plugin.NodeParameters(@"/test/file.mkv", new TestLogger(), false, string.Empty, new LocalFileService()); + var args = new FileFlows.Plugin.NodeParameters(@"/test/file.mkv", new TestLogger(), false, string.Empty, MockFileService.Object); var output = WriteText.GetText(args, "", "file.csv"); Assert.AreEqual("\"/test/file.mkv\"", output); @@ -21,7 +21,7 @@ public class WriteTextTests : TestBase [TestMethod] public void WorkingFile_Text() { - var args = new FileFlows.Plugin.NodeParameters(@"/test/file.mkv", new TestLogger(), false, string.Empty, new LocalFileService()); + var args = new FileFlows.Plugin.NodeParameters(@"/test/file.mkv", new TestLogger(), false, string.Empty, MockFileService.Object); var output = WriteText.GetText(args, "", "file.txt"); Assert.AreEqual("/test/file.mkv", output); @@ -30,7 +30,7 @@ public class WriteTextTests : TestBase [TestMethod] public void CsvArgs() { - var args = new FileFlows.Plugin.NodeParameters(@"/test/file.mkv", new TestLogger(), false, string.Empty, new LocalFileService()); + var args = new FileFlows.Plugin.NodeParameters(@"/test/file.mkv", new TestLogger(), false, string.Empty, MockFileService.Object); args.Variables["file.Name"] = "file.mkv"; args.Variables["ext"] = "mkv"; @@ -41,7 +41,7 @@ public class WriteTextTests : TestBase [TestMethod] public void CsvArg() { - var args = new FileFlows.Plugin.NodeParameters(@"/test/file.mkv", new TestLogger(), false, string.Empty, new LocalFileService()); + var args = new FileFlows.Plugin.NodeParameters(@"/test/file.mkv", new TestLogger(), false, string.Empty, MockFileService.Object); args.Variables["file.Name"] = "file.mkv"; var output = WriteText.GetText(args, "{file.Name}", "file.csv"); diff --git a/BasicNodes/Tests/_TestBase.cs b/BasicNodes/Tests/_TestBase.cs index 2f749502..7b5edc10 100644 --- a/BasicNodes/Tests/_TestBase.cs +++ b/BasicNodes/Tests/_TestBase.cs @@ -4,6 +4,9 @@ using System.Runtime.InteropServices; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.IO; using FileFlows.BasicNodes; +using FileFlows.Plugin.Helpers; +using FileFlows.Plugin.Services; +using Moq; namespace BasicNodes.Tests; @@ -20,6 +23,8 @@ public abstract class TestBase internal TestLogger Logger = new(); + protected Mock MockFileService = new(); + /// /// Gets or sets the test context /// @@ -38,6 +43,8 @@ public abstract class TestBase [TestInitialize] public void TestInitialize() { + FileHelper.DontChangeOwner = true; + FileHelper.DontSetPermissions = true; Logger.Writer = (msg) => TestContext.WriteLine(msg); this.TestPath = this.TestPath?.EmptyAsNull() ?? (IsLinux ? "~/src/ff-files/test-files/videos" : @"d:\videos\testfiles"); @@ -48,11 +55,14 @@ public abstract class TestBase if (Directory.Exists(this.TempPath) == false) Directory.CreateDirectory(this.TempPath); + + TestStarting(); } [TestCleanup] public void CleanUp() { + TestCleanUp(); TestContext.WriteLine(Logger.ToString()); } @@ -60,6 +70,10 @@ public abstract class TestBase { } + protected virtual void TestCleanUp() + { + + } } diff --git a/BasicNodes/Tools/Executor.cs b/BasicNodes/Tools/Executor.cs index dc9c5b14..58ca69d5 100644 --- a/BasicNodes/Tools/Executor.cs +++ b/BasicNodes/Tools/Executor.cs @@ -1,102 +1,108 @@ -namespace FileFlows.BasicNodes.File +using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; +using FileFlows.Plugin; +using FileFlows.Plugin.Attributes; + +namespace FileFlows.BasicNodes.File; + +/// +/// Executes a command +/// +public class Executor : Node { - using System.ComponentModel; - using System.ComponentModel.DataAnnotations; - using System.Diagnostics; - using System.Text; - using System.Text.RegularExpressions; - using FileFlows.Plugin; - using FileFlows.Plugin.Attributes; + /// + public override int Inputs => 1; + /// + public override int Outputs => 2; + /// + public override FlowElementType Type => FlowElementType.Process; + /// + public override string Icon => "fas fa-terminal"; + /// + public override string HelpUrl => "https://fileflows.com/docs/plugins/basic-nodes/executor"; - public class Executor : Node + internal const string VariablePattern = @"(^[\s]*$)|(^([a-zA-Z_]+)[a-zA-Z_0-9]*$)"; + + [Required] + [File(1)] + public string FileName { get; set; } + + [Required] + [TextVariable(2)] + public string Arguments { get; set; } + + [Folder(3)] + public string WorkingDirectory { get; set; } + + [Required] + [NumberInt(4)] + public int SuccessCode { get; set; } + + [NumberInt(5)] + public int Timeout { get; set; } + + [Text(6)] + [System.ComponentModel.DataAnnotations.RegularExpression(VariablePattern)] + public string OutputVariable { get; set; } + + [Text(7)] + [System.ComponentModel.DataAnnotations.RegularExpression(VariablePattern)] + public string OutputErrorVariable { get; set; } + + private NodeParameters args; + + /// + public override Task Cancel() { - public override int Inputs => 1; - public override int Outputs => 2; - public override FlowElementType Type => FlowElementType.Process; - public override string Icon => "fas fa-terminal"; - public override string HelpUrl => "https://fileflows.com/docs/plugins/basic-nodes/executor"; - - internal const string VariablePattern = @"(^[\s]*$)|(^([a-zA-Z_]+)[a-zA-Z_0-9]*$)"; - - [Required] - [File(1)] - public string FileName { get; set; } - - [Required] - [TextVariable(2)] - public string Arguments { get; set; } - - [Folder(3)] - public string WorkingDirectory { get; set; } - - [Required] - [NumberInt(4)] - public int SuccessCode { get; set; } - - [NumberInt(5)] - public int Timeout { get; set; } - - [Text(6)] - [System.ComponentModel.DataAnnotations.RegularExpression(VariablePattern)] - public string OutputVariable { get; set; } - - [Text(7)] - [System.ComponentModel.DataAnnotations.RegularExpression(VariablePattern)] - public string OutputErrorVariable { get; set; } - - private NodeParameters args; - - public override Task Cancel() - { - args?.Process?.Cancel(); - return Task.CompletedTask; - } - - public override int Execute(NodeParameters args) - { - this.args = args; - string pArgs = args.ReplaceVariables(Arguments ?? string.Empty); - string filename = args.ReplaceVariables(FileName ?? string.Empty, stripMissing: true); - string workingDirectory = args.ReplaceVariables(WorkingDirectory ?? string.Empty, stripMissing: true); - var task = args.Process.ExecuteShellCommand(new ExecuteArgs - { - Command = filename, - Arguments = pArgs, - Timeout = Timeout, - WorkingDirectory = workingDirectory - }); - - task.Wait(); - - if(task.Result.Completed == false) - { - args.Logger?.ELog("Process failed to complete"); - return -1; - } - bool success = task.Result.ExitCode == this.SuccessCode; - if(string.IsNullOrWhiteSpace(OutputVariable) == false && Regex.IsMatch(OutputVariable, VariablePattern)) - { - args.UpdateVariables(new Dictionary - { - { OutputVariable, task.Result.StandardOutput } - }); - } - if (string.IsNullOrWhiteSpace(OutputErrorVariable) == false && Regex.IsMatch(OutputErrorVariable ?? string.Empty, VariablePattern)) - { - args.UpdateVariables(new Dictionary - { - { OutputErrorVariable, task.Result.StandardError } - }); - } - if (success) - return 1; - else - { - args.Logger?.ILog("Unsuccesful exit code returned: " + task.Result.ExitCode); - return 2; - } - } - - + args?.Process?.Cancel(); + return Task.CompletedTask; } + + /// + public override int Execute(NodeParameters args) + { + this.args = args; + string pArgs = args.ReplaceVariables(Arguments ?? string.Empty); + string filename = args.ReplaceVariables(FileName ?? string.Empty, stripMissing: true); + string workingDirectory = args.ReplaceVariables(WorkingDirectory ?? string.Empty, stripMissing: true); + var task = args.Process.ExecuteShellCommand(new ExecuteArgs + { + Command = filename, + Arguments = pArgs, + Timeout = Timeout, + WorkingDirectory = workingDirectory + }); + + task.Wait(); + + if(task.Result.Completed == false) + { + args.Logger?.ELog("Process failed to complete"); + return -1; + } + bool success = task.Result.ExitCode == this.SuccessCode; + if(string.IsNullOrWhiteSpace(OutputVariable) == false && Regex.IsMatch(OutputVariable, VariablePattern)) + { + args.UpdateVariables(new Dictionary + { + { OutputVariable, task.Result.StandardOutput } + }); + } + if (string.IsNullOrWhiteSpace(OutputErrorVariable) == false && Regex.IsMatch(OutputErrorVariable ?? string.Empty, VariablePattern)) + { + args.UpdateVariables(new Dictionary + { + { OutputErrorVariable, task.Result.StandardError } + }); + } + if (success) + return 1; + else + { + args.Logger?.ILog("Unsuccesful exit code returned: " + task.Result.ExitCode); + return 2; + } + } + + } \ No newline at end of file diff --git a/FileFlows.Plugin.dll b/FileFlows.Plugin.dll index 5ade9806..b8f493e5 100644 Binary files a/FileFlows.Plugin.dll and b/FileFlows.Plugin.dll differ diff --git a/FileFlows.Plugin.pdb b/FileFlows.Plugin.pdb index 790006f1..372a6662 100644 Binary files a/FileFlows.Plugin.pdb and b/FileFlows.Plugin.pdb differ