Jelajahi Sumber

PsQueue - add tests

Dalibor Votruba 1 tahun lalu
induk
melakukan
c3553ac484

+ 25 - 0
qdr.fnd.core.pqueue.test/Process/Mock/PsProcessProviderBaseMock.cs

@@ -6,10 +6,35 @@ namespace qdr.fnd.core.pqueue.test.Process.Mock
 {
     internal class PsProcessProviderBaseMock : PsProcessProviderBase
     {
+        public const string CS_ARG_EMIT_EXC = "emmit-exception";
+
         public PsProcessProviderBaseMock(ProcessDoneCallback processDoneCallback, ProcessStdOutputCallback processStdOutputCallback, string itemId, TypedArgument[] arguments, ILogger logger) : base(processDoneCallback, processStdOutputCallback, itemId, arguments, logger)
         {
         }
 
+        public new static TypedArgument[] CreateArguments()
+        {
+            var list = new List<TypedArgument>(PsProcessProviderBase.CreateArguments());
+            list.Add(new TypedArgument(CS_ARG_EMIT_EXC, typeof(string), false));
+            return list.ToArray();
+        }
+
+        protected override async Task OnProcess()
+        {
+            if (ContainsArgument(CS_ARG_EMIT_EXC) && !string.IsNullOrEmpty(GetArgumentValue<string>(CS_ARG_EMIT_EXC)))
+            {
+                var message = GetArgumentValue<string>(CS_ARG_EMIT_EXC);
+                Log.Log(LogSeverityEnum.Info, $"Emmiting exception '{message}'");
+                throw new Exception("Test exception");
+            }
+            else
+            {
+                Log.Log(LogSeverityEnum.Info, $"Nothing to emitte");
+            }
+            Task.Delay(3000).Wait();
+            await base.OnProcess();
+        }
+
         public void TestOnProcessError(Exception exception)
         {
             var task = base.OnProcessError(exception);

+ 36 - 0
qdr.fnd.core.pqueue.test/Process/PsProcessProviderBaseTest.cs

@@ -1,10 +1,12 @@
 using Newtonsoft.Json.Linq;
 using NUnit.Framework.Interfaces;
 using qdr.fnd.core.pqueue.Enums;
+using qdr.fnd.core.pqueue.fnd.candidates;
 using qdr.fnd.core.pqueue.Process;
 using qdr.fnd.core.pqueue.test.Mocks;
 using qdr.fnd.core.pqueue.test.Process.Mock;
 using Quadarax.Foundation.Core.Data;
+using Quadarax.Foundation.Core.Value.Extensions;
 using System.Collections.Concurrent;
 
 namespace qdr.fnd.core.pqueue.test.Process
@@ -102,6 +104,40 @@ namespace qdr.fnd.core.pqueue.test.Process
             Assert.Throws<ArgumentNullException>(() => process.TestContainsArgument(null!));
         }
 
+        [Test(TestOf=typeof(PsProcessProviderBase))]
+        public void StartOk()
+        {
+            var args = PsProcessProviderBaseMock.CreateArguments().ToArray();
+            args.SetArgumentValue<TimeSpan>(PsProcessProviderBase.CS_ARG_PROCESS_TIMEOUT, TimeSpan.FromSeconds(5));
+
+            var process = CreateProcess(args);
+            var dtStart = DateTime.Now;
+            process.Start();
+            process.WaitToDone();
+            TestContext.WriteLine($"#Process duration check: {(DateTime.Now - dtStart).ToReadableString()}");
+
+            Assert.That(process.IsRunning, Is.False);
+            Assert.That(_statusDonePool.ContainsKey(process.ItemId), Is.True);
+            Assert.That(_statusDonePool[process.ItemId].Any(x => x.Item1 == PsStatusEnum.DoneOk), Is.True);
+        }
+
+        [Test(TestOf=typeof(PsProcessProviderBase))]
+        public void StartTimeoutFail()
+        {
+            var args = PsProcessProviderBaseMock.CreateArguments().ToArray();
+            args.SetArgumentValue<TimeSpan>(PsProcessProviderBase.CS_ARG_PROCESS_TIMEOUT, TimeSpan.FromSeconds(1));
+
+            var process = CreateProcess(args);
+            var dtStart = DateTime.Now;
+            process.Start();
+            process.WaitToDone();
+            TestContext.WriteLine($"#Process duration check: {(DateTime.Now - dtStart).ToReadableString()}");
+
+            Assert.That(process.IsRunning, Is.False);
+            Assert.That(_statusDonePool.ContainsKey(process.ItemId), Is.True);
+            Assert.That(_statusDonePool[process.ItemId].Any(x => x.Item1 == PsStatusEnum.DoneOk), Is.True);
+        }
+
         private PsProcessProviderBaseMock CreateProcess(TypedArgument[] args)
         {
             var itemId = "a";

+ 88 - 0
qdr.fnd.core.pqueue.test/fnd.candidates/TypedArgumentExtTest.cs

@@ -0,0 +1,88 @@
+using qdr.fnd.core.pqueue.fnd.candidates;
+using Quadarax.Foundation.Core.Data;
+
+namespace qdr.fnd.core.pqueue.test.fnd.candidates
+{
+    public class TypedArgumentExtTest
+    {
+
+        private TypedArgument[] _args;
+
+        [SetUp]
+        public void Setup()
+        {
+            _args = new TypedArgument[]
+            {
+                new TypedArgument("a", "1", typeof(int)),
+                new TypedArgument("b", "2", typeof(int)),
+                new TypedArgument("c", "3", typeof(int)),
+                new TypedArgument("d", null, typeof(int)),
+            };
+        }
+
+        [Test(TestOf=typeof(TypedArgumentExt))]
+        public void GetArgumentValueOk()
+        {
+            var value = _args.GetArgumentValue<int>("a");
+            Assert.That(value, Is.EqualTo(1));
+        }
+
+        [Test(TestOf=typeof(TypedArgumentExt))]
+        public void GetArgumentValueFail()
+        {
+            Assert.Throws<ArgumentNullException>(()=>_args.GetArgumentValue<int>(null!));
+            Assert.Throws<ArgumentNullException>(()=>_args.GetArgumentValue<int>(string.Empty));
+            Assert.Throws<ArgumentOutOfRangeException>(()=>_args.GetArgumentValue<int>("x"));
+            Assert.Throws<NotSupportedException>(()=>_args.GetArgumentValue<DateTime>("a"));
+        }
+
+        [Test(TestOf=typeof(TypedArgumentExt))]
+        public void SetArgumentValueOk()
+        {
+            var value = 33;
+            _args.SetArgumentValue<int>("a", value);
+            Assert.That(value, Is.EqualTo(_args.First(x=>x.Name=="a").GetTypedValue<int>()));
+
+            int? value2 = null;
+            _args.SetArgumentValue<int?>("a", value2);
+            Assert.That(_args.First(x=>x.Name=="a").GetTypedValue<int?>(), Is.Null);
+        }
+
+        [Test(TestOf=typeof(TypedArgumentExt))]
+        public void SetArgumentValueFail()
+        {
+            Assert.Throws<ArgumentOutOfRangeException>(()=>_args.SetArgumentValue<int>("x", 0));
+            Assert.Throws<ArgumentOutOfRangeException>(()=>_args.SetArgumentValue<DateTime>("a", DateTime.Now));
+        }
+
+
+        [Test(TestOf=typeof(TypedArgumentExt))]
+        public void GetArgumentOk()
+        {
+            var arg = _args.GetArgument("a");
+            Assert.That(arg.Name, Is.EqualTo(_args.First(x=>x.Name == "a").Name));
+        }
+
+        [Test(TestOf=typeof(TypedArgumentExt))]
+        public void GetArgumentFail()
+        {
+            Assert.Throws<ArgumentNullException>(()=>_args.GetArgument(null!));
+            Assert.Throws<ArgumentNullException>(()=>_args.GetArgument(string.Empty));
+            Assert.Throws<ArgumentOutOfRangeException>(()=>_args.GetArgument("x"));
+        }
+
+        [Test(TestOf=typeof(TypedArgumentExt))]
+        public void ContainsArgumentOk()
+        {
+            Assert.That(_args.ContainsArgument("a"), Is.True);
+            Assert.That(_args.ContainsArgument("x"), Is.False);
+        }
+
+        [Test(TestOf=typeof(TypedArgumentExt))]
+        public void ContainsArgumentFail()
+        {
+            Assert.Throws<ArgumentNullException>(()=>_args.ContainsArgument(null!));
+            Assert.Throws<ArgumentNullException>(()=>_args.ContainsArgument(string.Empty));
+        }
+    }
+}

+ 12 - 0
qdr.fnd.core.pqueue/Extensions/PsProcessProviderExt.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace qdr.fnd.core.pqueue.Extensions
+{
+    public static class PsProcessProviderExt
+    {
+    }
+}

+ 5 - 0
qdr.fnd.core.pqueue/Process/IPsProcessProvider.cs

@@ -32,5 +32,10 @@ namespace qdr.fnd.core.pqueue.Process
         /// </summary>
         void Stop();
 
+        /// <summary>
+        /// Waits till <see cref="IsRunning"/> is false."/>
+        /// </summary>
+        void WaitToDone();
+
     }
 }

+ 14 - 2
qdr.fnd.core.pqueue/Process/PsProcessProviderBase.cs

@@ -72,7 +72,8 @@ namespace qdr.fnd.core.pqueue.Process
             Validate();
             IsRunning = true;
             var timeout = GetArgumentValue<TimeSpan>(CS_ARG_PROCESS_TIMEOUT);
-            Task.Factory.StartNew(()=>StartInternal(timeout), _cancelationToken!.Token);
+
+            Task.Factory.StartNew(()=>StartInternal(timeout).TimeoutAfter(timeout), _cancelationToken!.Token);
         }
 
         /// <inheritdoc />
@@ -99,6 +100,16 @@ namespace qdr.fnd.core.pqueue.Process
             };
             return list;
         }
+
+        /// <inheritdoc />
+        public void WaitToDone()
+        {
+            while(IsRunning)
+            {
+                Task.Delay(100).Wait();
+            };
+            Log.Log(LogSeverityEnum.Debug, $"Provider for ItemId='{ItemId}' detect that process finished.");
+        }
         #endregion
 
 
@@ -159,7 +170,8 @@ namespace qdr.fnd.core.pqueue.Process
             var dtStart = DateTime.Now;
             try
             {
-                await OnProcess().TimeoutAfter(timeout).ContinueWith(task =>
+                Log.Log(LogSeverityEnum.Debug, $"Provider for ItemId='{ItemId}' has general timeout for execution {timeout.ToReadableString()}.");
+                await OnProcess().ContinueWith(task =>
                 {
                     Log.Log(LogSeverityEnum.Info, $"Provider for ItemId='{ItemId}' done. Duration {(DateTime.Now - dtStart).ToReadableString()}.");
                     if (ProcessDoneCallback != null)

+ 39 - 0
qdr.fnd.core.pqueue/fnd.candidates/TypedArgumentExt.cs

@@ -0,0 +1,39 @@
+using Quadarax.Foundation.Core.Data;
+
+namespace qdr.fnd.core.pqueue.fnd.candidates
+{
+    public static class TypedArgumentExt
+    {
+        public static TValue? GetArgumentValue<TValue>(this IEnumerable<TypedArgument> args, string argumentName)
+        {
+            var arg = GetArgument(args, argumentName);
+            return arg.GetTypedValue<TValue>();
+        }
+
+        public static void SetArgumentValue<TValue>(this IEnumerable<TypedArgument> args, string argumentName, TValue? value)
+        {
+            var arg = GetArgument(args, argumentName);
+            if (value!=null && value.GetType().Name != arg.ValueType.Name)
+                throw new ArgumentOutOfRangeException(nameof(value), value, $"Value type '{value.GetType().Name}' is not equal to argument type '{arg.ValueType.Name}'.");
+            arg.Value = value == null ? null : value.ToString();
+        }
+
+        public static TypedArgument GetArgument(this IEnumerable<TypedArgument> args, string argumentName)
+        {
+            if (args == null) throw new ArgumentNullException(nameof(args));
+            if (string.IsNullOrWhiteSpace(argumentName)) throw new ArgumentNullException(nameof(argumentName));
+
+            if (!args.ContainsArgument(argumentName)) throw new ArgumentOutOfRangeException(nameof(argumentName),argumentName,$"Argument named '{argumentName}' is not in argument collection.");
+
+            return args.First(a => a.Name == argumentName);
+        }
+
+        public static bool ContainsArgument(this IEnumerable<TypedArgument> args, string argumentName)
+        {
+            if (args == null) throw new ArgumentNullException(nameof(args));
+            if (string.IsNullOrWhiteSpace(argumentName)) throw new ArgumentNullException(nameof(argumentName));
+
+            return args.Any(a => a.Name == argumentName);
+        }
+    }
+}