commit 0932a9e214cb251a9e986c9fcaea8d14354ce5b8
Author: Pultak <pultak5@gmail.com>
Date:   Mon Apr 25 22:36:16 2022 +0200

    re #9443 refactoring of detection classes

diff --git a/ld_client/LDClient/detection/DebuggerInfoParser.cs b/ld_client/LDClient/detection/DebuggerInfoParser.cs
index 3f07e32..dec8bd0 100644
--- a/ld_client/LDClient/detection/DebuggerInfoParser.cs
+++ b/ld_client/LDClient/detection/DebuggerInfoParser.cs
@@ -15,7 +15,7 @@ namespace LDClient.detection {
                 throw new ArgumentException($"Expected {ExpectedNumberOfMatches} matches to be found in the text (actually found: {matches.Count})");
             }
             
-            return (matches[0].ToString(), matches[1].ToString());
+            return (matches[1].ToString().Trim(), matches[0].ToString().Trim());
         }
     }
 }
\ No newline at end of file
diff --git a/ld_client/LDClient/detection/IInfoFetcher.cs b/ld_client/LDClient/detection/IInfoFetcher.cs
new file mode 100644
index 0000000..e48005c
--- /dev/null
+++ b/ld_client/LDClient/detection/IInfoFetcher.cs
@@ -0,0 +1,15 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LDClient.detection {
+    public interface IInfoFetcher {
+
+        public string HeadSerialNumber { get; set; }
+        public string BodySerialNumber { get; set; }
+
+        public Task<bool> FetchDataAsync();
+    }
+}
diff --git a/ld_client/LDClient/detection/IProcessUtils.cs b/ld_client/LDClient/detection/IProcessUtils.cs
new file mode 100644
index 0000000..b900375
--- /dev/null
+++ b/ld_client/LDClient/detection/IProcessUtils.cs
@@ -0,0 +1,13 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LDClient.detection {
+    public interface IProcessUtils {
+        public bool IsProcessRunning(string name);
+
+        public bool ExecuteNewProcess(string fileName, string argument, int timeout, int desiredExitCode);
+    }
+}
diff --git a/ld_client/LDClient/detection/InfoFetcher.cs b/ld_client/LDClient/detection/InfoFetcher.cs
index 0d2a206..07ddba1 100644
--- a/ld_client/LDClient/detection/InfoFetcher.cs
+++ b/ld_client/LDClient/detection/InfoFetcher.cs
@@ -1,9 +1,10 @@
 using System.Diagnostics;
+using LDClient.utils;
 using LDClient.utils.loggers;
 
 namespace LDClient.detection {
 
-    public class InfoFetcher {
+    public class InfoFetcher : IInfoFetcher {
         
         private const string UndefinedSerialNumber = "number";
 
@@ -15,10 +16,15 @@ namespace LDClient.detection {
         private readonly uint _waitPeriodMs;
         private readonly string _infoFilePath;
 
-        public string HeadSerialNumber { get; private set; } = UndefinedSerialNumber;
-        public string BodySerialNumber { get; private set; } = UndefinedSerialNumber;
+        public IProcessUtils ProcessUtils;
+        public IFileUtils FileUtils;
 
-        public InfoFetcher(uint maxAttempts, uint waitPeriodMs, string infoFilePath, string f32RemExecutable, string[] f32RemArguments, int f32SuccessExitCode, int f32WaitTimeoutMs) {
+        public string HeadSerialNumber { get; set; } = UndefinedSerialNumber;
+        public string BodySerialNumber { get; set; } = UndefinedSerialNumber;
+
+
+        public InfoFetcher(uint maxAttempts, uint waitPeriodMs, string infoFilePath, string f32RemExecutable,
+            string[] f32RemArguments, int f32SuccessExitCode, int f32WaitTimeoutMs) {
             _maxAttempts = maxAttempts;
             _waitPeriodMs = waitPeriodMs;
             _infoFilePath = infoFilePath;
@@ -26,6 +32,9 @@ namespace LDClient.detection {
             _f32RemArguments = f32RemArguments;
             _f32SuccessExitCode = f32SuccessExitCode;
             _f32WaitTimeoutMs = f32WaitTimeoutMs;
+            ProcessUtils = new ProcessUtils();
+            FileUtils = new FileUtils();
+
         }
 
         public async Task<bool> FetchDataAsync() {
@@ -49,7 +58,7 @@ namespace LDClient.detection {
 
         private bool RetrieveDebuggerInfo(string filePath) {
             try {
-                var fileContent = File.ReadAllLines(filePath).Aggregate("", (current, line) => $"{current}{line}\n");
+                var fileContent = FileUtils.ReadFileAllLines(filePath).Aggregate("", (current, line) => $"{current}{line}\n");
                 var (headSerialNumber, bodySerialNumber) = DebuggerInfoParser.Parse(fileContent);
                 HeadSerialNumber = headSerialNumber;
                 BodySerialNumber = bodySerialNumber;
@@ -61,27 +70,13 @@ namespace LDClient.detection {
             return true;
         }
 
-        private static bool SendRetrieveInfoCommands(string executableFile, IReadOnlyList<string>? arguments, int successExitCode, int waitTimeoutMs) {
+        private bool SendRetrieveInfoCommands(string executableFile, IReadOnlyList<string>? arguments, int desiredExitCode, int waitTimeoutMs) {
             if (arguments == null) {
                 Program.DefaultLogger.Error($"Failed to run {executableFile} - no parameters were given");
                 return false;
             }
             foreach (var argument in arguments) {
-                var t32RemProcess = new Process();
-                t32RemProcess.StartInfo.FileName = executableFile;
-                t32RemProcess.StartInfo.Arguments = argument;
-                try {
-                    t32RemProcess.Start();
-                    if (!t32RemProcess.WaitForExit(waitTimeoutMs)) {
-                        Program.DefaultLogger.Error($"Execution has not terminated within a predefined timeout of {waitTimeoutMs} ms");
-                        return false;
-                    }
-                    if (t32RemProcess.ExitCode != successExitCode) {
-                        Program.DefaultLogger.Error($"Execution terminated with an error code of {t32RemProcess.ExitCode}");
-                        return false;
-                    }
-                } catch (Exception exception) {
-                    Program.DefaultLogger.Error($"Failed to run {executableFile} {argument}. {exception.Message}");
+                if (!ProcessUtils.ExecuteNewProcess(executableFile, argument, waitTimeoutMs, desiredExitCode)) {
                     return false;
                 }
             }
diff --git a/ld_client/LDClient/detection/ProcessDetection.cs b/ld_client/LDClient/detection/ProcessDetection.cs
index fb68c65..27d5333 100644
--- a/ld_client/LDClient/detection/ProcessDetection.cs
+++ b/ld_client/LDClient/detection/ProcessDetection.cs
@@ -4,25 +4,29 @@ using LDClient.network.data;
 
 namespace LDClient.detection {
    
-	 public sealed class ProcessProcessDetection : IProcessDetection {
+	 public sealed class ProcessDetection : IProcessDetection {
         
         private const string DatetimeFormat = "yyyy-MM-dd hh:mm:ss";
 
         private readonly string _processName;
         private readonly uint _detectionPeriodMs;
-        private readonly InfoFetcher _infoFetcher;
+        private readonly IInfoFetcher _infoFetcher;
         private readonly IApiClient _apiClient;
-        
+        private readonly IProcessUtils _processUtils;
+
         private bool _processIsActive;
         private bool _failedToRetrieveData;
         private Payload? _lastConnectedPayload;
 
-        public ProcessProcessDetection(string processName, uint detectionPeriodMs, InfoFetcher infoFetcher, IApiClient apiClient) {
+        public bool DetectionRunning = false;
+
+        public ProcessDetection(string processName, uint detectionPeriodMs, IInfoFetcher infoFetcher, IApiClient apiClient, IProcessUtils processUtils) {
             _processName = processName;
             _detectionPeriodMs = detectionPeriodMs;
             _infoFetcher = infoFetcher;
             _apiClient = apiClient;
             _failedToRetrieveData = false;
+            _processUtils = processUtils;
         }
 
         private async Task<bool> RetrieveDataFromDebugger() {
@@ -43,7 +47,7 @@ namespace LDClient.detection {
         }
 
         private async Task DetectProcessAsync() {
-            var processExists = Process.GetProcessesByName(_processName).Length > 0;
+            var processExists = _processUtils.IsProcessRunning(_processName);
 
             if (processExists && !_processIsActive) {
                 Program.DefaultLogger.Info($"Process started: {_processName}");
@@ -77,11 +81,11 @@ namespace LDClient.detection {
         
         public async void RunPeriodicDetection() {
             Program.DefaultLogger.Info("Process periodic detector has started");
-            while (true) {
+            DetectionRunning = true;
+            while (DetectionRunning) {
                 await DetectProcessAsync();
                 Thread.Sleep((int)_detectionPeriodMs);
             }
-            // ReSharper disable once FunctionNeverReturns
         }
     }
 }
diff --git a/ld_client/LDClient/detection/ProcessUtils.cs b/ld_client/LDClient/detection/ProcessUtils.cs
new file mode 100644
index 0000000..b707f66
--- /dev/null
+++ b/ld_client/LDClient/detection/ProcessUtils.cs
@@ -0,0 +1,40 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LDClient.detection {
+    public class ProcessUtils : IProcessUtils{
+
+        public bool IsProcessRunning(string name) {
+            return Process.GetProcessesByName(name).Length > 0;
+        }
+
+
+        public bool ExecuteNewProcess(string fileName, string argument, int timeout, int desiredExitCode) {
+
+            var t32RemProcess = new Process();
+            t32RemProcess.StartInfo.FileName = fileName;
+            t32RemProcess.StartInfo.Arguments = argument;
+            try {
+                t32RemProcess.Start();
+                if (!t32RemProcess.WaitForExit(timeout)) {
+                    Program.DefaultLogger.Error($"Execution has not terminated within a predefined timeout of {timeout} ms");
+                    return false;
+                }
+                if (t32RemProcess.ExitCode != desiredExitCode) {
+                    Program.DefaultLogger.Error($"Execution terminated with an error code of {t32RemProcess.ExitCode}");
+                    return false;
+                }
+            } catch (Exception exception) {
+                Program.DefaultLogger.Error($"Failed to run {fileName} {argument}. {exception.Message}");
+                return false;
+            }
+
+            return true;
+        }
+
+    }
+}
