diff --git a/Directory.Packages.props b/Directory.Packages.props
index 11e42b335..5105a783f 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -24,8 +24,8 @@
-
-
+
+
@@ -38,6 +38,6 @@
-
+
diff --git a/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessor.cs b/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessor.cs
index 8834e3ac5..9e9b3c113 100644
--- a/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessor.cs
+++ b/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessor.cs
@@ -1,6 +1,7 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Applications.DicomDirectoryProcessor
{
@@ -18,20 +19,22 @@ public static class DicomDirectoryProcessor
/// Arguments. There should be exactly one argument that specified the
/// path to the top level directory that is be searched.
///
- public static int Main(IEnumerable args)
+ ///
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
int ret = SmiCliInit
.ParseAndRun(
args,
typeof(DicomDirectoryProcessor),
- OnParse
+ OnParse,
+ fileSystem ?? new FileSystem()
);
return ret;
}
- private static int OnParse(GlobalOptions globals, DicomDirectoryProcessorCliOptions parsedOptions)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, DicomDirectoryProcessorCliOptions parsedOptions)
{
- var bootstrapper = new MicroserviceHostBootstrapper(() => new DicomDirectoryProcessorHost(globals, parsedOptions));
+ var bootstrapper = new MicroserviceHostBootstrapper(() => new DicomDirectoryProcessorHost(globals, parsedOptions, fileSystem));
int ret = bootstrapper.Main();
return ret;
}
diff --git a/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessorCliOptions.cs b/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessorCliOptions.cs
index 52a7487c5..f3a20d9b7 100644
--- a/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessorCliOptions.cs
+++ b/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessorCliOptions.cs
@@ -16,17 +16,6 @@ public class DicomDirectoryProcessorCliOptions : CliOptions
public string? DirectoryFormat { get; set; }
- public DirectoryInfo? ToProcessDir
- {
- get
- {
- return ToProcess == null
- ? null
- : new DirectoryInfo(ToProcess);
- }
- set => ToProcess = value?.FullName ?? throw new ArgumentNullException(nameof(value));
- }
-
[Usage]
public static IEnumerable Examples
{
diff --git a/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessorHost.cs b/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessorHost.cs
index 88d3feee1..fdc75dd4b 100644
--- a/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessorHost.cs
+++ b/src/SmiServices/Applications/DicomDirectoryProcessor/DicomDirectoryProcessorHost.cs
@@ -4,6 +4,7 @@
using System;
using System.Globalization;
using System.IO;
+using System.IO.Abstractions;
namespace SmiServices.Applications.DicomDirectoryProcessor
{
@@ -19,32 +20,35 @@ public class DicomDirectoryProcessorHost : MicroserviceHost
/// Constructor
///
/// Common microservices options. Must contain details for an message exchange labelled as "accessionDirectories"
+ ///
/// Configuration settings for the program
- public DicomDirectoryProcessorHost(GlobalOptions globals, DicomDirectoryProcessorCliOptions cliOptions)
- : base(globals)
+ public DicomDirectoryProcessorHost(GlobalOptions globals, DicomDirectoryProcessorCliOptions cliOptions, IFileSystem? fileSystem = null)
+ : base(globals, fileSystem ?? new FileSystem())
{
_cliOptions = cliOptions;
+ IDirectoryInfo toProcessDir = FileSystem.DirectoryInfo.New(cliOptions.ToProcess);
+
if (!cliOptions.DirectoryFormat!.ToLower().Equals("list"))
{
// TODO(rkm 2020-02-12) I think we want to check this regardless of the mode
// (bp 2020-02-13) By not doing this check on list means that the list of paths is not required to be in PACS and can be imported from anywhere
- if (!Directory.Exists(globals.FileSystemOptions!.FileSystemRoot))
- throw new ArgumentException("Cannot find the FileSystemRoot specified in the given MicroservicesOptions (" + globals.FileSystemOptions.FileSystemRoot + ")");
+ if (!FileSystem.Directory.Exists(globals.FileSystemOptions!.FileSystemRoot))
+ throw new ArgumentException($"Cannot find the FileSystemRoot specified in the given MicroservicesOptions ({globals.FileSystemOptions.FileSystemRoot})");
- if (!cliOptions.ToProcessDir!.Exists)
- throw new ArgumentException("Could not find directory " + cliOptions.ToProcessDir.FullName);
+ if (!toProcessDir.Exists)
+ throw new ArgumentException($"Could not find directory {toProcessDir.FullName}");
- if (!cliOptions.ToProcessDir.FullName.StartsWith(globals.FileSystemOptions.FileSystemRoot, true, CultureInfo.CurrentCulture))
- throw new ArgumentException("Directory parameter (" + cliOptions.ToProcessDir.FullName + ") must be below the FileSystemRoot (" + globals.FileSystemOptions.FileSystemRoot + ")");
+ if (!toProcessDir.FullName.StartsWith(globals.FileSystemOptions.FileSystemRoot, true, CultureInfo.CurrentCulture))
+ throw new ArgumentException($"Directory parameter ({toProcessDir.FullName}) must be below the FileSystemRoot ({globals.FileSystemOptions.FileSystemRoot})");
}
else
{
- if (!File.Exists(cliOptions.ToProcessDir!.FullName))
- throw new ArgumentException("Could not find accession directory list file (" + cliOptions.ToProcessDir.FullName + ")");
+ if (!FileSystem.File.Exists(toProcessDir.FullName))
+ throw new ArgumentException($"Could not find accession directory list file ({toProcessDir.FullName})");
- if (!Path.GetExtension(cliOptions.ToProcessDir.FullName).Equals(".csv"))
- throw new ArgumentException("When in 'list' mode, path to accession directory file of format .csv expected (" + cliOptions.ToProcessDir.FullName + ")");
+ if (!FileSystem.Path.GetExtension(toProcessDir.FullName).Equals(".csv"))
+ throw new ArgumentException($"When in 'list' mode, path to accession directory file of format .csv expected ({toProcessDir.FullName})");
}
switch (cliOptions.DirectoryFormat.ToLower())
@@ -84,9 +88,11 @@ public DicomDirectoryProcessorHost(GlobalOptions globals, DicomDirectoryProcesso
///
public override void Start()
{
+ IDirectoryInfo toProcessDir = FileSystem.DirectoryInfo.New(_cliOptions.ToProcess);
+
try
{
- _ddf.SearchForDicomDirectories(_cliOptions.ToProcessDir!.FullName);
+ _ddf.SearchForDicomDirectories(toProcessDir.FullName);
}
catch (Exception e)
{
diff --git a/src/SmiServices/Applications/DicomDirectoryProcessor/DirectoryFinders/DicomDirectoryFinder.cs b/src/SmiServices/Applications/DicomDirectoryProcessor/DirectoryFinders/DicomDirectoryFinder.cs
index b8b7b8e49..71a4ad2e7 100644
--- a/src/SmiServices/Applications/DicomDirectoryProcessor/DirectoryFinders/DicomDirectoryFinder.cs
+++ b/src/SmiServices/Applications/DicomDirectoryProcessor/DirectoryFinders/DicomDirectoryFinder.cs
@@ -96,7 +96,7 @@ protected void FoundNewDicomDirectory(string dir)
{
Logger.Debug("DicomDirectoryFinder: Found " + dir);
- string dirPath = Path.GetFullPath(dir).TrimEnd(Path.DirectorySeparatorChar);
+ string dirPath = FileSystem.Path.GetFullPath(dir).TrimEnd(FileSystem.Path.DirectorySeparatorChar);
if (dirPath.StartsWith(FileSystemRoot))
dirPath = dirPath.Remove(0, FileSystemRoot.Length);
diff --git a/src/SmiServices/Applications/DicomLoader/DicomLoader.cs b/src/SmiServices/Applications/DicomLoader/DicomLoader.cs
index 77dfb200d..70d29e833 100644
--- a/src/SmiServices/Applications/DicomLoader/DicomLoader.cs
+++ b/src/SmiServices/Applications/DicomLoader/DicomLoader.cs
@@ -17,6 +17,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.IO.Abstractions;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -26,14 +27,14 @@ namespace SmiServices.Applications.DicomLoader;
public static class DicomLoader
{
private static CancellationTokenSource? _cts;
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- return SmiCliInit.ParseAndRun(args, typeof(DicomLoader), OnParse);
+ return SmiCliInit.ParseAndRun(args, typeof(DicomLoader), OnParse, fileSystem ?? new FileSystem());
}
- private static int OnParse(GlobalOptions g, DicomLoaderOptions cliOptions)
+ private static int OnParse(GlobalOptions g, IFileSystem fileSystem, DicomLoaderOptions cliOptions)
{
- return OnParse(g, cliOptions, null);
+ return OnParse(g, fileSystem, cliOptions, null);
}
private static void CancelHandler(object? _, ConsoleCancelEventArgs a)
@@ -42,7 +43,7 @@ private static void CancelHandler(object? _, ConsoleCancelEventArgs a)
a.Cancel = true;
}
- private static int OnParse(GlobalOptions go, DicomLoaderOptions dicomLoaderOptions, Stream? fileList)
+ private static int OnParse(GlobalOptions go, IFileSystem fileSystem, DicomLoaderOptions dicomLoaderOptions, Stream? fileList)
{
if (go.MongoDatabases?.DicomStoreOptions is null)
throw new InvalidOperationException("MongoDatabases or DICOM store options not set");
diff --git a/src/SmiServices/Applications/DicomLoader/Loader.cs b/src/SmiServices/Applications/DicomLoader/Loader.cs
index 347215d22..0101a6dc0 100644
--- a/src/SmiServices/Applications/DicomLoader/Loader.cs
+++ b/src/SmiServices/Applications/DicomLoader/Loader.cs
@@ -15,6 +15,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.IO.Abstractions;
using System.Linq;
using System.Text;
using System.Threading;
@@ -257,9 +258,10 @@ public void Report(CancellationToken? cancellationToken = null)
private readonly DicomLoaderOptions _loadOptions;
private readonly ParallelDLEHost? _parallelDleHost;
private readonly LoadMetadata? _lmd;
+ private readonly IFileSystem _fileSystem;
public Loader(IMongoDatabase database, string imageCollection, string seriesCollection,
- DicomLoaderOptions loadOptions, ParallelDLEHost? parallelDleHost, LoadMetadata? lmd)
+ DicomLoaderOptions loadOptions, ParallelDLEHost? parallelDleHost, LoadMetadata? lmd, IFileSystem? fileSystem = null)
{
_imageQueueLock = new object();
_seriesListLock = new ReaderWriterLockSlim();
@@ -282,6 +284,7 @@ public Loader(IMongoDatabase database, string imageCollection, string seriesColl
_statsLock = new object();
_imageStore = database.GetCollection(imageCollection);
_seriesStore = database.GetCollection(seriesCollection);
+ _fileSystem = fileSystem ?? new FileSystem();
}
///
@@ -290,13 +293,13 @@ public Loader(IMongoDatabase database, string imageCollection, string seriesColl
/// DICOM file or archive of DICOM files to load
/// Cancellation token
///
- private void Process(FileInfo fi, CancellationToken ct)
+ private void Process(IFileInfo fi, CancellationToken ct)
{
ct.ThrowIfCancellationRequested();
var dName = fi.DirectoryName ?? throw new ApplicationException($"No parent directory for '{fi.FullName}'");
var bBuffer = new byte[132];
var buffer = new Span(bBuffer);
- using (var fileStream = File.OpenRead(fi.FullName))
+ using (var fileStream = fi.OpenRead())
{
if (fileStream.Read(buffer) == 132 && buffer[128..].SequenceEqual(_dicomMagic))
{
@@ -429,7 +432,7 @@ private bool ExistingEntry(string filename)
///
public ValueTask Load(string filename, CancellationToken ct)
{
- if (!File.Exists(filename))
+ if (!_fileSystem.File.Exists(filename))
{
Console.WriteLine($@"{filename} does not exist, skipping");
return ValueTask.CompletedTask;
@@ -442,7 +445,7 @@ public ValueTask Load(string filename, CancellationToken ct)
try
{
- Process(new FileInfo(filename), ct);
+ Process(_fileSystem.FileInfo.New(filename), ct);
}
catch (Exception e)
{
diff --git a/src/SmiServices/Applications/DynamicRulesTester/DynamicRulesTester.cs b/src/SmiServices/Applications/DynamicRulesTester/DynamicRulesTester.cs
index bf3d57107..617b165a6 100644
--- a/src/SmiServices/Applications/DynamicRulesTester/DynamicRulesTester.cs
+++ b/src/SmiServices/Applications/DynamicRulesTester/DynamicRulesTester.cs
@@ -22,7 +22,7 @@ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
try
{
- return SmiCliInit.ParseAndRun(args, typeof(DynamicRulesTester), OnParse);
+ return SmiCliInit.ParseAndRun(args, typeof(DynamicRulesTester), OnParse, _fileSystem);
}
catch (Exception e)
{
@@ -31,7 +31,7 @@ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
}
}
- private static int OnParse(GlobalOptions _, DynamicRulesTesterCliOptions cliOptions)
+ private static int OnParse(GlobalOptions _, IFileSystem fileSystem, DynamicRulesTesterCliOptions cliOptions)
{
var dynamicRejector = new DynamicRejector(cliOptions.DynamicRulesFile, _fileSystem);
diff --git a/src/SmiServices/Applications/ExtractImages/ExtractImages.cs b/src/SmiServices/Applications/ExtractImages/ExtractImages.cs
index 7b81a98af..b6b73fe02 100644
--- a/src/SmiServices/Applications/ExtractImages/ExtractImages.cs
+++ b/src/SmiServices/Applications/ExtractImages/ExtractImages.cs
@@ -2,6 +2,7 @@
using SmiServices.Common.Options;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+using System.IO.Abstractions;
namespace SmiServices.Applications.ExtractImages
@@ -9,21 +10,22 @@ namespace SmiServices.Applications.ExtractImages
[ExcludeFromCodeCoverage]
public static class ExtractImages
{
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
int ret = SmiCliInit
.ParseAndRun(
args,
typeof(ExtractImages),
- OnParse
+ OnParse,
+ fileSystem ?? new FileSystem()
);
return ret;
}
- private static int OnParse(GlobalOptions globals, ExtractImagesCliOptions parsedOptions)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, ExtractImagesCliOptions parsedOptions)
{
var bootstrapper =
- new MicroserviceHostBootstrapper(() => new ExtractImagesHost(globals, parsedOptions));
+ new MicroserviceHostBootstrapper(() => new ExtractImagesHost(globals, parsedOptions, fileSystem));
int ret = bootstrapper.Main();
return ret;
}
diff --git a/src/SmiServices/Applications/ExtractImages/ExtractImagesHost.cs b/src/SmiServices/Applications/ExtractImages/ExtractImagesHost.cs
index 059e3fc8b..0d81c9d58 100644
--- a/src/SmiServices/Applications/ExtractImages/ExtractImagesHost.cs
+++ b/src/SmiServices/Applications/ExtractImages/ExtractImagesHost.cs
@@ -14,8 +14,6 @@ namespace SmiServices.Applications.ExtractImages
{
public class ExtractImagesHost : MicroserviceHost
{
- private readonly IFileSystem _fileSystem;
-
private readonly string _csvFilePath;
private readonly IExtractionMessageSender _extractionMessageSender;
@@ -26,37 +24,37 @@ public class ExtractImagesHost : MicroserviceHost
public ExtractImagesHost(
GlobalOptions globals,
ExtractImagesCliOptions cliOptions,
+ IFileSystem? fileSystem = null,
IExtractionMessageSender? extractionMessageSender = null,
IMessageBroker? messageBroker = null,
- IFileSystem? fileSystem = null,
bool threaded = false
)
: base(
globals,
+ fileSystem ?? new FileSystem(),
messageBroker,
threaded
)
{
ExtractImagesOptions? options = Globals.ExtractImagesOptions ?? throw new ArgumentException(nameof(Globals.ExtractImagesOptions));
- _fileSystem = fileSystem ?? new FileSystem();
string extractRoot = Globals.FileSystemOptions?.ExtractRoot ?? throw new ArgumentException("Some part of Globals.FileSystemOptions.ExtractRoot was null");
- if (!_fileSystem.Directory.Exists(extractRoot))
+ if (!FileSystem.Directory.Exists(extractRoot))
throw new DirectoryNotFoundException($"Could not find the extraction root '{extractRoot}'");
_csvFilePath = cliOptions.CohortCsvFile;
if (string.IsNullOrWhiteSpace(_csvFilePath))
throw new ArgumentNullException(nameof(cliOptions));
- if (!_fileSystem.File.Exists(_csvFilePath))
+ if (!FileSystem.File.Exists(_csvFilePath))
throw new FileNotFoundException($"Could not find the cohort CSV file '{_csvFilePath}'");
// TODO(rkm 2021-04-01) Now that all the extraction path code is in C#, we would benefit from refactoring it all out
// to a helper class to support having multiple configurations (and probably prevent some bugs)
- string extractionName = _fileSystem.Path.GetFileNameWithoutExtension(_csvFilePath);
- string extractionDir = _fileSystem.Path.Join(cliOptions.ProjectId, "extractions", extractionName);
- _absoluteExtractionDir = _fileSystem.Path.Join(extractRoot, extractionDir);
+ string extractionName = FileSystem.Path.GetFileNameWithoutExtension(_csvFilePath);
+ string extractionDir = FileSystem.Path.Join(cliOptions.ProjectId, "extractions", extractionName);
+ _absoluteExtractionDir = FileSystem.Path.Join(extractRoot, extractionDir);
- if (_fileSystem.Directory.Exists(_absoluteExtractionDir))
+ if (FileSystem.Directory.Exists(_absoluteExtractionDir))
throw new DirectoryNotFoundException($"Extraction directory already exists '{_absoluteExtractionDir}'");
if (extractionMessageSender == null)
@@ -69,7 +67,7 @@ public ExtractImagesHost(
cliOptions,
extractionRequestProducer,
extractionRequestInfoProducer,
- _fileSystem,
+ FileSystem,
extractRoot,
extractionDir,
new DateTimeProvider(),
@@ -85,7 +83,7 @@ public ExtractImagesHost(
public override void Start()
{
- var parser = new CohortCsvParser(_fileSystem);
+ var parser = new CohortCsvParser(FileSystem);
(ExtractionKey extractionKey, List idList) = parser.Parse(_csvFilePath);
_extractionMessageSender.SendMessages(extractionKey, idList);
diff --git a/src/SmiServices/Applications/Setup/EnvironmentProbe.cs b/src/SmiServices/Applications/Setup/EnvironmentProbe.cs
index 68d8dca4a..0f9c04197 100644
--- a/src/SmiServices/Applications/Setup/EnvironmentProbe.cs
+++ b/src/SmiServices/Applications/Setup/EnvironmentProbe.cs
@@ -20,6 +20,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO.Abstractions;
using System.Linq;
using System.Text;
@@ -118,7 +119,7 @@ public EnvironmentProbe(string? yamlFile)
if (string.IsNullOrWhiteSpace(yamlFile))
throw new Exception("You have not yet entered a path for yaml file");
- Options = new GlobalOptionsFactory().Load("Setup", yamlFile);
+ Options = new GlobalOptionsFactory().Load("Setup", new FileSystem(), yamlFile);
DeserializeYaml = new CheckEventArgs("Deserialized Yaml File", CheckResult.Success);
}
catch (Exception ex)
diff --git a/src/SmiServices/Applications/Setup/MainWindow.cs b/src/SmiServices/Applications/Setup/MainWindow.cs
index 04db4b3fc..2e4fbf20a 100644
--- a/src/SmiServices/Applications/Setup/MainWindow.cs
+++ b/src/SmiServices/Applications/Setup/MainWindow.cs
@@ -18,6 +18,7 @@ namespace Setup
using System;
using System.Collections.Generic;
using System.IO;
+ using System.IO.Abstractions;
using Terminal.Gui;
using Attribute = Terminal.Gui.Attribute;
@@ -27,6 +28,8 @@ public partial class MainWindow {
private readonly ColorScheme _goodScheme;
private readonly ColorScheme _badScheme;
+ private readonly IFileSystem _fileSystem = new FileSystem();
+
///
/// The currently selected yaml file
///
@@ -114,9 +117,9 @@ private void RegisterTry(Button btn, Func probeFunc)
private void ReloadYaml()
{
var f = tbDefaultYaml.Text.ToString();
- if(File.Exists(f))
+ if(_fileSystem.File.Exists(f))
{
- var newYaml = File.ReadAllText(f);
+ var newYaml = _fileSystem.File.ReadAllText(f);
// no need to generate a new probe because the yaml has not changed
if (string.Equals(newYaml, _lastYaml))
diff --git a/src/SmiServices/Applications/TriggerUpdates/TriggerUpdates.cs b/src/SmiServices/Applications/TriggerUpdates/TriggerUpdates.cs
index c85aa269b..2b6c2b3ec 100644
--- a/src/SmiServices/Applications/TriggerUpdates/TriggerUpdates.cs
+++ b/src/SmiServices/Applications/TriggerUpdates/TriggerUpdates.cs
@@ -2,13 +2,14 @@
using SmiServices.Common.Options;
using System;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Applications.TriggerUpdates
{
public static class TriggerUpdates
{
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
int ret = SmiCliInit
.ParseAndRun(
@@ -17,12 +18,13 @@ public static int Main(IEnumerable args)
[
typeof(TriggerUpdatesFromMapperOptions),
],
- OnParse
+ OnParse,
+ fileSystem ?? new FileSystem()
);
return ret;
}
- private static int OnParse(GlobalOptions globals, object opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, object opts)
{
var parsedOptions = SmiCliInit.Verify(opts);
@@ -32,7 +34,7 @@ private static int OnParse(GlobalOptions globals, object opts)
_ => throw new NotImplementedException($"No case for '{parsedOptions.GetType()}'")
};
- var bootstrapper = new MicroserviceHostBootstrapper(() => new TriggerUpdatesHost(globals, source));
+ var bootstrapper = new MicroserviceHostBootstrapper(() => new TriggerUpdatesHost(globals, source, messageBroker: null, fileSystem));
int ret = bootstrapper.Main();
return ret;
}
diff --git a/src/SmiServices/Applications/TriggerUpdates/TriggerUpdatesHost.cs b/src/SmiServices/Applications/TriggerUpdates/TriggerUpdatesHost.cs
index 95bfe035c..2cc58e084 100644
--- a/src/SmiServices/Applications/TriggerUpdates/TriggerUpdatesHost.cs
+++ b/src/SmiServices/Applications/TriggerUpdates/TriggerUpdatesHost.cs
@@ -2,6 +2,7 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Messaging;
using SmiServices.Common.Options;
+using System.IO.Abstractions;
namespace SmiServices.Applications.TriggerUpdates
@@ -11,8 +12,8 @@ public class TriggerUpdatesHost : MicroserviceHost
private readonly ITriggerUpdatesSource _source;
private readonly IProducerModel _producer;
- public TriggerUpdatesHost(GlobalOptions options, ITriggerUpdatesSource source, IMessageBroker? messageBroker = null)
- : base(options, messageBroker)
+ public TriggerUpdatesHost(GlobalOptions options, ITriggerUpdatesSource source, IMessageBroker? messageBroker = null, IFileSystem? fileSystem = null)
+ : base(options, fileSystem ?? new FileSystem(), messageBroker)
{
_source = source;
_producer = MessageBroker.SetupProducer(options.TriggerUpdatesOptions!, isBatch: false);
diff --git a/src/SmiServices/Common/Execution/MicroserviceHost.cs b/src/SmiServices/Common/Execution/MicroserviceHost.cs
index 0283a04bf..f089ffb33 100644
--- a/src/SmiServices/Common/Execution/MicroserviceHost.cs
+++ b/src/SmiServices/Common/Execution/MicroserviceHost.cs
@@ -7,6 +7,7 @@
using SmiServices.Common.Messaging;
using SmiServices.Common.Options;
using System;
+using System.IO.Abstractions;
namespace SmiServices.Common.Execution
{
@@ -19,6 +20,7 @@ public abstract class MicroserviceHost : IMicroserviceHost
protected readonly GlobalOptions Globals;
protected readonly ILogger Logger;
+ protected readonly IFileSystem FileSystem;
protected readonly IMessageBroker MessageBroker;
@@ -39,16 +41,21 @@ public abstract class MicroserviceHost : IMicroserviceHost
/// Loads logging, sets up fatal behaviour, subscribes rabbit etc.
///
/// Settings for the microservice (location of rabbit, queue names etc)
+ ///
///
///
protected MicroserviceHost(
GlobalOptions globals,
+ IFileSystem fileSystem,
IMessageBroker? messageBroker = null,
- bool threaded = false)
+ bool threaded = false
+ )
{
if (globals == null || globals.FileSystemOptions == null || globals.RabbitOptions == null || globals.LoggingOptions == null)
throw new ArgumentException("All or part of the global options are null");
+ FileSystem = fileSystem;
+
// Disable fo-dicom's DICOM validation globally from here
new DicomSetupBuilder().SkipValidation();
diff --git a/src/SmiServices/Common/Messages/AccessionDirectoryMessage.cs b/src/SmiServices/Common/Messages/AccessionDirectoryMessage.cs
index e01876eee..2a9647e82 100644
--- a/src/SmiServices/Common/Messages/AccessionDirectoryMessage.cs
+++ b/src/SmiServices/Common/Messages/AccessionDirectoryMessage.cs
@@ -3,6 +3,7 @@
using Newtonsoft.Json;
using System;
using System.IO;
+using System.IO.Abstractions;
namespace SmiServices.Common.Messages
{
@@ -19,7 +20,7 @@ public sealed class AccessionDirectoryMessage : MemberwiseEquatable Path.Combine(rootPath, DirectoryPath);
-
public override string ToString() => $"AccessionDirectoryMessage[DirectoryPath={DirectoryPath}]";
}
}
diff --git a/src/SmiServices/Common/Messages/DicomFileMessage.cs b/src/SmiServices/Common/Messages/DicomFileMessage.cs
index a500b6d5b..e72bbebc1 100644
--- a/src/SmiServices/Common/Messages/DicomFileMessage.cs
+++ b/src/SmiServices/Common/Messages/DicomFileMessage.cs
@@ -60,32 +60,6 @@ public DicomFileMessage(string root, string file)
DicomFilePath = file[root.Length..].TrimStart(Path.DirectorySeparatorChar);
}
- public string GetAbsolutePath(string rootPath)
- {
- return Path.Combine(rootPath, DicomFilePath);
- }
-
- public bool Validate(string fileSystemRoot)
- {
- var absolutePath = GetAbsolutePath(fileSystemRoot);
-
- if (string.IsNullOrWhiteSpace(absolutePath))
- return false;
-
- try
- {
- var dir = new FileInfo(absolutePath);
-
- //There file referenced must exist
- return dir.Exists;
- }
- catch (Exception)
- {
- return false;
- }
-
- }
-
public bool VerifyPopulated()
{
return !string.IsNullOrWhiteSpace(DicomFilePath) &&
diff --git a/src/SmiServices/Common/Options/GlobalOptions.cs b/src/SmiServices/Common/Options/GlobalOptions.cs
index 8076a37f0..a550405cb 100644
--- a/src/SmiServices/Common/Options/GlobalOptions.cs
+++ b/src/SmiServices/Common/Options/GlobalOptions.cs
@@ -11,6 +11,7 @@
using SmiServices.Common.Messaging;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -557,7 +558,9 @@ public IRDMPPlatformRepositoryServiceLocator GetRepositoryProvider()
// if using file system backend for RDMP create that repo instead
if (!string.IsNullOrWhiteSpace(YamlDir))
{
- return new RepositoryProvider(new YamlRepository(new System.IO.DirectoryInfo(YamlDir)));
+#pragma warning disable IO0007 // Replace DirectoryInfo class with IFileSystem.DirectoryInfo for improved testability
+ return new RepositoryProvider(new YamlRepository(new DirectoryInfo(YamlDir)));
+#pragma warning restore IO0007 // Replace DirectoryInfo class with IFileSystem.DirectoryInfo for improved testability
}
// We are using database backend for RDMP (i.e. Sql Server)
diff --git a/src/SmiServices/Common/Options/GlobalOptionsFactory.cs b/src/SmiServices/Common/Options/GlobalOptionsFactory.cs
index ee93358ca..2d6eb0265 100644
--- a/src/SmiServices/Common/Options/GlobalOptionsFactory.cs
+++ b/src/SmiServices/Common/Options/GlobalOptionsFactory.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.IO.Abstractions;
using YamlDotNet.Serialization;
namespace SmiServices.Common.Options
@@ -28,18 +29,19 @@ public GlobalOptionsFactory(
///
///
///
+ ///
///
- public GlobalOptions Load(string hostProcessName, string configFilePath = "default.yaml")
+ public GlobalOptions Load(string hostProcessName, IFileSystem fileSystem, string configFilePath = "default.yaml")
{
IDeserializer deserializer = new DeserializerBuilder()
.WithObjectFactory(GetGlobalOption)
.IgnoreUnmatchedProperties()
.Build();
- if (!File.Exists(configFilePath))
+ if (!fileSystem.File.Exists(configFilePath))
throw new ArgumentException($"Could not find config file '{configFilePath}'");
- string yamlContents = File.ReadAllText(configFilePath);
+ string yamlContents = fileSystem.File.ReadAllText(configFilePath);
using var sr = new StringReader(yamlContents);
var globals = deserializer.Deserialize(sr);
@@ -70,10 +72,11 @@ private GlobalOptions Decorate(GlobalOptions globals)
///
///
///
+ ///
///
- public GlobalOptions Load(string hostProcessName, CliOptions cliOptions)
+ public GlobalOptions Load(string hostProcessName, CliOptions cliOptions, IFileSystem fileSystem)
{
- GlobalOptions globalOptions = Load(hostProcessName, cliOptions.YamlFile);
+ GlobalOptions globalOptions = Load(hostProcessName, fileSystem, cliOptions.YamlFile);
// The above Load call does the decoration - don't do it here.
return globalOptions;
diff --git a/src/SmiServices/Common/Options/SmiCliInit.cs b/src/SmiServices/Common/Options/SmiCliInit.cs
index f2e30ab53..f6eed04cd 100644
--- a/src/SmiServices/Common/Options/SmiCliInit.cs
+++ b/src/SmiServices/Common/Options/SmiCliInit.cs
@@ -4,6 +4,7 @@
using NLog.Targets;
using System;
using System.Collections.Generic;
+using System.IO.Abstractions;
using System.Linq;
@@ -48,8 +49,9 @@ public static Parser GetDefaultParser()
/// Arguments passed to Main
///
/// The function to call on a successful parse
+ ///
/// The return code from the onParse function
- public static int ParseAndRun(IEnumerable args, Type programType, Func onParse) where T : CliOptions
+ public static int ParseAndRun(IEnumerable args, Type programType, Func onParse, IFileSystem fileSystem) where T : CliOptions
{
int ret = _parser
.ParseArguments(args)
@@ -58,7 +60,7 @@ public static int ParseAndRun(IEnumerable args, Type programType, Fun
{
string hostProcessName = GetHostProcessName(programType);
- GlobalOptions globals = new GlobalOptionsFactory().Load(hostProcessName, parsed);
+ GlobalOptions globals = new GlobalOptionsFactory().Load(hostProcessName, parsed, fileSystem);
if (InitSmiLogging)
{
@@ -66,7 +68,7 @@ public static int ParseAndRun(IEnumerable args, Type programType, Fun
SmiLogging.Setup(globals.LoggingOptions, hostProcessName);
}
- return onParse(globals, parsed);
+ return onParse(globals, fileSystem, parsed);
},
OnErrors
);
@@ -80,8 +82,9 @@ public static int ParseAndRun(IEnumerable args, Type programType, Fun
///
/// The list of possible target verb types to construct from the args
/// The function to call on a successful parse
+ ///
/// The return code from the onParse function
- public static int ParseAndRun(IEnumerable args, Type programType, Type[] targetVerbTypes, Func onParse)
+ public static int ParseAndRun(IEnumerable args, Type programType, Type[] targetVerbTypes, Func onParse, IFileSystem fileSystem)
{
int ret = _parser
.ParseArguments(
@@ -94,7 +97,7 @@ public static int ParseAndRun(IEnumerable args, Type programType, Type[]
string hostProcessName = GetHostProcessName(programType);
var cliOptions = Verify(parsed);
- GlobalOptions globals = new GlobalOptionsFactory().Load(hostProcessName, cliOptions);
+ GlobalOptions globals = new GlobalOptionsFactory().Load(hostProcessName, cliOptions, fileSystem);
if (InitSmiLogging)
{
@@ -102,7 +105,7 @@ public static int ParseAndRun(IEnumerable args, Type programType, Type[]
SmiLogging.Setup(globals.LoggingOptions, hostProcessName);
}
- return onParse(globals, parsed);
+ return onParse(globals, fileSystem, parsed);
},
OnErrors
);
diff --git a/src/SmiServices/Common/SmiLogging.cs b/src/SmiServices/Common/SmiLogging.cs
index 9253a43b3..62ab5a0de 100644
--- a/src/SmiServices/Common/SmiLogging.cs
+++ b/src/SmiServices/Common/SmiLogging.cs
@@ -2,6 +2,7 @@
using SmiServices.Common.Options;
using System;
using System.IO;
+using System.IO.Abstractions;
namespace SmiServices.Common
@@ -12,18 +13,20 @@ public static class SmiLogging
private static bool _initialised;
- public static void Setup(LoggingOptions loggingOptions, string hostProcessName)
+ public static void Setup(LoggingOptions loggingOptions, string hostProcessName, IFileSystem? fileSystem = null)
{
if (_initialised)
throw new Exception("SmiLogging already initialised");
_initialised = true;
- string localConfig = Path.Combine(Directory.GetCurrentDirectory(), DefaultLogConfigName);
+ fileSystem ??= new FileSystem();
+
+ string localConfig = fileSystem.Path.Combine(fileSystem.Directory.GetCurrentDirectory(), DefaultLogConfigName);
string configFilePathToLoad = !string.IsNullOrWhiteSpace(loggingOptions.LogConfigFile)
? loggingOptions.LogConfigFile
: localConfig;
- if (!File.Exists(configFilePathToLoad))
+ if (!fileSystem.File.Exists(configFilePathToLoad))
throw new FileNotFoundException($"Could not find the specified logging configuration '{configFilePathToLoad})'");
LogManager.ThrowConfigExceptions = true;
@@ -31,10 +34,10 @@ public static void Setup(LoggingOptions loggingOptions, string hostProcessName)
if (!string.IsNullOrWhiteSpace(loggingOptions.LogsRoot))
{
- if (!Directory.Exists(loggingOptions.LogsRoot))
+ if (!fileSystem.Directory.Exists(loggingOptions.LogsRoot))
throw new ApplicationException($"Invalid log root '{loggingOptions.LogsRoot}'");
- VerifyCanWrite(loggingOptions.LogsRoot);
+ VerifyCanWrite(loggingOptions.LogsRoot, fileSystem);
LogManager.Configuration.Variables["baseFileName"] =
$"{loggingOptions.LogsRoot}/" +
@@ -42,7 +45,7 @@ public static void Setup(LoggingOptions loggingOptions, string hostProcessName)
$"${{cached:cached=true:clearCache=None:inner=${{date:format=yyyy-MM-dd-HH-mm-ss}}}}-${{processid}}";
}
else
- VerifyCanWrite(Directory.GetCurrentDirectory());
+ VerifyCanWrite(fileSystem.Directory.GetCurrentDirectory(), fileSystem);
Logger logger = LogManager.GetLogger(nameof(SmiLogging));
LogManager.GlobalThreshold = LogLevel.Trace;
@@ -54,13 +57,13 @@ public static void Setup(LoggingOptions loggingOptions, string hostProcessName)
logger.Info($"Logging config loaded from {configFilePathToLoad}");
}
- private static void VerifyCanWrite(string logsRoot)
+ private static void VerifyCanWrite(string logsRoot, IFileSystem fileSystem)
{
- string[] tmpFileParts = Path.GetTempFileName().Split(Path.DirectorySeparatorChar);
- string tmpFileInLogsRoot = Path.Combine(logsRoot, tmpFileParts[^1]);
+ string[] tmpFileParts = fileSystem.Path.GetTempFileName().Split(fileSystem.Path.DirectorySeparatorChar);
+ string tmpFileInLogsRoot = fileSystem.Path.Combine(logsRoot, tmpFileParts[^1]);
try
{
- File.WriteAllText(tmpFileInLogsRoot, "");
+ fileSystem.File.WriteAllText(tmpFileInLogsRoot, "");
}
catch (UnauthorizedAccessException e)
{
@@ -68,7 +71,7 @@ private static void VerifyCanWrite(string logsRoot)
}
finally
{
- File.Delete(tmpFileInLogsRoot);
+ fileSystem.File.Delete(tmpFileInLogsRoot);
}
}
}
diff --git a/src/SmiServices/Common/ZipHelper.cs b/src/SmiServices/Common/ZipHelper.cs
index 8c388f768..c7d6371a3 100644
--- a/src/SmiServices/Common/ZipHelper.cs
+++ b/src/SmiServices/Common/ZipHelper.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.IO;
using System.IO.Abstractions;
namespace SmiServices.Common
@@ -21,16 +20,5 @@ public static bool IsZip(IFileInfo f)
{
return SupportedExtensions.Contains(f.Extension);
}
-
- ///
- /// Returns true if looks like a compressed archive compatible with smi e.g. zip, tar etc
- ///
- ///
- ///
- public static bool IsZip(string path)
- {
- return SupportedExtensions.Contains(Path.GetExtension(path));
- }
-
}
}
diff --git a/src/SmiServices/Microservices/CohortExtractor/CohortExtractor.cs b/src/SmiServices/Microservices/CohortExtractor/CohortExtractor.cs
index c4db41ee8..9c8672e23 100644
--- a/src/SmiServices/Microservices/CohortExtractor/CohortExtractor.cs
+++ b/src/SmiServices/Microservices/CohortExtractor/CohortExtractor.cs
@@ -1,18 +1,19 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.CohortExtractor
{
public static class CohortExtractor
{
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(CohortExtractor), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(CohortExtractor), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, CliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem? fileSystem, CliOptions opts)
{
//Use the auditor and request fullfilers specified in the yaml
var bootstrapper = new MicroserviceHostBootstrapper(
diff --git a/src/SmiServices/Microservices/CohortExtractor/CohortExtractorHost.cs b/src/SmiServices/Microservices/CohortExtractor/CohortExtractorHost.cs
index ea35dd48f..001667045 100644
--- a/src/SmiServices/Microservices/CohortExtractor/CohortExtractorHost.cs
+++ b/src/SmiServices/Microservices/CohortExtractor/CohortExtractorHost.cs
@@ -15,6 +15,7 @@
using SmiServices.Microservices.CohortExtractor.ProjectPathResolvers;
using SmiServices.Microservices.CohortExtractor.RequestFulfillers;
using System;
+using System.IO.Abstractions;
using System.Linq;
using System.Text.RegularExpressions;
@@ -45,10 +46,11 @@ public class CohortExtractorHost : MicroserviceHost
/// Creates a new instance of the host with the given
///
/// Settings for the microservice (location of rabbit, queue names etc)
+ ///
/// Optional override for the value specified in
/// Optional override for the value specified in
- public CohortExtractorHost(GlobalOptions options, IAuditExtractions? auditor, IExtractionRequestFulfiller? fulfiller)
- : base(options)
+ public CohortExtractorHost(GlobalOptions options, IAuditExtractions? auditor, IExtractionRequestFulfiller? fulfiller, IFileSystem? fileSystem = null)
+ : base(options, fileSystem ?? new FileSystem())
{
_consumerOptions = options.CohortExtractorOptions!;
_consumerOptions.Validate();
@@ -151,7 +153,7 @@ private void InitializeExtractionSources(IRDMPPlatformRepositoryServiceLocator r
}
_pathResolver = string.IsNullOrWhiteSpace(_consumerOptions.ProjectPathResolverType)
- ? new DefaultProjectPathResolver()
+ ? new DefaultProjectPathResolver(FileSystem)
: ObjectFactory.CreateInstance(
_consumerOptions.ProjectPathResolverType, typeof(IProjectPathResolver).Assembly, repositoryLocator);
}
diff --git a/src/SmiServices/Microservices/CohortExtractor/ProjectPathResolvers/DefaultProjectPathResolver.cs b/src/SmiServices/Microservices/CohortExtractor/ProjectPathResolvers/DefaultProjectPathResolver.cs
index 64cb2b26d..5b6b30e84 100644
--- a/src/SmiServices/Microservices/CohortExtractor/ProjectPathResolvers/DefaultProjectPathResolver.cs
+++ b/src/SmiServices/Microservices/CohortExtractor/ProjectPathResolvers/DefaultProjectPathResolver.cs
@@ -1,17 +1,24 @@
using SmiServices.Common.Messages.Extraction;
using SmiServices.Microservices.CohortExtractor.RequestFulfillers;
using System;
-using System.IO;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.CohortExtractor.ProjectPathResolvers
{
public class DefaultProjectPathResolver : IProjectPathResolver
{
+ private readonly IFileSystem _fileSystem;
+
public string AnonExt { get; protected set; } = "-an.dcm";
public string IdentExt { get; protected set; } = ".dcm";
private static readonly string[] _replaceableExtensions = [".dcm", ".dicom"];
+ public DefaultProjectPathResolver(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
///
/// Returns the output path for the anonymised file, relative to the ExtractionDirectory
///
@@ -23,7 +30,7 @@ public string GetOutputPath(QueryToExecuteResult result, ExtractionRequestMessag
string extToUse = message.IsIdentifiableExtraction ? IdentExt : AnonExt;
// The extension of the input DICOM file can be anything (or nothing), but here we try to standardise the output file name to have the required extension
- string fileName = Path.GetFileName(result.FilePathValue);
+ string fileName = _fileSystem.Path.GetFileName(result.FilePathValue);
if (string.IsNullOrWhiteSpace(fileName))
throw new ArgumentNullException(nameof(result));
@@ -43,10 +50,11 @@ public string GetOutputPath(QueryToExecuteResult result, ExtractionRequestMessag
string? studyUID = result.StudyTagValue?.TrimStart('.');
string? seriesUID = result.SeriesTagValue?.TrimStart('.');
- return Path.Combine(
+ return _fileSystem.Path.Combine(
studyUID ?? "unknown",
seriesUID ?? "unknown",
- fileName);
+ fileName
+ );
}
}
}
diff --git a/src/SmiServices/Microservices/CohortExtractor/ProjectPathResolvers/NoSuffixProjectPathResolver.cs b/src/SmiServices/Microservices/CohortExtractor/ProjectPathResolvers/NoSuffixProjectPathResolver.cs
index 5e49d9575..14dd70302 100644
--- a/src/SmiServices/Microservices/CohortExtractor/ProjectPathResolvers/NoSuffixProjectPathResolver.cs
+++ b/src/SmiServices/Microservices/CohortExtractor/ProjectPathResolvers/NoSuffixProjectPathResolver.cs
@@ -1,3 +1,5 @@
+using System.IO.Abstractions;
+
namespace SmiServices.Microservices.CohortExtractor.ProjectPathResolvers
{
///
@@ -5,7 +7,8 @@ namespace SmiServices.Microservices.CohortExtractor.ProjectPathResolvers
///
public class NoSuffixProjectPathResolver : DefaultProjectPathResolver
{
- public NoSuffixProjectPathResolver()
+ public NoSuffixProjectPathResolver(IFileSystem fileSystem)
+ : base(fileSystem)
{
AnonExt = ".dcm";
}
diff --git a/src/SmiServices/Microservices/CohortPackager/CohortPackager.cs b/src/SmiServices/Microservices/CohortPackager/CohortPackager.cs
index 70992a0a1..992a9409a 100644
--- a/src/SmiServices/Microservices/CohortPackager/CohortPackager.cs
+++ b/src/SmiServices/Microservices/CohortPackager/CohortPackager.cs
@@ -7,31 +7,29 @@
using SmiServices.Microservices.CohortPackager.JobProcessing.Reporting;
using System;
using System.Collections.Generic;
-using System.IO;
using System.IO.Abstractions;
-
namespace SmiServices.Microservices.CohortPackager
{
public static class CohortPackager
{
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(CohortPackager), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(CohortPackager), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, CohortPackagerCliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, CohortPackagerCliOptions opts)
{
if (opts.ExtractionId != default)
- return RecreateReports(globals, opts);
+ return RecreateReports(globals, fileSystem, opts);
var bootstrapper = new MicroserviceHostBootstrapper(() => new CohortPackagerHost(globals));
int ret = bootstrapper.Main();
return ret;
}
- private static int RecreateReports(GlobalOptions globalOptions, CohortPackagerCliOptions cliOptions)
+ private static int RecreateReports(GlobalOptions globalOptions, IFileSystem fileSystem, CohortPackagerCliOptions cliOptions)
{
Logger logger = LogManager.GetCurrentClassLogger();
@@ -58,7 +56,7 @@ private static int RecreateReports(GlobalOptions globalOptions, CohortPackagerCl
var reporter = new JobReporter(
jobStore,
new FileSystem(),
- Directory.GetCurrentDirectory(),
+ fileSystem.Directory.GetCurrentDirectory(),
cliOptions.OutputNewLine ?? globalOptions.CohortPackagerOptions?.ReportNewLine
);
diff --git a/src/SmiServices/Microservices/CohortPackager/CohortPackagerHost.cs b/src/SmiServices/Microservices/CohortPackager/CohortPackagerHost.cs
index f132e05c9..c778d7960 100644
--- a/src/SmiServices/Microservices/CohortPackager/CohortPackagerHost.cs
+++ b/src/SmiServices/Microservices/CohortPackager/CohortPackagerHost.cs
@@ -42,14 +42,14 @@ public class CohortPackagerHost : MicroserviceHost
///
public CohortPackagerHost(
GlobalOptions globals,
- IExtractJobStore? jobStore = null,
IFileSystem? fileSystem = null,
+ IExtractJobStore? jobStore = null,
IJobReporter? reporter = null,
IJobCompleteNotifier? notifier = null,
IMessageBroker? messageBroker = null,
DateTimeProvider? dateTimeProvider = null
)
- : base(globals, messageBroker)
+ : base(globals, fileSystem ?? new FileSystem(), messageBroker)
{
var cohortPackagerOptions = globals.CohortPackagerOptions ??
throw new ArgumentNullException(nameof(globals), "CohortPackagerOptions cannot be null");
@@ -77,7 +77,7 @@ public CohortPackagerHost(
reporter = new JobReporter(
jobStore,
- fileSystem ?? new FileSystem(),
+ FileSystem,
extractRoot,
cohortPackagerOptions.ReportNewLine
);
diff --git a/src/SmiServices/Microservices/DicomAnonymiser/DicomAnonymiser.cs b/src/SmiServices/Microservices/DicomAnonymiser/DicomAnonymiser.cs
index 22c5d6cd4..c00bab5a7 100644
--- a/src/SmiServices/Microservices/DicomAnonymiser/DicomAnonymiser.cs
+++ b/src/SmiServices/Microservices/DicomAnonymiser/DicomAnonymiser.cs
@@ -1,6 +1,7 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.DicomAnonymiser
{
@@ -10,13 +11,14 @@ public static class DicomAnonymiser
/// Program entry point when run from the command line
///
///
- public static int Main(IEnumerable args)
+ ///
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(DicomAnonymiser), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(DicomAnonymiser), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, CliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, CliOptions opts)
{
var bootstrapper = new MicroserviceHostBootstrapper(() => new DicomAnonymiserHost(globals));
int ret = bootstrapper.Main();
diff --git a/src/SmiServices/Microservices/DicomAnonymiser/DicomAnonymiserHost.cs b/src/SmiServices/Microservices/DicomAnonymiser/DicomAnonymiserHost.cs
index 08867db04..a08ef8e9d 100644
--- a/src/SmiServices/Microservices/DicomAnonymiser/DicomAnonymiserHost.cs
+++ b/src/SmiServices/Microservices/DicomAnonymiser/DicomAnonymiserHost.cs
@@ -13,10 +13,10 @@ public class DicomAnonymiserHost : MicroserviceHost
public DicomAnonymiserHost(
GlobalOptions options,
- IDicomAnonymiser? anonymiser = null,
- IFileSystem? fileSystem = null
+ IFileSystem? fileSystem = null,
+ IDicomAnonymiser? anonymiser = null
)
- : base(options)
+ : base(options, fileSystem ?? new FileSystem())
{
_anonymiser = anonymiser ?? AnonymiserFactory.CreateAnonymiser(options!);
@@ -28,7 +28,7 @@ public DicomAnonymiserHost(
Globals.FileSystemOptions.ExtractRoot!,
_anonymiser,
producerModel,
- fileSystem
+ FileSystem
);
}
diff --git a/src/SmiServices/Microservices/DicomRelationalMapper/DicomRelationalMapper.cs b/src/SmiServices/Microservices/DicomRelationalMapper/DicomRelationalMapper.cs
index 9f8aa7322..347ae7c15 100644
--- a/src/SmiServices/Microservices/DicomRelationalMapper/DicomRelationalMapper.cs
+++ b/src/SmiServices/Microservices/DicomRelationalMapper/DicomRelationalMapper.cs
@@ -1,18 +1,19 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.DicomRelationalMapper
{
public static class DicomRelationalMapper
{
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(DicomRelationalMapper), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(DicomRelationalMapper), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, CliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, CliOptions opts)
{
var bootstrapper = new MicroserviceHostBootstrapper(() => new DicomRelationalMapperHost(globals));
int ret = bootstrapper.Main();
diff --git a/src/SmiServices/Microservices/DicomRelationalMapper/DicomRelationalMapperHost.cs b/src/SmiServices/Microservices/DicomRelationalMapper/DicomRelationalMapperHost.cs
index 2922e9d26..0c77d30a2 100644
--- a/src/SmiServices/Microservices/DicomRelationalMapper/DicomRelationalMapperHost.cs
+++ b/src/SmiServices/Microservices/DicomRelationalMapper/DicomRelationalMapperHost.cs
@@ -11,6 +11,7 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.DicomRelationalMapper
@@ -19,8 +20,8 @@ public class DicomRelationalMapperHost : MicroserviceHost, IDisposable
{
public DicomRelationalMapperQueueConsumer? Consumer { get; private set; }
- public DicomRelationalMapperHost(GlobalOptions globals)
- : base(globals)
+ public DicomRelationalMapperHost(GlobalOptions globals, IFileSystem? fileSystem = null)
+ : base(globals, fileSystem ?? new FileSystem())
{
FansiImplementations.Load();
}
diff --git a/src/SmiServices/Microservices/DicomRelationalMapper/ExplicitListDicomProcessListProvider.cs b/src/SmiServices/Microservices/DicomRelationalMapper/ExplicitListDicomProcessListProvider.cs
index 27735d607..d0bd8c567 100644
--- a/src/SmiServices/Microservices/DicomRelationalMapper/ExplicitListDicomProcessListProvider.cs
+++ b/src/SmiServices/Microservices/DicomRelationalMapper/ExplicitListDicomProcessListProvider.cs
@@ -25,19 +25,25 @@ public bool GetNextFileOrDirectoryToProcess(out DirectoryInfo? directory, out Am
return false;
}
+#pragma warning disable IO0002 // Replace File class with IFileSystem.File for improved testability
if (File.Exists(_filesAndOrDirectories[index]))
{
file = new AmbiguousFilePath(_filesAndOrDirectories[index]);
index++;
return true;
}
+#pragma warning restore IO0002 // Replace File class with IFileSystem.File for improved testability
+#pragma warning disable IO0003 // Replace Directory class with IFileSystem.Directory for improved testability
if (Directory.Exists(_filesAndOrDirectories[index]))
{
+#pragma warning disable IO0007 // Replace DirectoryInfo class with IFileSystem.DirectoryInfo for improved testability
directory = new DirectoryInfo(_filesAndOrDirectories[index]);
+#pragma warning restore IO0007 // Replace DirectoryInfo class with IFileSystem.DirectoryInfo for improved testability
index++;
return true;
}
+#pragma warning restore IO0003 // Replace Directory class with IFileSystem.Directory for improved testability
throw new Exception("Array element " + index + " of filesAndOrDirectories was not a File or Directory (or the referenced file did not exist). Array element is '" + _filesAndOrDirectories[index] + "'");
}
diff --git a/src/SmiServices/Microservices/DicomReprocessor/DicomReprocessor.cs b/src/SmiServices/Microservices/DicomReprocessor/DicomReprocessor.cs
index 11b96dad7..0a06458c9 100644
--- a/src/SmiServices/Microservices/DicomReprocessor/DicomReprocessor.cs
+++ b/src/SmiServices/Microservices/DicomReprocessor/DicomReprocessor.cs
@@ -1,18 +1,19 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.DicomReprocessor
{
public static class DicomReprocessor
{
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(DicomReprocessor), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(DicomReprocessor), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, DicomReprocessorCliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, DicomReprocessorCliOptions opts)
{
var bootstrapper = new MicroserviceHostBootstrapper(() => new DicomReprocessorHost(globals, opts));
int ret = bootstrapper.Main();
diff --git a/src/SmiServices/Microservices/DicomReprocessor/DicomReprocessorHost.cs b/src/SmiServices/Microservices/DicomReprocessor/DicomReprocessorHost.cs
index 657734438..f9f1f076a 100644
--- a/src/SmiServices/Microservices/DicomReprocessor/DicomReprocessorHost.cs
+++ b/src/SmiServices/Microservices/DicomReprocessor/DicomReprocessorHost.cs
@@ -2,7 +2,7 @@
using SmiServices.Common.Messaging;
using SmiServices.Common.Options;
using System;
-using System.IO;
+using System.IO.Abstractions;
using System.Threading.Tasks;
namespace SmiServices.Microservices.DicomReprocessor
@@ -15,8 +15,8 @@ public class DicomReprocessorHost : MicroserviceHost
private readonly string? _queryString;
- public DicomReprocessorHost(GlobalOptions options, DicomReprocessorCliOptions cliOptions)
- : base(options)
+ public DicomReprocessorHost(GlobalOptions options, DicomReprocessorCliOptions cliOptions, IFileSystem? fileSystem = null)
+ : base(options, fileSystem ?? new FileSystem())
{
string? key = cliOptions.ReprocessingRoutingKey;
@@ -33,7 +33,7 @@ public DicomReprocessorHost(GlobalOptions options, DicomReprocessorCliOptions cl
options.RabbitOptions!.RabbitMqVirtualHost + " with routing key \"" + key + "\"");
if (!string.IsNullOrWhiteSpace(cliOptions.QueryFile))
- _queryString = File.ReadAllText(cliOptions.QueryFile);
+ _queryString = FileSystem.File.ReadAllText(cliOptions.QueryFile);
//TODO Make this into a CreateInstance<> call
_processor = options.DicomReprocessorOptions.ProcessingMode switch
diff --git a/src/SmiServices/Microservices/DicomTagReader/DicomTagReader.cs b/src/SmiServices/Microservices/DicomTagReader/DicomTagReader.cs
index 6bb0cfb2a..b4f71daf4 100644
--- a/src/SmiServices/Microservices/DicomTagReader/DicomTagReader.cs
+++ b/src/SmiServices/Microservices/DicomTagReader/DicomTagReader.cs
@@ -4,6 +4,7 @@
using SmiServices.Microservices.DicomTagReader.Execution;
using System;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.DicomTagReader
{
@@ -13,20 +14,21 @@ public static class DicomTagReader
/// Program entry point when run from the command line
///
///
- public static int Main(IEnumerable args)
+ ///
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(DicomTagReader), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(DicomTagReader), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, DicomTagReaderCliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, DicomTagReaderCliOptions opts)
{
if (opts.File != null)
{
try
{
var host = new DicomTagReaderHost(globals);
- host.AccessionDirectoryMessageConsumer.RunSingleFile(opts.File);
+ host.AccessionDirectoryMessageConsumer.RunSingleFile(fileSystem.FileInfo.New(opts.File));
return 0;
}
catch (Exception ex)
diff --git a/src/SmiServices/Microservices/DicomTagReader/DicomTagReaderCliOptions.cs b/src/SmiServices/Microservices/DicomTagReader/DicomTagReaderCliOptions.cs
index 75551f5ec..5ecd16cac 100644
--- a/src/SmiServices/Microservices/DicomTagReader/DicomTagReaderCliOptions.cs
+++ b/src/SmiServices/Microservices/DicomTagReader/DicomTagReaderCliOptions.cs
@@ -15,6 +15,6 @@ public class DicomTagReaderCliOptions : CliOptions
Required = false,
HelpText = "[Optional] Name of a specific dicom or zip file to process instead of subscribing to rabbit"
)]
- public FileInfo? File { get; set; }
+ public string? File { get; set; }
}
}
diff --git a/src/SmiServices/Microservices/DicomTagReader/Execution/DicomTagReaderHost.cs b/src/SmiServices/Microservices/DicomTagReader/Execution/DicomTagReaderHost.cs
index bda3f364c..4d6602126 100644
--- a/src/SmiServices/Microservices/DicomTagReader/Execution/DicomTagReaderHost.cs
+++ b/src/SmiServices/Microservices/DicomTagReader/Execution/DicomTagReaderHost.cs
@@ -15,10 +15,10 @@ public class DicomTagReaderHost : MicroserviceHost
private readonly TagReaderBase _tagReader;
- public DicomTagReaderHost(GlobalOptions options)
- : base(options)
+ public DicomTagReaderHost(GlobalOptions options, IFileSystem? fileSystem = null)
+ : base(options, fileSystem ?? new FileSystem())
{
- if (!Directory.Exists(options.FileSystemOptions!.FileSystemRoot))
+ if (!FileSystem.Directory.Exists(options.FileSystemOptions!.FileSystemRoot))
throw new ArgumentException(
$"Cannot find the FileSystemRoot specified in the given MicroservicesOptions ({options.FileSystemOptions.FileSystemRoot})");
diff --git a/src/SmiServices/Microservices/DicomTagReader/Execution/ParallelTagReader.cs b/src/SmiServices/Microservices/DicomTagReader/Execution/ParallelTagReader.cs
index 5c3762863..6b105b2a4 100644
--- a/src/SmiServices/Microservices/DicomTagReader/Execution/ParallelTagReader.cs
+++ b/src/SmiServices/Microservices/DicomTagReader/Execution/ParallelTagReader.cs
@@ -28,7 +28,7 @@ public ParallelTagReader(DicomTagReaderOptions options, FileSystemOptions fileSy
Logger.Info($"Using MaxDegreeOfParallelism={_parallelOptions.MaxDegreeOfParallelism} for parallel IO operations");
}
- protected override List ReadTagsImpl(IEnumerable dicomFilePaths,
+ protected override List ReadTagsImpl(IEnumerable dicomFilePaths,
AccessionDirectoryMessage accMessage)
{
var fileMessages = new List();
diff --git a/src/SmiServices/Microservices/DicomTagReader/Execution/SerialTagReader.cs b/src/SmiServices/Microservices/DicomTagReader/Execution/SerialTagReader.cs
index 513c6a4ea..237bf130f 100644
--- a/src/SmiServices/Microservices/DicomTagReader/Execution/SerialTagReader.cs
+++ b/src/SmiServices/Microservices/DicomTagReader/Execution/SerialTagReader.cs
@@ -16,11 +16,11 @@ public SerialTagReader(DicomTagReaderOptions options, FileSystemOptions fileSyst
IProducerModel seriesMessageProducerModel, IProducerModel fileMessageProducerModel, IFileSystem fs)
: base(options, fileSystemOptions, seriesMessageProducerModel, fileMessageProducerModel, fs) { }
- protected override List ReadTagsImpl(IEnumerable dicomFilePaths, AccessionDirectoryMessage accMessage)
+ protected override List ReadTagsImpl(IEnumerable dicomFilePaths, AccessionDirectoryMessage accMessage)
{
var fileMessages = new List();
- foreach (FileInfo dicomFilePath in dicomFilePaths)
+ foreach (var dicomFilePath in dicomFilePaths)
{
Logger.Trace("TagReader: Processing " + dicomFilePath);
diff --git a/src/SmiServices/Microservices/DicomTagReader/Execution/TagReaderBase.cs b/src/SmiServices/Microservices/DicomTagReader/Execution/TagReaderBase.cs
index b3c0b60a9..065eca696 100644
--- a/src/SmiServices/Microservices/DicomTagReader/Execution/TagReaderBase.cs
+++ b/src/SmiServices/Microservices/DicomTagReader/Execution/TagReaderBase.cs
@@ -20,7 +20,7 @@ namespace SmiServices.Microservices.DicomTagReader.Execution
public abstract class TagReaderBase
{
private readonly string _filesystemRoot;
- private readonly IFileSystem _fs;
+ private readonly IFileSystem _fileSystem;
private readonly IProducerModel _seriesMessageProducerModel;
private readonly IProducerModel _fileMessageProducerModel;
@@ -68,7 +68,7 @@ public TagReaderBase(DicomTagReaderOptions options, FileSystemOptions fileSystem
_seriesMessageProducerModel = seriesMessageProducerModel;
_fileMessageProducerModel = fileMessageProducerModel;
- _fs = fs;
+ _fileSystem = fs;
Logger.Info($"Stopwatch implementation - IsHighResolution: {Stopwatch.IsHighResolution}. Frequency: {Stopwatch.Frequency} ticks/s");
}
@@ -82,18 +82,18 @@ public void ReadTags(IMessageHeader? header, AccessionDirectoryMessage message)
{
_stopwatch.Restart();
- string dirPath = message.GetAbsolutePath(_filesystemRoot);
+ string dirPath = _fileSystem.Path.Combine(_filesystemRoot, message.DirectoryPath);
Logger.Debug("TagReader: About to process files in " + dirPath);
- if (!_fs.Directory.Exists(dirPath))
+ if (!_fileSystem.Directory.Exists(dirPath))
throw new ApplicationException("Directory not found: " + dirPath);
if (!dirPath.StartsWith(_filesystemRoot, StringComparison.CurrentCultureIgnoreCase))
throw new ApplicationException("Directory " + dirPath + " is not below the given FileSystemRoot (" +
_filesystemRoot + ")");
long beginEnumerate = _stopwatch.ElapsedTicks;
- string[] dicomFilePaths = _fs.Directory.EnumerateFiles(dirPath, _searchPattern).Where(Include).ToArray();
- string[] zipFilePaths = _fs.Directory.EnumerateFiles(dirPath).Where(ZipHelper.IsZip).Where(Include).ToArray();
+ string[] dicomFilePaths = _fileSystem.Directory.EnumerateFiles(dirPath, _searchPattern).Where(Include).ToArray();
+ string[] zipFilePaths = _fileSystem.Directory.EnumerateFiles(dirPath).Where(x => ZipHelper.IsZip(_fileSystem.FileInfo.New(x))).Where(Include).ToArray();
_swTotals[0] += _stopwatch.ElapsedTicks - beginEnumerate;
Logger.Debug("TagReader: Found " + dicomFilePaths.Length + " dicom files to process");
@@ -108,8 +108,8 @@ public void ReadTags(IMessageHeader? header, AccessionDirectoryMessage message)
long beginRead = _stopwatch.ElapsedTicks;
- List fileMessages = ReadTagsImpl(dicomFilePaths.Select(p => new FileInfo(p)), message);
- fileMessages.AddRange(ReadZipFilesImpl(zipFilePaths.Select(p => new FileInfo(p)), message));
+ List fileMessages = ReadTagsImpl(dicomFilePaths.Select(_fileSystem.FileInfo.New), message);
+ fileMessages.AddRange(ReadZipFilesImpl(zipFilePaths.Select(_fileSystem.FileInfo.New), message));
_swTotals[1] += (_stopwatch.ElapsedTicks - beginRead) / toProcess;
@@ -192,9 +192,9 @@ public bool Include(string filePath)
/// All the zip files that must be explored for dcm files
/// The upstream message that suggested we look for dicom files in a given directory
///
- protected virtual IEnumerable ReadZipFilesImpl(IEnumerable zipFilePaths, AccessionDirectoryMessage accMessage)
+ protected virtual IEnumerable ReadZipFilesImpl(IEnumerable zipFilePaths, AccessionDirectoryMessage accMessage)
{
- foreach (FileInfo zipFilePath in zipFilePaths)
+ foreach (var zipFilePath in zipFilePaths)
{
using var archive = ZipFile.Open(zipFilePath.FullName, ZipArchiveMode.Read);
foreach (var entry in archive.Entries)
@@ -285,7 +285,7 @@ private static byte[] ReadFully(Stream stream)
ms.Write(buffer, 0, read);
}
}
- protected abstract List ReadTagsImpl(IEnumerable dicomFilePaths,
+ protected abstract List ReadTagsImpl(IEnumerable dicomFilePaths,
AccessionDirectoryMessage accMessage);
///
@@ -293,7 +293,7 @@ protected abstract List ReadTagsImpl(IEnumerable dic
///
///
///
- protected DicomFileMessage ReadTagsFromFile(FileInfo dicomFilePath)
+ protected DicomFileMessage ReadTagsFromFile(IFileInfo dicomFilePath)
{
try
{
diff --git a/src/SmiServices/Microservices/DicomTagReader/Messaging/DicomTagReaderConsumer.cs b/src/SmiServices/Microservices/DicomTagReader/Messaging/DicomTagReaderConsumer.cs
index 5ec1ebc88..0eb8fbbc0 100644
--- a/src/SmiServices/Microservices/DicomTagReader/Messaging/DicomTagReaderConsumer.cs
+++ b/src/SmiServices/Microservices/DicomTagReader/Messaging/DicomTagReaderConsumer.cs
@@ -5,6 +5,7 @@
using SmiServices.Microservices.DicomTagReader.Execution;
using System;
using System.IO;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.DicomTagReader.Messaging
{
@@ -61,10 +62,10 @@ protected override void ProcessMessageImpl(IMessageHeader header, AccessionDirec
/// Runs a single file (dicom or zip) through tag reading process
///
///
- public void RunSingleFile(FileInfo file)
+ public void RunSingleFile(IFileInfo file)
{
// tell reader only to consider our specific file
- _reader.IncludeFile = f => new FileInfo(f).FullName.Equals(file.FullName, StringComparison.CurrentCultureIgnoreCase);
+ _reader.IncludeFile = f => file.FileSystem.FileInfo.New(f).FullName.Equals(file.FullName, StringComparison.CurrentCultureIgnoreCase);
_reader.ReadTags(null, new AccessionDirectoryMessage(_opts.FileSystemOptions!.FileSystemRoot!, file.Directory!));
// good practice to clear this afterwards
diff --git a/src/SmiServices/Microservices/FileCopier/FileCopier.cs b/src/SmiServices/Microservices/FileCopier/FileCopier.cs
index 59c0a84ec..59f457069 100644
--- a/src/SmiServices/Microservices/FileCopier/FileCopier.cs
+++ b/src/SmiServices/Microservices/FileCopier/FileCopier.cs
@@ -1,6 +1,7 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.FileCopier
{
@@ -10,13 +11,14 @@ public static class FileCopier
/// Program entry point when run from the command line
///
///
- public static int Main(IEnumerable args)
+ ///
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(FileCopier), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(FileCopier), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, CliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, CliOptions opts)
{
var bootstrapper = new MicroserviceHostBootstrapper(() => new FileCopierHost(globals));
int ret = bootstrapper.Main();
diff --git a/src/SmiServices/Microservices/FileCopier/FileCopierHost.cs b/src/SmiServices/Microservices/FileCopier/FileCopierHost.cs
index c8f2fd3d0..a01697c10 100644
--- a/src/SmiServices/Microservices/FileCopier/FileCopierHost.cs
+++ b/src/SmiServices/Microservices/FileCopier/FileCopierHost.cs
@@ -15,7 +15,8 @@ public FileCopierHost(
IFileSystem? fileSystem = null
)
: base(
- options
+ options,
+ fileSystem ?? new FileSystem()
)
{
Logger.Debug("Creating FileCopierHost with FileSystemRoot: " + Globals.FileSystemOptions!.FileSystemRoot);
@@ -27,7 +28,7 @@ public FileCopierHost(
copyStatusProducerModel,
Globals.FileSystemOptions.FileSystemRoot!,
Globals.FileSystemOptions.ExtractRoot!,
- fileSystem
+ FileSystem
);
_consumer = new FileCopyQueueConsumer(fileCopier);
}
diff --git a/src/SmiServices/Microservices/IdentifierMapper/IdentifierMapper.cs b/src/SmiServices/Microservices/IdentifierMapper/IdentifierMapper.cs
index 022b01c1b..4372146af 100644
--- a/src/SmiServices/Microservices/IdentifierMapper/IdentifierMapper.cs
+++ b/src/SmiServices/Microservices/IdentifierMapper/IdentifierMapper.cs
@@ -1,18 +1,19 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.IdentifierMapper
{
public static class IdentifierMapper
{
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(IdentifierMapper), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(IdentifierMapper), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, CliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, CliOptions opts)
{
var bootstrapper = new MicroserviceHostBootstrapper(() => new IdentifierMapperHost(globals));
int ret = bootstrapper.Main();
diff --git a/src/SmiServices/Microservices/IdentifierMapper/IdentifierMapperHost.cs b/src/SmiServices/Microservices/IdentifierMapper/IdentifierMapperHost.cs
index 0530ca9d9..58f025898 100644
--- a/src/SmiServices/Microservices/IdentifierMapper/IdentifierMapperHost.cs
+++ b/src/SmiServices/Microservices/IdentifierMapper/IdentifierMapperHost.cs
@@ -7,6 +7,7 @@
using SmiServices.Microservices.IdentifierMapper.Swappers;
using StackExchange.Redis;
using System;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.IdentifierMapper
@@ -24,8 +25,8 @@ public class IdentifierMapperHost : MicroserviceHost
- public IdentifierMapperHost(GlobalOptions options, ISwapIdentifiers? swapper = null)
- : base(options)
+ public IdentifierMapperHost(GlobalOptions options, ISwapIdentifiers? swapper = null, IFileSystem? fileSystem = null)
+ : base(options, fileSystem ?? new FileSystem())
{
_consumerOptions = options.IdentifierMapperOptions!;
diff --git a/src/SmiServices/Microservices/IsIdentifiable/Classifier.cs b/src/SmiServices/Microservices/IsIdentifiable/Classifier.cs
index e7a1a81c5..83b7a2c48 100644
--- a/src/SmiServices/Microservices/IsIdentifiable/Classifier.cs
+++ b/src/SmiServices/Microservices/IsIdentifiable/Classifier.cs
@@ -9,10 +9,10 @@ namespace SmiServices.Microservices.IsIdentifiable
{
public abstract class Classifier : IClassifier
{
- public DirectoryInfo? DataDirectory { get; set; }
+ public IDirectoryInfo? DataDirectory { get; set; }
- protected Classifier(DirectoryInfo dataDirectory)
+ protected Classifier(IDirectoryInfo dataDirectory)
{
DataDirectory = dataDirectory;
@@ -27,7 +27,7 @@ protected Classifier(DirectoryInfo dataDirectory)
///
///
///
- protected DirectoryInfo GetSubdirectory(string toFind)
+ protected IDirectoryInfo GetSubdirectory(string toFind)
{
var stanfordNerDir = DataDirectory!.GetDirectories(toFind).SingleOrDefault() ?? throw new DirectoryNotFoundException($"Expected sub-directory called '{toFind}' to exist in '{DataDirectory}'");
return stanfordNerDir;
diff --git a/src/SmiServices/Microservices/IsIdentifiable/IClassifier.cs b/src/SmiServices/Microservices/IsIdentifiable/IClassifier.cs
index df3ee7ec8..de2c1c8eb 100644
--- a/src/SmiServices/Microservices/IsIdentifiable/IClassifier.cs
+++ b/src/SmiServices/Microservices/IsIdentifiable/IClassifier.cs
@@ -1,6 +1,5 @@
using IsIdentifiable.Failures;
using System.Collections.Generic;
-using System.IO;
using System.IO.Abstractions;
namespace SmiServices.Microservices.IsIdentifiable
@@ -10,7 +9,7 @@ public interface IClassifier
///
/// The location in which you can get your required data files
///
- DirectoryInfo? DataDirectory { get; set; }
+ IDirectoryInfo? DataDirectory { get; set; }
IEnumerable Classify(IFileInfo dcm);
}
diff --git a/src/SmiServices/Microservices/IsIdentifiable/IsIdentifiable.cs b/src/SmiServices/Microservices/IsIdentifiable/IsIdentifiable.cs
index 07db67bfd..4bb29ea23 100644
--- a/src/SmiServices/Microservices/IsIdentifiable/IsIdentifiable.cs
+++ b/src/SmiServices/Microservices/IsIdentifiable/IsIdentifiable.cs
@@ -1,18 +1,19 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.IsIdentifiable
{
public static class IsIdentifiable
{
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(IsIdentifiable), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(IsIdentifiable), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, CliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, CliOptions opts)
{
var bootstrapper = new MicroserviceHostBootstrapper(
() => new IsIdentifiableHost(globals));
diff --git a/src/SmiServices/Microservices/IsIdentifiable/IsIdentifiableHost.cs b/src/SmiServices/Microservices/IsIdentifiable/IsIdentifiableHost.cs
index 4b5ce59c3..5393093ba 100644
--- a/src/SmiServices/Microservices/IsIdentifiable/IsIdentifiableHost.cs
+++ b/src/SmiServices/Microservices/IsIdentifiable/IsIdentifiableHost.cs
@@ -3,7 +3,7 @@
using SmiServices.Common.Messaging;
using SmiServices.Common.Options;
using System;
-using System.IO;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.IsIdentifiable
{
@@ -15,9 +15,10 @@ public class IsIdentifiableHost : MicroserviceHost
private readonly IProducerModel _producerModel;
public IsIdentifiableHost(
- GlobalOptions globals
+ GlobalOptions globals,
+ IFileSystem? fileSystem = null
)
- : base(globals)
+ : base(globals, fileSystem ?? new FileSystem())
{
_consumerOptions = globals.IsIdentifiableServiceOptions ?? throw new ArgumentNullException(nameof(globals));
@@ -30,7 +31,7 @@ GlobalOptions globals
throw new ArgumentException("A DataDirectory must be set", nameof(globals));
var objectFactory = new MicroserviceObjectFactory();
- var classifier = objectFactory.CreateInstance(classifierTypename, typeof(IClassifier).Assembly, new DirectoryInfo(dataDirectory), globals.IsIdentifiableOptions!)
+ var classifier = objectFactory.CreateInstance(classifierTypename, typeof(IClassifier).Assembly, FileSystem.DirectoryInfo.New(dataDirectory), globals.IsIdentifiableOptions!)
?? throw new TypeLoadException($"Could not find IClassifier Type {classifierTypename}");
_producerModel = MessageBroker.SetupProducer(globals.IsIdentifiableServiceOptions.IsIdentifiableProducerOptions!, isBatch: false);
diff --git a/src/SmiServices/Microservices/IsIdentifiable/RejectAllClassifier.cs b/src/SmiServices/Microservices/IsIdentifiable/RejectAllClassifier.cs
index e2869e019..df7d3bd96 100644
--- a/src/SmiServices/Microservices/IsIdentifiable/RejectAllClassifier.cs
+++ b/src/SmiServices/Microservices/IsIdentifiable/RejectAllClassifier.cs
@@ -1,14 +1,13 @@
using IsIdentifiable.Failures;
using IsIdentifiable.Options;
using System.Collections.Generic;
-using System.IO;
using System.IO.Abstractions;
namespace SmiServices.Microservices.IsIdentifiable
{
public class RejectAllClassifier : Classifier
{
- public RejectAllClassifier(DirectoryInfo dataDirectory, IsIdentifiableDicomFileOptions _) : base(dataDirectory)
+ public RejectAllClassifier(IDirectoryInfo dataDirectory, IsIdentifiableDicomFileOptions _) : base(dataDirectory)
{
}
diff --git a/src/SmiServices/Microservices/IsIdentifiable/TesseractStanfordDicomFileClassifier.cs b/src/SmiServices/Microservices/IsIdentifiable/TesseractStanfordDicomFileClassifier.cs
index 35ebebe35..2242fcb17 100644
--- a/src/SmiServices/Microservices/IsIdentifiable/TesseractStanfordDicomFileClassifier.cs
+++ b/src/SmiServices/Microservices/IsIdentifiable/TesseractStanfordDicomFileClassifier.cs
@@ -4,7 +4,6 @@
using IsIdentifiable.Runners;
using System;
using System.Collections.Generic;
-using System.IO;
using System.IO.Abstractions;
namespace SmiServices.Microservices.IsIdentifiable
@@ -14,15 +13,15 @@ public class TesseractStanfordDicomFileClassifier : Classifier, IDisposable
private readonly DicomFileRunner _runner;
//public TesseractStanfordDicomFileClassifier(DirectoryInfo dataDirectory) : base(dataDirectory)
- public TesseractStanfordDicomFileClassifier(DirectoryInfo dataDirectory, IsIdentifiableDicomFileOptions fileOptions) : base(dataDirectory)
+ public TesseractStanfordDicomFileClassifier(IDirectoryInfo dataDirectory, IsIdentifiableDicomFileOptions fileOptions) : base(dataDirectory)
{
//need to pass this so that the runner doesn't get unhappy about there being no reports (even though we clear it below)
fileOptions.ColumnReport = true;
fileOptions.TessDirectory = dataDirectory.FullName;
// The Rules directory is always called "IsIdentifiableRules"
- DirectoryInfo[] subDirs = dataDirectory.GetDirectories("IsIdentifiableRules");
- foreach (DirectoryInfo subDir in subDirs)
+ var subDirs = dataDirectory.GetDirectories("IsIdentifiableRules");
+ foreach (var subDir in subDirs)
fileOptions.RulesDirectory = subDir.FullName;
_runner = new DicomFileRunner(fileOptions, new FileSystem());
diff --git a/src/SmiServices/Microservices/MongoDBPopulator/MongoDBPopulator.cs b/src/SmiServices/Microservices/MongoDBPopulator/MongoDBPopulator.cs
index 9c7f36f32..d76d4ad69 100644
--- a/src/SmiServices/Microservices/MongoDBPopulator/MongoDBPopulator.cs
+++ b/src/SmiServices/Microservices/MongoDBPopulator/MongoDBPopulator.cs
@@ -1,6 +1,7 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.MongoDBPopulator
{
@@ -9,13 +10,13 @@ public static class MongoDBPopulator
///
/// Program entry point when run from command line
///
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
- int ret = SmiCliInit.ParseAndRun(args, typeof(MongoDBPopulator), OnParse);
+ int ret = SmiCliInit.ParseAndRun(args, typeof(MongoDBPopulator), OnParse, fileSystem ?? new FileSystem());
return ret;
}
- private static int OnParse(GlobalOptions globals, CliOptions _)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, CliOptions _)
{
var bootstrapper = new MicroserviceHostBootstrapper(() => new MongoDbPopulatorHost(globals));
int ret = bootstrapper.Main();
diff --git a/src/SmiServices/Microservices/MongoDBPopulator/MongoDbPopulatorHost.cs b/src/SmiServices/Microservices/MongoDBPopulator/MongoDbPopulatorHost.cs
index ec9d1df58..a1e7e7fbb 100644
--- a/src/SmiServices/Microservices/MongoDBPopulator/MongoDbPopulatorHost.cs
+++ b/src/SmiServices/Microservices/MongoDBPopulator/MongoDbPopulatorHost.cs
@@ -3,6 +3,7 @@
using SmiServices.Common.Options;
using System;
using System.Collections.Generic;
+using System.IO.Abstractions;
using System.Linq;
namespace SmiServices.Microservices.MongoDBPopulator
@@ -15,8 +16,8 @@ public class MongoDbPopulatorHost : MicroserviceHost
public readonly List Consumers = [];
- public MongoDbPopulatorHost(GlobalOptions options)
- : base(options)
+ public MongoDbPopulatorHost(GlobalOptions options, IFileSystem? fileSystem = null)
+ : base(options, fileSystem ?? new FileSystem())
{
Consumers.Add(new MongoDbPopulatorMessageConsumer(options.MongoDatabases!.DicomStoreOptions!, options.MongoDbPopulatorOptions!, options.MongoDbPopulatorOptions!.SeriesQueueConsumerOptions!));
Consumers.Add(new MongoDbPopulatorMessageConsumer(options.MongoDatabases.DicomStoreOptions!, options.MongoDbPopulatorOptions, options.MongoDbPopulatorOptions.ImageQueueConsumerOptions!));
diff --git a/src/SmiServices/Microservices/UpdateValues/UpdateValues.cs b/src/SmiServices/Microservices/UpdateValues/UpdateValues.cs
index b57746e49..107c069da 100644
--- a/src/SmiServices/Microservices/UpdateValues/UpdateValues.cs
+++ b/src/SmiServices/Microservices/UpdateValues/UpdateValues.cs
@@ -1,23 +1,25 @@
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
using System.Collections.Generic;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.UpdateValues
{
public static class UpdateValues
{
- public static int Main(IEnumerable args)
+ public static int Main(IEnumerable args, IFileSystem? fileSystem = null)
{
return SmiCliInit
.ParseAndRun(
args,
typeof(UpdateValues),
- OnParse
+ OnParse,
+ fileSystem ?? new FileSystem()
);
}
- private static int OnParse(GlobalOptions globals, UpdateValuesCliOptions opts)
+ private static int OnParse(GlobalOptions globals, IFileSystem fileSystem, UpdateValuesCliOptions opts)
{
var bootstrapper = new MicroserviceHostBootstrapper(() => new UpdateValuesHost(globals));
int ret = bootstrapper.Main();
diff --git a/src/SmiServices/Microservices/UpdateValues/UpdateValuesHost.cs b/src/SmiServices/Microservices/UpdateValues/UpdateValuesHost.cs
index 559765927..3183dca0a 100644
--- a/src/SmiServices/Microservices/UpdateValues/UpdateValuesHost.cs
+++ b/src/SmiServices/Microservices/UpdateValues/UpdateValuesHost.cs
@@ -2,6 +2,7 @@
using SmiServices.Common;
using SmiServices.Common.Execution;
using SmiServices.Common.Options;
+using System.IO.Abstractions;
namespace SmiServices.Microservices.UpdateValues
{
@@ -9,8 +10,8 @@ public class UpdateValuesHost : MicroserviceHost
{
public UpdateValuesQueueConsumer? Consumer { get; set; }
- public UpdateValuesHost(GlobalOptions globals, IMessageBroker? messageBroker = null, bool threaded = false)
- : base(globals, messageBroker, threaded)
+ public UpdateValuesHost(GlobalOptions globals, IFileSystem? fileSystem = null, IMessageBroker? messageBroker = null, bool threaded = false)
+ : base(globals, fileSystem ?? new FileSystem(), messageBroker, threaded)
{
FansiImplementations.Load();
}
diff --git a/src/SmiServices/SmiServices.csproj b/src/SmiServices/SmiServices.csproj
index 56c7ac171..3217547c9 100644
--- a/src/SmiServices/SmiServices.csproj
+++ b/src/SmiServices/SmiServices.csproj
@@ -24,7 +24,8 @@
-
+
+
diff --git a/tests/SmiServices.IntegrationTests/SmiServices.IntegrationTests.csproj b/tests/SmiServices.IntegrationTests/SmiServices.IntegrationTests.csproj
index bbdeff3b6..ab7439191 100644
--- a/tests/SmiServices.IntegrationTests/SmiServices.IntegrationTests.csproj
+++ b/tests/SmiServices.IntegrationTests/SmiServices.IntegrationTests.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/tests/SmiServices.UnitTests/SmiServices.UnitTests.csproj b/tests/SmiServices.UnitTests/SmiServices.UnitTests.csproj
index 31de220f2..a2b320fef 100644
--- a/tests/SmiServices.UnitTests/SmiServices.UnitTests.csproj
+++ b/tests/SmiServices.UnitTests/SmiServices.UnitTests.csproj
@@ -5,7 +5,7 @@
-
+