/Flower.Processing.Tests/ProcessBuilderTests.cs
http://flower.codeplex.com · C# · 1535 lines · 1402 code · 118 blank · 15 comment · 19 complexity · ae7023b4f24a66df756d41a420e97d35 MD5 · raw file
- /*
- Copyright 2012 Dmitry Bratus
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.Serialization;
- using System.Text;
- using System.Threading;
- using Flower.Client;
- using Flower.Directory.Host.Default;
- using Flower.Directory.Management;
- using Flower.Logging;
- using Flower.Services;
- using Flower.Services.Data;
- using Flower.Testing;
- using NUnit.Framework;
- using Flower.Workflow;
- using Flower.Processing.Interruptions;
- using SortOrder = Flower.Workflow.SortOrder;
- using Flower.Directory.Util;
- using Flower.Directory.Host;
- using Spring.Context.Support;
- using Spring.Context;
- using System.Threading.Tasks;
-
- #pragma warning disable 0649
-
- namespace Flower.Processing.Tests
- {
- [TestFixture]
- public class ProcessBuilderTests
- {
- private static readonly Log Log = LogManager.CreateLog(typeof(ProcessBuilderTests).Name);
- private IApplicationContext _appContext;
-
- private const int POS1 = 1;
- private const int POS2 = 1 << 1;
- private const int POS3 = 1 << 2;
- private const int POS4 = 1 << 3;
- private const int POS5 = 1 << 4;
- private const int POS6 = 1 << 5;
- private const int POS7 = 1 << 6;
- private const int POS8 = 1 << 7;
- private const int POS9 = 1 << 8;
- private const int POS10 = 1 << 9;
-
- #region Setup
-
- public IDirectory CreateDirectory()
- {
- var dir = (IDirectory)_appContext.GetObject("directory");
-
- return dir;
- }
-
- private class Service
- {
- public int ReturnOne() { return 1; }
- }
-
- private IFlowerClient _flowerClient;
-
- [TestFixtureSetUp]
- public void Setup()
- {
- _appContext = new XmlApplicationContext("Flower.Directory.Host.config");
-
- _flowerClient = new FlowerClient(CreateDirectory());
- }
-
- [TestFixtureTearDown]
- public void TearDown()
- {
- _flowerClient.Dispose();
- }
-
- #endregion
-
- #region If
-
- [DataContract]
- private class IfProcess : Workflow.Process, IProcessDefinition
- {
- public bool Cond;
-
- public int Pos1;
- public int Pos2;
- public int Pos3;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { Pos1 = POS1; })
-
- .If(_ => Cond)
- .Exec(_ => { Pos2 = POS2; })
- .End()
-
- .Exec(_ => { Pos3 = POS3; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void If()
- {
- var prc = new Processor("Test", _flowerClient);
-
- var proc = new IfProcess { Cond = false };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3) == (POS1 | POS3));
-
- proc = new IfProcess { Cond = true };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3) == (POS1 | POS2 | POS3));
- }
-
- [DataContract]
- private class IfElseProcess : Workflow.Process, IProcessDefinition
- {
- public bool Cond;
-
- public int Pos1;
- public int Pos2;
- public int Pos3;
- public int Pos4;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { Pos1 = POS1; })
-
- .If(_ => Cond)
- .Exec(_ => { Pos2 = POS2; })
- .Else()
- .Exec(_ => { Pos3 = POS3; })
- .End()
-
- .Exec(_ => { Pos4 = POS4; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void IfElse()
- {
- var prc = new Processor("Test", _flowerClient);
-
- var proc = new IfElseProcess { Cond = false };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3 | proc.Pos4) == (POS1 | POS3 | POS4));
-
- proc = new IfElseProcess { Cond = true };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3 | proc.Pos4) == (POS1 | POS2 | POS4));
- }
-
- [DataContract]
- private class IfElseIfElseProcess : Workflow.Process, IProcessDefinition
- {
- public bool Cond1;
- public bool Cond2;
-
- public int Pos1;
- public int Pos2;
- public int Pos3;
- public int Pos4;
- public int Pos5;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { Pos1 = POS1; })
-
- .If(_ => Cond1)
- .Exec(_ => { Pos2 = POS2; })
- .ElseIf(_ => Cond2)
- .Exec(_ => { Pos3 = POS3; })
- .Else()
- .Exec(_ => { Pos4 = POS4; })
- .End()
-
- .Exec(_ => { Pos5 = POS5; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void IfElseIfElse()
- {
- var prc = new Processor("Test", _flowerClient);
-
- var proc = new IfElseIfElseProcess { Cond1 = false, Cond2 = false };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3 | proc.Pos4 | proc.Pos5) == (POS1 | POS4 | POS5));
-
- proc = new IfElseIfElseProcess { Cond1 = false, Cond2 = true };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3 | proc.Pos4 | proc.Pos5) == (POS1 | POS3 | POS5));
-
- proc = new IfElseIfElseProcess { Cond1 = true, Cond2 = false };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3 | proc.Pos4 | proc.Pos5) == (POS1 | POS2 | POS5));
-
- proc = new IfElseIfElseProcess { Cond1 = true, Cond2 = true };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3 | proc.Pos4 | proc.Pos5) == (POS1 | POS2 | POS5));
- }
- #endregion
-
- #region While
-
- [DataContract]
- private class WhileProcess : Workflow.Process, IProcessDefinition
- {
- public int Iterations;
-
- public int Cnt;
- public int Pos1;
- public int Pos2;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { Pos1 = POS1; })
-
- .While(_ => Cnt < Iterations)
- .Exec(_ => { Cnt++; })
- .End()
-
- .Exec(_ => { Pos2 = POS2; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void While()
- {
- var prc = new Processor("Test", _flowerClient);
-
- var proc = new WhileProcess { Iterations = 3 };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue(proc.Cnt == proc.Iterations);
- Assert.IsTrue((proc.Pos1 | proc.Pos2) == (POS1 | POS2));
- }
-
- [DataContract]
- private class WhileContinueBreakProcess : Workflow.Process, IProcessDefinition
- {
- public int Iterations;
-
- public int Cnt;
- public int Pos1;
- public int Pos2;
- public int Pos3;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { Pos1 = POS1; })
-
- .While(_ => true)
- .If(_ => Cnt == Iterations)
- .Break()
- .Else()
- .Exec(_ => { Cnt++; })
- .Continue()
- .Exec(_ => { Pos2 = POS2; })
- .End()
- .End()
-
- .Exec(_ => { Pos3 = POS3; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void WhileContinueBreak()
- {
- var prc = new Processor("Test", _flowerClient);
-
- var proc = new WhileContinueBreakProcess { Iterations = 3 };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue(proc.Cnt == proc.Iterations);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3) == (POS1 | POS3));
- }
-
- #endregion
-
- #region For
-
- [DataContract]
- private class ForProcess : Workflow.Process, IProcessDefinition
- {
- public int Iterations;
-
- public int Pos1;
- public int Pos2;
- public int Pos3;
-
- public int I;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { Pos1 = POS1; })
-
- .For(_ => { I = 0; }, _ => I < Iterations, _ => { I++; })
- .Exec(_ => { Pos2 = POS2; })
- .End()
-
- .Exec(_ => { Pos3 = POS3; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void For()
- {
- var prc = new Processor("Test", _flowerClient);
-
- var proc = new ForProcess { Iterations = 3 };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue(proc.I == proc.Iterations);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3) == (POS1 | POS2 | POS3));
- }
-
- [DataContract]
- private class ForBreakContinueProcess : Workflow.Process, IProcessDefinition
- {
- public int Iterations;
-
- public int Cnt;
- public int Pos1;
- public int Pos2;
- public int Pos3;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { Pos1 = POS1; })
-
- .For(_ => { }, _ => true, _ => { })
- .If(_ => Cnt == Iterations)
- .Break()
- .Else()
- .Exec(_ => { Cnt++; })
- .Continue()
- .Exec(_ => { Pos2 = POS2; })
- .End()
- .End()
-
- .Exec(_ => { Pos3 = POS3; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void ForContinueBreak()
- {
- var prc = new Processor("Test", _flowerClient);
-
- var proc = new ForBreakContinueProcess { Iterations = 3 };
- prc.Init("PID", proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue(proc.Cnt == proc.Iterations);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3) == (POS1 | POS3));
- }
-
- #endregion
-
- #region Try Catch
-
- [DataContract]
- private class TryCatchProcess : Workflow.Process, IProcessDefinition
- {
- public int passed;
-
- private readonly Exception _exception;
-
- public TryCatchProcess(Exception exception)
- {
- _exception = exception;
- }
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { passed = 0; })
- .Exec(_ => { passed |= POS1; })
-
- .Try()
- .Exec(_ => { passed |= POS2; })
-
- .If(_ => _exception != null)
- .Throw(_ => _exception)
- .End()
- .Catch<InvalidOperationException>((ctx, ex) => {})
- .Exec(_ => { passed |= POS3; })
- .Catch<ArgumentException>((ctx, ex) => { })
- .Exec(_ => { passed |= POS4; })
- .Catch<Exception>((ctx, ex) => { })
- .Exec(_ => { passed |= POS5; })
- .Finally()
- .Exec(_ => { passed |= POS6; })
- .End()
-
- .Exec(_ => { passed |= POS7; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void TryCatch()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Processors")
- .Processor("Proc1", (string)null)
- .Folder("Running")
- .Process
- (
- typeof(TryCatchProcess).AssemblyQualifiedName,
- out pid
- ).End()
- .End()
- .Folder("Pending").End()
- .Folder("Suspended").End()
- .End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var prc = new Processor("Test", cli);
- var proc = new TryCatchProcess(null);
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.AreEqual
- (
- POS1 |
- POS2 |
- POS6 |
- POS7,
- proc.passed
- );
-
- prc = new Processor("Test", cli);
- proc = new TryCatchProcess(new InvalidOperationException());
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.AreEqual
- (
- POS1 |
- POS2 |
- POS3 |
- POS6 |
- POS7,
- proc.passed
- );
-
- prc = new Processor("Test", cli);
- proc = new TryCatchProcess(new ArgumentException());
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.AreEqual
- (
- POS1 |
- POS2 |
- POS4 |
- POS6 |
- POS7,
- proc.passed
- );
-
- prc = new Processor("Test", cli);
- proc = new TryCatchProcess(new IndexOutOfRangeException());
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.AreEqual
- (
- POS1 |
- POS2 |
- POS5 |
- POS6 |
- POS7,
- proc.passed
- );
- }
- }
-
- #endregion
-
- #region Invoke
-
- [DataContract]
- private class InvokeProcess : Workflow.Process, IProcessDefinition
- {
- public int retvalDynamic;
- public int retvalInjected;
-
- [Service("Test/Service")]
- private Service service;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Invoke<Service>(_ => "/Services/Test/Service", (_, svc) => { retvalDynamic = svc.ReturnOne(); })
- .Invoke(service, (_, svc) => { retvalInjected = svc.ReturnOne(); });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- private static readonly string TEST_SERVICE_CONTAINER =
- @"<objects xmlns=""http://www.springframework.net"">" +
- @" <object id=""Service"" type=""" + typeof(Service).AssemblyQualifiedName + @""" />" +
- @"</objects>";
-
- [Test]
- public void Invoke()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Services")
- .ServiceContainer("Test", TEST_SERVICE_CONTAINER).End()
- .End()
- .Root("/Processors")
- .Processor("Proc1", (string)null)
- .Folder("Running")
- .Process
- (
- typeof(InvokeProcess).AssemblyQualifiedName,
- out pid
- ).End()
- .End()
- .Folder("Pending").End()
- .Folder("Suspended").End()
- .End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var proc = new InvokeProcess();
- var prc = new Processor("Proc1", cli);
-
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue(proc.retvalDynamic == 1);
- Assert.IsTrue(proc.retvalInjected == 1);
- Assert.IsTrue(dir.CountChildren(pid, DirectoryEntryTypes.State) == 2);
- }
- }
-
- #endregion
-
- #region Lock/Unlock
-
- [DataContract]
- private class LockUnlockProcess : Workflow.Process, IProcessDefinition
- {
- public const string RES1 = "/Sets/Shared/Resource1/Root";
- public const string RES2 = "/Sets/Shared/Resource2/Root";
-
- public static readonly string[] Resources = new string[] { RES1, RES2 };
-
- public bool FirstLockFailed;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Lock
- (
- _ => new[] { RES1 },
- ctx => ctx.Pid,
- _ => false,
- (ctx, failures) => { FirstLockFailed = true; }
- )
- .Lock
- (
- _ => new[] { RES2 },
- ctx => ctx.Pid,
- _ => true
- )
- .Unlock(_ => Resources, ctx => ctx.Pid);
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void LockUnlock()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Sets/Shared")
- .Set("Resource1", typeof(int).FullName, 0).End()
- .Set("Resource2", typeof(int).FullName, 0)
- .Folder("Root")
- .Message("X", BlobFormat.TextXml, 1).End()
- .End()
- .End()
- .End()
- .Root("/Processors")
- .Processor("Proc1", (string)null)
- .Folder("Running")
- .Process
- (
- typeof(LockUnlockProcess).FullName,
- out pid
- ).End()
- .End()
- .Folder("Waiting").End()
- .Folder("Pending").End()
- .End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var proc = new LockUnlockProcess();
- var prc = new Processor("Proc1", cli);
-
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Waiting);
- Assert.IsFalse(dir.Exists("/Processors/Proc1/Running/" + pid, DateTime.MinValue));
- Assert.IsTrue(dir.Exists("/Processors/Proc1/Waiting/" + pid, DateTime.MinValue));
-
- prc.Client.Unlock(new[] { LockUnlockProcess.RES2 }, "X");
- Assert.IsFalse(dir.Exists("/Processors/Proc1/Waiting/" + pid, DateTime.MinValue));
- Assert.IsTrue(dir.Exists("/Processors/Proc1/Pending/" + pid, DateTime.MinValue));
-
- Assert.IsTrue(prc.Execute() is Finish);
- }
- }
-
- #endregion
-
- #region Enqueue/Dequeue
-
- [DataContract]
- private class EnqueueDequeueProcess : Workflow.Process, IProcessDefinition
- {
- public const string SRC = "/Sets/Shared/Src";
- public const string DEST = "/Sets/Shared/Dest";
-
- private int i;
- private int message;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .For(_ => { i = 0; }, _ => i < 10, _ => { ++i; })
- .Dequeue<int>(_ => SRC, (ctx, msg) => { message = msg; })
- .Enqueue(_ => DEST, _ => message, _ => MessageFormat.BinXml)
- .End();
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void EnqueueDequeue()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Sets/Shared")
- .Set("Src", typeof(int).FullName, 0).End()
- .Set("Dest", typeof(int).FullName, 5).End()
- .End()
- .Root("/Processors")
- .Processor("Proc1", (string)null)
- .Folder("Running")
- .Process
- (
- typeof(LockUnlockProcess).FullName,
- out pid
- ).End()
- .End()
- .Folder("Waiting").End()
- .Folder("Pending").End()
- .End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var proc = new EnqueueDequeueProcess();
- var prc = new Processor("Proc1", cli);
-
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Waiting);
- Assert.IsFalse(dir.Exists("/Processors/Proc1/Running/" + pid, DateTime.MinValue));
- Assert.IsTrue(dir.Exists("/Processors/Proc1/Waiting/" + pid, DateTime.MinValue));
-
- for (int i = 0; i < 10; i++)
- {
- Assert.IsTrue(cli.PutMessage(EnqueueDequeueProcess.SRC, i.ToString(), i, BlobFormat.BinXml));
- }
-
- dir.Move(pid, "/Processors/Proc1/Running");
-
- Assert.IsTrue(prc.Execute() is Waiting);
- Assert.IsFalse(dir.Exists("/Processors/Proc1/Running/" + pid, DateTime.MinValue));
- Assert.IsTrue(dir.Exists("/Processors/Proc1/Waiting/" + pid, DateTime.MinValue));
- Assert.AreEqual(5, dir.CountChildren(EnqueueDequeueProcess.DEST, DirectoryEntryTypes.Message));
-
- var messages = dir.GetChildren(EnqueueDequeueProcess.DEST, DirectoryEntryTypes.Message, SortProperty.Default, Services.Data.SortOrder.Asc, 0, long.MaxValue);
- foreach(var msg in messages)
- {
- cli.RemoveMessage(msg.Id);
- }
-
- Assert.AreEqual(0, dir.CountChildren(EnqueueDequeueProcess.DEST, DirectoryEntryTypes.Message));
-
- dir.Move(pid, "/Processors/Proc1/Running");
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.AreEqual(5, dir.CountChildren(EnqueueDequeueProcess.DEST, DirectoryEntryTypes.Message));
- }
- }
-
- #endregion
-
- #region ForEach
-
- [DataContract]
- private class ForEachProcess : Workflow.Process, IProcessDefinition
- {
- public const string SET = "/Sets/Shared/Messages";
-
- private int i;
- public int sum;
- private int item;
- private string itemName;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .For(_ => { i = 0; }, _ => i < 8, _ => { i++; })
- .Enqueue(_ => SET, _ => i.ToString(), _ => 1 << i, _ => MessageFormat.BinXml)
- .End()
-
- .Exec(_ => { sum = 0; })
-
- .ForEach
- (
- _ => SET,
- _ => MessageProperty.Default,
- _ => SortOrder.Asc,
- _ => 100,
- _ => false,
- (string _, int itm) => { item = itm; }
- )
- .Exec(_ => { sum = sum | item; })
- .End()
-
- .Breakpoint("First sum")
-
- .ForEach
- (
- _ => SET,
- _ => MessageProperty.Default,
- _ => SortOrder.Asc,
- _ => 100,
- _ => false,
- (string itmName, int itm) => { item = itm; itemName = itmName; }
- )
- .UpdateCurrent(_ => itemName, _ => item << 8, _ => MessageFormat.BinXml)
- .End()
-
- .ForEach
- (
- _ => SET,
- _ => MessageProperty.Default,
- _ => SortOrder.Asc,
- _ => 100,
- _ => false,
- (string _, int itm) => { item = itm; }
- )
- .Exec(_ => { sum = sum | item; })
- .End()
-
- .Breakpoint("Second sum")
-
- .ForEach
- (
- _ => SET,
- _ => MessageProperty.Default,
- _ => SortOrder.Asc,
- _ => 100,
- _ => false,
- (string _, int itm) => { item = itm; }
- )
- .If(_ => item < 0x1000)
- .RemoveCurrent()
- .End()
- .End()
-
- .Exec(_ => { sum = 0; })
-
- .ForEach
- (
- _ => SET,
- _ => MessageProperty.Default,
- _ => SortOrder.Asc,
- _ => 100,
- _ => false,
- (string _, int itm) => { item = itm; }
- )
- .Exec(_ => { sum = sum | item; })
- .End()
-
- .Breakpoint("Third sum");
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void ForEach()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Sets/Shared")
- .Set("Messages", typeof(int).FullName, 0).End()
- .End()
- .Root("/Processors")
- .Processor("Proc1", (string)null)
- .Folder("Running")
- .Process
- (
- typeof(LockUnlockProcess).FullName,
- out pid
- ).End()
- .Folder("Waiting").End()
- .Folder("Pending").End()
- .End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var proc = new ForEachProcess();
- var prc = new Processor("Proc1", cli, null, new Processor.Settings { EmitBreakpoints = true });
-
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Breakpoint);
- Assert.AreEqual(0xFF, proc.sum);
-
- Assert.IsTrue(prc.Execute() is Breakpoint);
- Assert.AreEqual(0xFFFF, proc.sum);
-
- Assert.IsTrue(prc.Execute() is Breakpoint);
- Assert.AreEqual(0xF000, proc.sum);
- }
- }
-
- [DataContract]
- private class ForEachWaitingProcess : Workflow.Process, IProcessDefinition
- {
- public const string SET = "/Sets/Shared/Messages";
-
- public int sum;
- private int item;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { sum = 0; })
-
- .ForEach
- (
- _ => SET,
- _ => MessageProperty.Default,
- _ => SortOrder.Asc,
- _ => 100,
- _ => true,
- (string _, int itm) => { item = itm; }
- )
- .Exec(_ => { sum = sum | item; })
- .End();
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void ForEachWaiting()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Sets/Shared")
- .Set("Messages", typeof(int).FullName, 0).End()
- .End()
- .RegisterProcessor("Proc1")
- .Root("/Processors/Proc1/Running")
- .Process
- (
- typeof(LockUnlockProcess).FullName,
- out pid
- ).End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var proc = new ForEachWaitingProcess();
- var prc = new Processor("Proc1", cli);
-
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Waiting);
-
- for (int i = 0; i < 8; i++)
- {
- prc.Client.PutMessage(ForEachWaitingProcess.SET, i.ToString(), 1 << i, BlobFormat.BinXml);
- }
-
- dir.Move(pid, "/Processors/Proc1/Running");
-
- Assert.IsTrue(prc.Execute() is Waiting);
- Assert.AreEqual(0xFF, proc.sum);
-
- proc.sum = 0;
-
- for (int i = 8; i < 16; i++)
- {
- prc.Client.PutMessage(ForEachWaitingProcess.SET, i.ToString(), 1 << i, BlobFormat.BinXml);
- }
-
- dir.Move(pid, "/Processors/Proc1/Running");
-
- Assert.IsTrue(prc.Execute() is Waiting);
- Assert.AreEqual(0xFF00, proc.sum);
- }
- }
-
- #endregion
-
- #region WaitUntil
-
- [DataContract]
- private class WaitUntilProcess : Workflow.Process, IProcessDefinition
- {
- public DateTime start;
- public bool finished;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .WaitUntil(_ => start + TimeSpan.FromSeconds(1), _ => { finished = true; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void WaitUntil()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Processors")
- .Processor("Proc1", (string)null)
- .Folder("Running")
- .Process
- (
- typeof(LockUnlockProcess).FullName,
- out pid
- ).End()
- .Folder("Suspended").End()
- .End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var proc = new WaitUntilProcess { start = DateTime.Now };
- var prc = new Processor("Proc1", cli);
-
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Suspention);
- Assert.AreEqual(1, cli.Directory.CountChildren("/Processors/Proc1/Suspended", DirectoryEntryTypes.Link));
-
- Thread.Sleep(2000);
-
- Assert.IsTrue(prc.Execute() is Finish);
- }
- }
-
- #endregion
-
- #region StartProcess/WaitProcess
-
- [DataContract]
- public class EmptyWorkflow : Workflow.Process, IWorkflow<int, int>
- {
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
-
- public int Initialize(IInitializationContext context, int arg)
- {
- return arg + 1;
- }
-
- public void DefineProcess(IProcessBuilder bld)
- {
- }
- }
-
- [DataContract]
- public class StartProcessWaitProcessProcess : Workflow.Process, IProcessDefinition
- {
- private const string WORKFLOW = "/Workflows/Empty";
-
- public string pid;
- public int startResult;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .StartProcess<int, int>
- (
- _ => WORKFLOW,
- _ => 1,
- (_, p, result) =>
- {
- pid = p;
- startResult = result;
- }
- )
-
- .JoinProcess(_ => pid, null);
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void StartProcessWaitProcess()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Workflows")
- .Workflow("Empty", typeof(EmptyWorkflow).AssemblyQualifiedName, null).End()
- .End()
- .RegisterProcessor("Proc1")
- .Root("/Processors/Proc1/Running")
- .Process
- (
- typeof(LockUnlockProcess).FullName,
- out pid
- ).End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var proc = new StartProcessWaitProcessProcess();
- var prc = new Processor("Proc1", cli);
-
- prc.Init(pid, proc);
-
- Assert.IsTrue(prc.Execute() is Waiting);
- Assert.AreEqual(2, proc.startResult);
-
- cli
- .CreateScript()
- .SetText("__changeProcessStatus($in.pid, 'Finished');")
- .AddParameter("pid", proc.pid)
- .Execute();
-
- Assert.IsTrue(prc.Execute() is Finish);
- }
- }
-
- #endregion
-
- #region WaitAny
-
- [DataContract]
- private class WaitAnyProcess : Workflow.Process, IProcessDefinition
- {
- public const string GET_SET = "/Sets/Shared/Get";
- public const string PUT_SET = "/Sets/Shared/Put";
- public const string ENQUEUE_SET = "/Sets/Shared/Enqueue";
- public const string LOCK_SET = "/Sets/Shared/Lock";
- private const string WORKFLOW = "/Workflows/Empty";
-
- public DateTime waitUntil;
- public int count;
- public string pid;
- private int iterationsCount;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ =>
- {
- count = 0;
- iterationsCount = 0;
- waitUntil = DateTime.Now + TimeSpan.FromDays(1);
- })
-
- .StartProcess<int, int>
- (
- _ => WORKFLOW,
- _ => 1,
- (ctx, p, result) => { pid = p; }
- )
-
- .While(_ => count != (1 | 2 | 4 | 8 | 16 | 32) && iterationsCount <= 6)
- .WaitAny()
- .Enqueue(_ => PUT_SET, _ => "Msg", _ => 1, _ => MessageFormat.BinXml, _ => { count = count | 1; })
- .Enqueue(_ => ENQUEUE_SET, _ => 1, _ => MessageFormat.BinXml, _ => { count = count | 2; })
- .Dequeue<int>(_ => GET_SET, (_, msg) => { count = count | 4; })
- .Lock
- (
- _ => new[] { LOCK_SET },
- _ => ((count & 8) == 0) ? "Proc1" : "Proc2",
- _ => true,
- (_, failures) => { if (failures.Length == 0) count = count | 8; }
- )
- .JoinProcess(_ => pid, _ => { count = count | 16; })
- .WaitUntil(_ => waitUntil, _ => { count = count | 32; })
- .End()
-
- .If(_ => (count & 16) != 0)
- .StartProcess<int, int>
- (
- _ => WORKFLOW,
- _ => 1,
- (_, p, result) => { pid = p; }
- )
- .End()
-
- .Exec(_ => { ++iterationsCount; })
- .End();
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void WaitAny()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Workflows")
- .Workflow("Empty", typeof(EmptyWorkflow).AssemblyQualifiedName, null).End()
- .End()
- .Root("/Sets/Shared")
- .Set("Get", typeof(int).FullName, 0).End()
- .Set("Put", typeof(int).FullName, 1)
- .Message("Msg", BlobFormat.BinXml, 1).End()
- .End()
- .Set("Enqueue", typeof(int).FullName, 1)
- .Message("Msg", BlobFormat.BinXml, 1).End()
- .End()
- .Set("Lock", typeof(int).FullName, 1)
- .Message("Owner", BlobFormat.BinXml, 1).End()
- .End()
- .End()
- .RegisterProcessor("Proc1")
- .Root("/Processors/Proc1/Running")
- .Process
- (
- typeof(LockUnlockProcess).FullName,
- out pid
- ).End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var proc = new WaitAnyProcess();
- var prc = new Processor("Proc1", cli);
-
- prc.Init(pid, proc);
-
- var suspention = prc.Execute() as Suspention;
-
- Assert.IsTrue(suspention != null && !suspention.Stop);
- Assert.IsTrue(prc.Execute() is Waiting);
- Assert.IsTrue(dir.CountChildren(WaitAnyProcess.GET_SET + "/GetWaiters", DirectoryEntryTypes.Link) > 0);
-
- cli.PutMessage(WaitAnyProcess.GET_SET, "Msg", 1, BlobFormat.BinXml);
- dir.Move(pid, "/Processors/Proc1/Running");
- foreach (var suspentionLink in dir.GetChildren("/Processors/Proc1/Suspended", DirectoryEntryTypes.Link, SortProperty.Default, Services.Data.SortOrder.Asc, 0, long.MaxValue))
- {
- dir.Remove(suspentionLink.Id);
- }
-
- suspention = prc.Execute() as Suspention;
- Assert.IsTrue(suspention != null && !suspention.Stop);
- Assert.IsTrue(prc.Execute() is Waiting);
-
- cli.RemoveMessage("/Sets/Shared/Put/Msg");
- dir.Move(pid, "/Processors/Proc1/Running");
- foreach (var suspentionLink in dir.GetChildren("/Processors/Proc1/Suspended", DirectoryEntryTypes.Link, SortProperty.Default, Services.Data.SortOrder.Asc, 0, long.MaxValue))
- {
- dir.Remove(suspentionLink.Id);
- }
-
- suspention = prc.Execute() as Suspention;
- Assert.IsTrue(suspention != null && !suspention.Stop);
- Assert.IsTrue(prc.Execute() is Waiting);
-
- cli.RemoveMessage("/Sets/Shared/Enqueue/Msg");
- dir.Move(pid, "/Processors/Proc1/Running");
- foreach (var suspentionLink in dir.GetChildren("/Processors/Proc1/Suspended", DirectoryEntryTypes.Link, SortProperty.Default, Services.Data.SortOrder.Asc, 0, long.MaxValue))
- {
- dir.Remove(suspentionLink.Id);
- }
-
- suspention = prc.Execute() as Suspention;
- Assert.IsTrue(suspention != null && !suspention.Stop);
- Assert.IsTrue(prc.Execute() is Waiting);
-
- cli.RemoveMessage("/Sets/Shared/Lock/Owner");
- dir.Move(pid, "/Processors/Proc1/Running");
- foreach (var suspentionLink in dir.GetChildren("/Processors/Proc1/Suspended", DirectoryEntryTypes.Link, SortProperty.Default, Services.Data.SortOrder.Asc, 0, long.MaxValue))
- {
- dir.Remove(suspentionLink.Id);
- }
-
- suspention = prc.Execute() as Suspention;
- Assert.IsTrue(suspention != null && !suspention.Stop);
- Assert.IsTrue(prc.Execute() is Waiting);
-
- cli
- .CreateScript()
- .SetText("__changeProcessStatus($in.pid, 'Finished');")
- .AddParameter("pid", proc.pid)
- .Execute();
- dir.Move(pid, "/Processors/Proc1/Running");
- foreach (var suspentionLink in dir.GetChildren("/Processors/Proc1/Suspended", DirectoryEntryTypes.Link, SortProperty.Default, Services.Data.SortOrder.Asc, 0, long.MaxValue))
- {
- dir.Remove(suspentionLink.Id);
- }
-
- suspention = prc.Execute() as Suspention;
- Assert.IsTrue(suspention != null && !suspention.Stop);
- Assert.IsTrue(prc.Execute() is Waiting);
-
- dir.Move(pid, "/Processors/Proc1/Running");
- foreach (var suspentionLink in dir.GetChildren("/Processors/Proc1/Suspended", DirectoryEntryTypes.Link, SortProperty.Default, Services.Data.SortOrder.Asc, 0, long.MaxValue))
- {
- dir.Remove(suspentionLink.Id);
- }
-
- proc.waitUntil = DateTime.Now;
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.AreEqual(1 | 2 | 4 | 8 | 16 | 32, proc.count);
- }
- }
-
- #endregion
-
- #region Breakpoint
-
- [DataContract]
- private class BreakpointProcess : Workflow.Process, IProcessDefinition
- {
- public int Pos1;
- public int Pos2;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { Pos1 = POS1; })
-
- .Breakpoint("break")
-
- .Exec(_ => { Pos2 = POS2; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void Breakpoint()
- {
- var proc = new BreakpointProcess();
- var prc = new Processor("Test", _flowerClient, null, new Processor.Settings { EmitBreakpoints = true });
-
- prc.Init("PID", proc);
-
- var bp = prc.Execute() as Breakpoint;
-
- Assert.IsTrue(bp != null);
- Assert.IsTrue(bp.Name == "break");
- Assert.IsTrue(prc.Execute() is Finish);
- }
-
- #endregion
-
- #region Save/Load process
-
- [DataContract]
- private class SaveLoadProcessProcess : Workflow.Process, IWorkflow<object, object>
- {
- [DataMember]
- public int counter;
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
-
- public object Initialize(IInitializationContext context, object arg)
- {
- return null;
- }
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Breakpoint("Break1")
- .Exec(_ => { counter = 0; })
- .ExecAndSave(_ => { counter++; })
- .Breakpoint("Break2")
- .ExecAndSave(_ => { counter++; });
- }
- }
-
- [Test]
- public void SaveLoadProcess()
- {
- var dir = CreateDirectory();
-
- string pid;
-
- new DirectoryBuilder(dir)
- .Root("/Processors")
- .Processor("Proc", (string)null)
- .Folder("Running")
- .Process
- (
- typeof(SaveLoadProcessProcess).AssemblyQualifiedName,
- out pid
- )
- .End()
- .End()
- .End()
- .End();
-
- using (var cli = new FlowerClient(dir))
- {
- var prc = new SaveLoadProcessProcess();
- var proc = new Processor("Proc", cli, null, new Processor.Settings { EmitBreakpoints = true });
-
- proc.Init(pid, prc);
-
- Assert.IsTrue(proc.Execute() is Breakpoint);
- proc.SaveState(false);
-
- proc = new Processor("Proc", cli, null, new Processor.Settings { EmitBreakpoints = true });
- proc.LoadProcess(pid);
- prc = (SaveLoadProcessProcess)proc.State;
-
- Assert.IsTrue(proc.Execute() is Breakpoint);
- Assert.AreEqual(1, prc.counter);
- proc.SaveState(false);
-
- proc = new Processor("Proc", cli, null, new Processor.Settings { EmitBreakpoints = true });
-
- proc.LoadProcess(pid);
- prc = (SaveLoadProcessProcess)proc.State;
-
- Assert.AreEqual(1, prc.counter);
-
- Assert.IsTrue(proc.Execute() is Finish);
- Assert.AreEqual(2, prc.counter);
- }
- }
-
- #endregion
-
- #region ExecAsync
-
- [DataContract]
- private class ExecAsyncProcess : Workflow.Process, IProcessDefinition
- {
- public int Pos1;
- public int Pos2;
- public int Pos3;
-
- public void DefineProcess(IProcessBuilder bld)
- {
- bld
- .Exec(_ => { Pos1 = POS1; })
- .ExecAsync
- (
- async _ =>
- {
- await Task.Factory.StartNew(() => Pos2 = POS2);
- }
- )
- .Exec(_ => { Pos3 = POS3; });
- }
-
- public void DefineLocalSets(ISetsBuilder bld)
- {
- }
- }
-
- [Test]
- public void ExecAsync()
- {
- var prc = new Processor("Test", _flowerClient);
-
- var proc = new ExecAsyncProcess();
- prc.Init("PID", proc);
-
- Async asyncInterruption;
-
- Assert.IsTrue((asyncInterruption = prc.Execute() as Async) != null);
-
- asyncInterruption.Task.Wait();
-
- Assert.IsTrue(prc.Execute() is Finish);
- Assert.IsTrue((proc.Pos1 | proc.Pos2 | proc.Pos3) == (POS1 | POS2 | POS3));
- }
-
- #endregion
- }
- }