[DataRow("6", 6, true, true, 8, 0, false)] //input1 will be string, so the eval will fail public void NormalizedExpressionDecisionDmnTest(object input1, int input2, bool isExecErr, bool result1, int result2, int result3, bool result4) { var def = MODEL("issue11expressions.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(def); var inputParameters = new Dictionary <string, object> { { "input1_æøåščřáů", input1 }, { "input_2_æøåščřáů", input2 } }; ctx.WithInputParameters(inputParameters); if (!isExecErr) { var execResult1 = ctx.ExecuteDecision("decision1"); var execResult2 = ctx.ExecuteDecision("decision2"); var execResult3 = ctx.ExecuteDecision("decision3"); var execResult4 = ctx.ExecuteDecision("decision4"); execResult1.First["var1æøåščřáů"].Value.Should().Be(result1); execResult2.First["var2æøåšč_99_88___řáů"].Value.Should().Be(result2); execResult3.First["var2æøåšč_99_88___řáů"].Value.Should().Be(result3); execResult4.First["var1æøåščřáů"].Value.Should().Be(result4); } else { Action act = () => ctx.ExecuteDecision("decision1"); act.Should().Throw <DmnExecutorException>(); } }
[DataRow(8, 8, null)] //no hit public void CollectListHitPolicyTest(int?a, int?b, string[] hits) { var def = new DmnDefinitionBuilder() .WithInput <int>("a", out var aRef) .WithInput <int>("b", out var bRef) .WithVariable <long>("o", out var oRef) .WithTableDecision("Collect", table => table .WithInput(aRef, out var inputARef) .WithInput(bRef, out var inputBRef) .WithOutput(oRef, out var outputRef) .WithHitPolicy(HitPolicyEnum.Collect) .WithAggregation(CollectHitPolicyAggregationEnum.List) .WithRule("r1", r => r .When(inputARef, "< 5").And(inputBRef, "1").Then(outputRef, "5")) .WithRule("r2", r => r .When(inputARef, "<= 5").And(inputBRef, "2").Then(outputRef, "3")) .WithRule("r3", r => r .When(inputARef, "5").And(inputBRef, "1").Then(outputRef, "4")) .WithRule("r4", r => r .When(inputARef, "5").Then(outputRef, "8")) .WithRule("r5", r => r .When(inputARef, "6").Then(outputRef, "2")) .WithRule("r6", r => r .When(inputARef, ">= 6").And(inputBRef, "1").Then(outputRef, "1")) .WithRule("rEmpty", r => r .When(inputARef, ">= 6").And(inputBRef, "2").Then(outputRef, "")) .WithRule("r7", r => r .When(inputBRef, "3").Then(outputRef, "2")) .WithRule("r8", r => r .When(inputARef, "9").And(inputBRef, "1").Then(outputRef, "3")) .Requires(aRef).Requires(bRef)) .Build(); var ctx = DmnExecutionContextFactory .CreateExecutionContext(def) .WithInputParameter("a", a) .WithInputParameter("b", b); var result = ctx.ExecuteDecision("Collect"); var hitsCount = hits?.Length ?? 0; result.Should().NotBeNull(); result.Results.Should().NotBeNull(); result.Results.Should().HaveCount(hitsCount); if (hitsCount == 0) { return; } for (var i = 0; i < hitsCount; i++) { result.Results[i].HitRules.Should().HaveCount(1); // ReSharper disable once PossibleNullReferenceException result.Results[i].HitRules[0].Name.Should().Be(hits[i]); } }
public static void InitCtx(TestContext testContext) { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/sfeel.dmn"); ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); }
public void InitCtx() { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/test.dmn"); ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse(file)); }
[DataRow(9, 9, null, 0)] //no hit public void UniqueHitPolicyTest(int?a, int?b, string hit, int hitsCount) { var def = new DmnDefinitionBuilder() .WithInput <int>("a", out var aRef) .WithInput <int>("b", out var bRef) .WithVariable <string>("o", out var oRef) .WithTableDecision("Unique", table => table .WithInput(aRef, out var inputARef) .WithInput(bRef, out var inputBRef) .WithOutput(oRef, out var outputRef) .WithHitPolicy(HitPolicyEnum.Unique) .WithRule("r1", r => r .When(inputARef, "< 5").And(inputBRef, "1").Then(outputRef, "\"r1\"")) .WithRule("r2", "err not unique for 5 - 2", r => r .When(inputARef, "<= 5").And(inputBRef, "2").Then(outputRef, "\"r2\"")) .WithRule("r3", r => r .When(inputARef, "5").And(inputBRef, "1").Then(outputRef, "\"r3\"")) .WithRule("r4", "err not unique for 5 - 2", r => r .When(inputARef, "5").And(inputBRef, "2").Then(outputRef, "\"r4\"")) .WithRule("r5", "err not unique for 6-3", r => r .When(inputARef, "6").Then(outputRef, "\"r5\"")) .WithRule("r6", r => r .When(inputARef, "> 6").And(inputBRef, "2").Then(outputRef, "\"r6\"")) .WithRule("rEmpty", "empty out", r => r .When(inputARef, "> 6").And(inputBRef, "1").Then(outputRef, "")) .WithRule("r8", "err not unique for 6-3", r => r .When(inputBRef, "3").Then(outputRef, "\"r8\"")) .Requires(aRef).Requires(bRef)) .Build(); var ctx = DmnExecutionContextFactory .CreateExecutionContext(def) .WithInputParameter("a", a) .WithInputParameter("b", b); DmnDecisionResult result = null; Action act = () => { result = ctx.ExecuteDecision("Unique"); }; if (hitsCount < 0) { act.Should().Throw <DmnExecutorException>().WithMessage("UNIQUE hit policy violation*"); return; } act.Invoke(); result.Should().NotBeNull(); result.Results.Should().NotBeNull(); result.Results.Should().HaveCount(hitsCount); if (hitsCount == 0) { return; } result.Results[0].HitRules.Should().HaveCount(1); result.Results[0].HitRules[0].Name.Should().Be(hit ?? "rEmpty"); }
public void WrongHitPolicyAggregationTest() { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_WrongAggregation.dmn"); Action act = () => DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); act.Should().Throw <DmnParserException>().WithMessage("Wrong hit policy aggregation *"); }
public void ParseTypesErrTest() { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/datatypes_err.dmn"); Action act = () => DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); act.Should().Throw <DmnParserException>().WithMessage("Unsupported type name datetime"); }
// ReSharper disable once InconsistentNaming protected static DmnExecutionContext CTX(string dmnFile, SourceEnum source, Action <DmnExecutionContextOptions> configure = null) { var ctx = source != SourceEnum.Builder ? DmnExecutionContextFactory.CreateExecutionContext(MODEL(dmnFile, source), configure) : DmnExecutionContextFactory.CreateExecutionContext(DmnBuilderSamples.Files[dmnFile], configure); return(ctx); }
//[TestMethod] - uncomment to see the StackOverflowException with circular dependency in model public void CircularReferenceTest() { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/circular_err.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", 0); ctx.ExecuteDecision("Second"); }
public void ParallelTest() { TestContext.WriteLine(""); var stopWatch = System.Diagnostics.Stopwatch.StartNew(); var parallel = Enumerable.Range(10, 17) .AsParallel() .AsOrdered() .Select(n => { var startInner = DateTime.Now; var ctx = DmnExecutionContextFactory.CreateExecutionContext(DefStatic, ConfigureCtx); TestContext.WriteLine($"ctx: Source={Source}, Opts:{CtxOptionsStr(ctx.Options)}; DMN: parallel.dmn"); ctx.WithInputParameter("numin", -1 * n); ctx.WithInputParameter("str", "2018-01-" + n); ctx.WithInputParameter("dt", DateTime.ParseExact("2019-01-01 01:01", "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture)); var result = ctx.Reset().ExecuteDecision("sfeel"); var endInner = DateTime.Now; var msInner = (endInner - startInner).Milliseconds; TestContext.WriteLine($"Done for n={n} - execution time: {msInner}ms, start: {startInner:HH:mm:ss.ffff}, end: {endInner:HH:mm:ss.ffff}"); return(result); }) .ToArray(); stopWatch.Stop(); var ms = stopWatch.ElapsedMilliseconds; TestContext.WriteLine($"All done - Total execution time: {ms}ms"); foreach (var result in parallel) { result.Should().NotBeNull(); result.IsSingleResult.Should().Be(true); result.FirstResultVariables.Should().NotBeNull(); result.FirstResultVariables.Should().HaveCount(3); result.Results[0].HitRules.Should().HaveCount(1); var outNumInOut = result.FirstResultVariables[2]; outNumInOut.Should().NotBeNull(); outNumInOut.Name.Should().Be("numinout"); outNumInOut.Type.Should().Be(typeof(int)); var numInOut = (int)outNumInOut.Value; var outO = result.FirstResultVariables[0]; outO.Should().NotBeNull(); outO.Name.Should().Be("o"); outO.Value.Should().Be("2018-01" + numInOut).And.BeOfType <string>(); outO.Type.Should().Be(typeof(string)); var outNumOut = result.FirstResultVariables[1]; outNumOut.Should().NotBeNull(); outNumOut.Name.Should().Be("numout"); outNumOut.Value.Should().Be(4 * numInOut).And.BeOfType <int>(); outNumOut.Type.Should().Be(typeof(int)); } }
public void CtxInputTests() { var def = new DmnDefinitionBuilder() .WithInput <int>("input1", out var input1Ref) .WithInput("input2", out var input2Ref) .WithVariable <object>("output", out var outputRef) .WithExpressionDecision("decision1", "(input1+1).ToString()", outputRef) .WithExpressionDecision("decision2", "input2+1", outputRef) .Build(); var ctx = DmnExecutionContextFactory.CreateExecutionContext(def); Action act = null; //override var result1 = ctx .WithInputParameter("input1", 5) .WithInputParameter("input1", 10) .ExecuteDecision("decision1"); result1.First["output"].Value.Should().Be("11"); //wrong type act = () => { var result = ctx.WithInputParameter("input1", "dummy"); }; act.Should().Throw <DmnExecutorException>("Can't cast value to target type: Int32. Value is: dummy of type String"); //type "on init" and the cache setting impact var ctx2 = DmnExecutionContextFactory.CreateExecutionContext(def); var result2 = ctx2 .WithInputParameter("input2", 5) .ExecuteDecision("decision2"); result2.First["output"].Value.Should().Be(6); //cached with 'input2+1' parsed with input2:int -> should throw act = () => { var ctx3 = DmnExecutionContextFactory.CreateExecutionContext(def); var result3 = ctx3 .WithInputParameter("input2", "6") .ExecuteDecision("decision2"); result3.First["output"].Value.Should().Be("61"); }; act.Should().Throw <DmnExecutorException>("Exception while invoking the expression input2+1--->System.ArgumentException: Object of type 'System.String' cannot be converted to type 'System.Int32'"); //bypass cache -> should parse and execute with input2:string var ctx4 = DmnExecutionContextFactory.CreateExecutionContext(def, o => o.ParsedExpressionCacheScope = ParsedExpressionCacheScopeEnum.None); var result4 = ctx4 .WithInputParameter("input2", "6") .ExecuteDecision("decision2"); result4.First["output"].Value.Should().Be("61"); }
// ReSharper disable once InconsistentNaming protected DmnExecutionContext CTX(string dmnFile, Action <DmnExecutionContextOptions> configure = null) { var ctx = Source != SourceEnum.Builder ? DmnExecutionContextFactory.CreateExecutionContext(MODEL(dmnFile), configure ?? ConfigureCtx) : DmnExecutionContextFactory.CreateExecutionContext(DmnBuilderSamples.Files[dmnFile], configure ?? ConfigureCtx); TestContext.WriteLine($"CTX: Source={Source}, Opts:{CtxOptionsStr(ctx.Options)}; DMN: {dmnFile}"); return(ctx); }
public void FirstHitPolicyTest(int?a, int?b, string hit, int hitsCount) { var def = new DmnDefinitionBuilder() .WithInput <int>("a", out var aRef) .WithInput <int>("b", out var bRef) .WithVariable <string>("o", out var oRef) .WithTableDecision("First", table => table .WithInput(aRef, out var inputARef) .WithInput(bRef, out var inputBRef) .WithOutput(oRef, out var outputRef) .WithHitPolicy(HitPolicyEnum.First) .WithRule("r1", r => r .When(inputARef, "< 5").And(inputBRef, "1").Then(outputRef, "\"r1\"")) .WithRule("r2", r => r .When(inputARef, "<= 5").And(inputBRef, "2").Then(outputRef, "\"r2\"")) .WithRule("r3", r => r .When(inputARef, "5").And(inputBRef, "1").Then(outputRef, "\"r3\"")) .WithRule("r4", r => r .When(inputARef, "5").And(inputBRef, "2").Then(outputRef, "\"r4\"")) //should never hit (r2 hits first) .WithRule("r5", r => r .When(inputARef, "6").Then(outputRef, "\"r5\"")) .WithRule("r6", r => r .When(inputBRef, "2").Then(outputRef, "\"r6\"")) .WithRule("rEmpty", "empty out", r => r .When(inputBRef, "1").Then(outputRef, "")) .WithRule("fallback", r => r .Always().Then(outputRef, "\"fallback\"")) .Requires(aRef).Requires(bRef)) .Build(); var ctx = DmnExecutionContextFactory .CreateExecutionContext(def) .WithInputParameter("a", a) .WithInputParameter("b", b); ctx.WithInputParameter("a", a); ctx.WithInputParameter("b", b); var result = ctx.ExecuteDecision("First"); result.Should().NotBeNull(); result.Results.Should().NotBeNull(); result.Results.Should().HaveCount(hitsCount); if (hitsCount == 0) { return; } result.Results[0].HitRules.Should().HaveCount(1); result.Results[0].HitRules[0].Name.Should().Be(hit ?? "rEmpty"); }
[DataRow(8, 8, null)] //no hit public void PriorityHitPolicyTest(int?a, int?b, string hit) { var def = new DmnDefinitionBuilder() .WithInput <int>("a", out var aRef) .WithInput <int>("b", out var bRef) .WithVariable <string>("o", out var oRef) .WithTableDecision("Priority", table => table .WithInput(aRef, out var inputARef) .WithInput(bRef, out var inputBRef) .WithOutput(oRef, out var outputRef, "b", "a", "c", "d") .WithHitPolicy(HitPolicyEnum.Priority) .WithRule("r1", r => r .When(inputARef, "< 5").And(inputBRef, "1").Then(outputRef, "\"a\"")) .WithRule("r2", r => r .When(inputARef, "<= 5").And(inputBRef, "2").Then(outputRef, "\"b\"")) .WithRule("r3", r => r .When(inputARef, "5").And(inputBRef, "1").Then(outputRef, "\"c\"")) .WithRule("r4", r => r .When(inputARef, "5").Then(outputRef, "\"a\"")) .WithRule("r5", r => r .When(inputARef, "6").Then(outputRef, "\"d\"")) .WithRule("r6", r => r .When(inputARef, ">= 6").And(inputBRef, "2").Then(outputRef, "\"a\"")) .WithRule("rEmpty", r => r .When(inputARef, ">= 6").And(inputBRef, "1").Then(outputRef, "")) .WithRule("r7", r => r .When(inputBRef, "3").Then(outputRef, "\"c\"")) .Requires(aRef).Requires(bRef)) .Build(); var ctx = DmnExecutionContextFactory .CreateExecutionContext(def) .WithInputParameter("a", a) .WithInputParameter("b", b); var result = ctx.ExecuteDecision("Priority"); var hitsCount = hit != null ? 1 : 0; result.Should().NotBeNull(); result.Results.Should().NotBeNull(); result.Results.Should().HaveCount(hitsCount); if (hitsCount == 0) { return; } result.Results[0].HitRules.Should().HaveCount(1); result.Results[0].HitRules[0].Name.Should().Be(hit); }
[DataRow(9, 9, null, 0, 0)] //no hit public void UniqueHitPolicyTest(int?a, int?b, string c, int hitsCount, int outVariableCount) { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_Unique.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", a); ctx.WithInputParameter("b", b); DmnDecisionResult result = null; Action act = () => { result = ctx.ExecuteDecision("Unique"); }; if (hitsCount < 0) { act.Should().Throw <DmnExecutorException>().WithMessage("UNIQUE hit policy violation*"); return; } act.Invoke(); result.Should().NotBeNull(); result.Results.Should().NotBeNull(); if (hitsCount <= 0) { result.Results.Should().HaveCount(0); result.HasResult.Should().Be(false); result.IsSingleResult.Should().Be(false); return; } result.Results.Should().HaveCount(hitsCount); result.HasResult.Should().Be(true); if (hitsCount == 1) { result.IsSingleResult.Should().Be(true); result.SingleResult.Should().NotBeNull(); result.SingleResult.Should().HaveCount(outVariableCount); } if (outVariableCount <= 0) { return; } var output = result.SingleResult[0]; output.Should().NotBeNull(); output.Name.Should().Be("o"); output.Value.Should().Be(c).And.BeOfType <string>(); output.Type.Should().Be(typeof(string)); }
public void CollectCountBoolHitPolicyTest() { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_Collect_CountBool.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", 2); ctx.WithInputParameter("b", 1); Action act = () => { ctx.ExecuteDecision("Collect"); }; act.Should().Throw <DmnExecutorException>().WithMessage("COLLECT hit policy violation - type Boolean not allowed for aggregation Count"); }
public void OutputOrder_NoOutWithAllowedHitPolicyTest() { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_OutputOrder_NoOutWithAllowed.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", 2); ctx.WithInputParameter("b", 1); Action act = () => { ctx.ExecuteDecision("OutputOrder"); }; act.Should().Throw <DmnExecutorException>().WithMessage("OUTPUT ORDER hit policy violation - no outputs with Allowed Values"); }
[DataRow(8, 8, null, 0, new[] { 0 })] //no hit public void OutputOrderHitPolicyTest(int?a, int?b, string[] c, int hitsCount, int[] outVariableCount) { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_OutputOrder.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", a); ctx.WithInputParameter("b", b); DmnDecisionResult result = null; Action act = () => { result = ctx.ExecuteDecision("OutputOrder"); }; act.Invoke(); result.Should().NotBeNull(); result.Results.Should().NotBeNull(); if (hitsCount <= 0) { result.Results.Should().HaveCount(0); result.HasResult.Should().Be(false); result.IsSingleResult.Should().Be(false); return; } result.Results.Should().HaveCount(hitsCount); result.HasResult.Should().Be(true); if (hitsCount == 1) { result.IsSingleResult.Should().Be(true); result.SingleResult.Should().NotBeNull(); result.SingleResult.Should().HaveCount(outVariableCount[0]); } for (var i = 0; i < hitsCount; i++) { if (outVariableCount[i] <= 0) { result.Results[i].Variables.Should().HaveCount(0); continue; } result.Results[i].Variables.Should().HaveCount(1); var output = result.Results[i].Variables[0]; output.Should().NotBeNull(); output.Name.Should().Be("o"); output.Value.Should().Be(c[i]).And.BeOfType <string>(); output.Type.Should().Be(typeof(string)); } }
public void ParseTypesTest() { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/datatypes.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.Should().NotBeNull(); ctx.Variables["string"].Type.Should().Be(typeof(string)); ctx.Variables["int"].Type.Should().Be(typeof(int)); ctx.Variables["bool"].Type.Should().Be(typeof(bool)); ctx.Variables["long"].Type.Should().Be(typeof(long)); ctx.Variables["double"].Type.Should().Be(typeof(double)); ctx.Variables["date"].Type.Should().Be(typeof(DateTime)); }
[DataRow(8, 8, false, 0)] //no hit public void CollectMaxBoolHitPolicyTest(int?a, int?b, bool?c, int hitsCount) { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_Collect_MaxBool.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", a); ctx.WithInputParameter("b", b); DmnDecisionResult result = null; Action act = () => { result = ctx.ExecuteDecision("Collect"); }; act.Invoke(); result.Should().NotBeNull(); result.Results.Should().NotBeNull(); if (hitsCount <= 0) { result.Results.Should().HaveCount(0); result.HasResult.Should().Be(false); result.IsSingleResult.Should().Be(false); return; } result.Results.Should().HaveCount(hitsCount); result.HasResult.Should().Be(true); result.IsSingleResult.Should().Be(true); result.SingleResult.Should().NotBeNull(); result.SingleResult.Should().HaveCount(1); result.Results[0].Variables.Should().HaveCount(1); var output = result.Results[0].Variables[0]; output.Should().NotBeNull(); output.Name.Should().Be("o"); if (c != null) { output.Value.Should().Be(c).And.BeOfType <bool>(); output.Type.Should().Be(typeof(bool)); } else { output.Value.Should().BeNull(); output.Type.Should().Be(typeof(bool)); } }
public void LogicalAndDecisionTest() { //Logical1: input1 & input2 => output //Logical2: output (from logical1) & input2 ; with negate => output //meaning output=not(input1 & input2 & input3) var builder = new DmnDefinitionBuilderEx(); builder .WithInput <bool>("input1", out var input1Ref) .WithInput <bool>("input2", out var input2Ref) .WithInput <bool>("input3", out var input3Ref) .WithVariable <bool>("output", out var outputRef) .As <DmnDefinitionBuilderEx>() .WithLogicalAndDecision("Logical1", b => b .WithInputs(input1Ref, input2Ref) .WithOutput(outputRef), out var d1Ref) .WithLogicalAndDecision("Logical2", b => b .WithInputs(outputRef, input3Ref) .WithNegate(true) .WithOutput(outputRef) .Requires(d1Ref), out _); var def = builder.Build(); var ctx1 = DmnExecutionContextFactory.CreateExecutionContext(def); ctx1.WithInputParameters(new Dictionary <string, object>() { { "input1", true }, { "input2", true }, { "input3", true } }); var result1 = ctx1.ExecuteDecision("Logical2"); result1.First["output"].Value.Should().Be(false); var ctx2 = DmnExecutionContextFactory.CreateExecutionContext(def); ctx2.WithInputParameters(new Dictionary <string, object>() { { "input1", true }, { "input2", false }, { "input3", true } }); var result2 = ctx2.ExecuteDecision("Logical2"); result2.First["output"].Value.Should().Be(true); }
public void NoInformationRequirementsSubElementsTest() { var def = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; def += "<definitions xmlns = \"https://www.omg.org/spec/DMN/20191111/MODEL/\" > "; def += "<decision id = \"test\" name=\"Test\">"; def += "<informationRequirement>"; def += "</informationRequirement>"; def += "</decision>"; def += "</definitions>"; Action act = () => DmnExecutionContextFactory.CreateExecutionContext(DmnParser.ParseString13(def)); act.Should().Throw <DmnParserException>().WithMessage( "informationRequirement element doesn't contain requiredDecision nor requiredInput elements or contains both"); }
public void MissingHashInInformationRequirementReferenceTest(string hrefAttr) { var def = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; def += "<definitions xmlns = \"http://www.omg.org/spec/DMN/20151101/dmn.xsd\" >"; def += "<decision id = \"test\" name=\"Test\">"; def += "<informationRequirement>"; def += $"<requiredInput {hrefAttr} />"; def += "</informationRequirement>"; def += "</decision>"; def += "</definitions>"; Action act = () => DmnExecutionContextFactory.CreateExecutionContext(DmnParser.ParseString(def)); act.Should().Throw <DmnParserException>().WithMessage( "Can't parse InformationRequirement - reference doesn't start with #"); }
public void TooShortInformationRequirementReferenceTest(string hrefAttr) { var def = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; def += "<definitions xmlns = \"https://www.omg.org/spec/DMN/20191111/MODEL/\" >"; def += "<decision id = \"test\" name=\"Test\">"; def += "<informationRequirement>"; def += $"<requiredInput {hrefAttr} />"; def += "</informationRequirement>"; def += "</decision>"; def += "</definitions>"; Action act = () => DmnExecutionContextFactory.CreateExecutionContext(DmnParser.ParseString13(def)); act.Should().Throw <DmnParserException>().WithMessage( "Can't parse InformationRequirement - reference too short/missing"); }
public void FirstHitPolicyTest(int?a, int?b, string c, int hitsCount, int outVariableCount) { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_First.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", a); ctx.WithInputParameter("b", b); var result = ctx.ExecuteDecision("First"); result.Should().NotBeNull(); result.Results.Should().NotBeNull(); if (hitsCount <= 0) { result.Results.Should().HaveCount(0); result.HasResult.Should().Be(false); result.IsSingleResult.Should().Be(false); return; } result.Results.Should().HaveCount(hitsCount); result.HasResult.Should().Be(true); if (hitsCount == 1) { result.IsSingleResult.Should().Be(true); result.SingleResult.Should().NotBeNull(); result.SingleResult.Should().HaveCount(outVariableCount); } if (outVariableCount <= 0) { return; } var output = result.SingleResult[0]; output.Should().NotBeNull(); output.Name.Should().Be("o"); output.Value.Should().Be(c).And.BeOfType <string>(); output.Type.Should().Be(typeof(string)); }
[DataRow(99, "A", false, true, null, "O", "error")] //O is not allowed output public void TableDmnTest(int input1, string input2, bool input3, bool isErr, int?resultOut1, string resultOut2, string match) { var def = DmnTestBase.DEF("issue11tbl.dmn", SourceEnum.File13); var ctx = DmnExecutionContextFactory .CreateExecutionContext(def) .WithInputParameter("input_1_æøåščřáů", input1) .WithInputParameter("input2æøåščřáů", input2) .WithInputParameter("input3æøåščřáů", input3); if (!isErr) { var result = ctx.ExecuteDecision("tbl"); result.HasResult.Should().BeTrue(); if (resultOut1 != null) { result.First["var_2_æøåščřáů"].Value.Should().Be(resultOut1); } else { result.First["var_2_æøåščřáů"].Should().BeNull(); } if (resultOut2 != null) { result.First["var3æøåščřáů"].Value.Should().Be(resultOut2); } else { result.First["var3æøåščřáů"].Should().BeNull(); } result.First.HitRules.Should().HaveCount(1); result.First.HitRules[0].Name.Should().Be(match); } else { Action act = () => ctx.ExecuteDecision("tbl"); act.Should().Throw <Exception>(); } }
public void AllowedValuesTest(string a, string b, string c, bool validIn, bool validOut) { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/allowedValues.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse(file, DmnParser.DmnVersionEnum.V1_3)); ctx.WithInputParameter("a", a); ctx.WithInputParameter("b", b); DmnDecisionResult result = null; Action act = () => { result = ctx.ExecuteDecision("Test"); }; if (!validIn && validOut) { act.Should().Throw <DmnExecutorException>().WithMessage("Decision table Test,* Input value * is not in allowed values list *"); return; } if (!validOut) { act.Should().Throw <DmnExecutorException>().WithMessage("Decision table Test,* Output value * is not in allowed values list *"); return; } act.Invoke(); result.Should().NotBeNull(); result.IsSingleResult.Should().Be(true); result.SingleResult.Should().NotBeNull(); result.SingleResult.Should().HaveCount(1); var output = result.SingleResult[0]; output.Should().NotBeNull(); output.Name.Should().Be("c"); output.Value.Should().Be(c).And.BeOfType <string>(); output.Type.Should().Be(typeof(string)); }
[DataRow(null, null, new[] { "" }, new[] { -1 }, new[] { "" }, false)] //null -> 0 public void RuleOrderHitPolicyMultiOutTest(int?a, int?b, string[] o1, int[] o2, string[] o3, bool hasHit) { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_MultiOut_RuleOrder.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", a); ctx.WithInputParameter("b", b); DmnDecisionResult result = null; Action act = () => { result = ctx.ExecuteDecision("RuleOrder"); }; act.Invoke(); result.Should().NotBeNull(); result.Results.Should().NotBeNull(); if (!hasHit) { result.Results.Should().HaveCount(0); result.HasResult.Should().Be(false); result.IsSingleResult.Should().Be(false); return; } var hitsCount = o1.Length; result.Results.Should().HaveCount(hitsCount); result.HasResult.Should().Be(true); if (hitsCount == 1) { result.IsSingleResult.Should().Be(true); result.SingleResult.Should().NotBeNull(); } result.Results.Should().HaveCount(hitsCount); var idx = 0; foreach (var resultHit in result.Results) { var o1Result = resultHit.Variables?.FirstOrDefault(v => v.Name == "o1"); var o2Result = resultHit.Variables?.FirstOrDefault(v => v.Name == "o2"); var o3Result = resultHit.Variables?.FirstOrDefault(v => v.Name == "o3"); var o1Asserrt = o1[idx]; var o2Asserrt = o2[idx]; var o3Asserrt = o3[idx]; if (o1Result == null) { o1Asserrt.Should().BeNull(); } else { o1Result.Should().NotBeNull(); o1Result.Value.Should().NotBeNull(); o1Result.Value.Should().Be(o1Asserrt).And.BeOfType <string>(); o1Result.Type.Should().Be(typeof(string)); } if (o2Result == null) { o2Asserrt.Should().Be(-1); //-1 means null } else { o2Result.Should().NotBeNull(); o2Result.Value.Should().NotBeNull(); o2Result.Value.Should().Be(o2Asserrt).And.BeOfType <int>(); o2Result.Type.Should().Be(typeof(int)); } if (o3Result == null) { o3Asserrt.Should().BeNull(); } else { o3Result.Should().NotBeNull(); o3Result.Value.Should().NotBeNull(); o3Result.Value.Should().Be(o3Asserrt).And.BeOfType <string>(); o3Result.Type.Should().Be(typeof(string)); } idx++; } }
public void AnyHitPolicyMultiOutTest(int?a, int?b, string o1, int?o2, bool hasHit, bool isErr) { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_MultiOut_Any.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", a); ctx.WithInputParameter("b", b); DmnDecisionResult result = null; Action act = () => { result = ctx.ExecuteDecision("Any"); }; if (isErr) { act.Should().Throw <DmnExecutorException>().WithMessage("ANY hit policy violation - the outputs don't match"); return; } act.Invoke(); result.Should().NotBeNull(); result.Results.Should().NotBeNull(); if (!hasHit) { result.Results.Should().HaveCount(0); result.HasResult.Should().Be(false); result.IsSingleResult.Should().Be(false); return; } result.Results.Should().HaveCount(1); result.HasResult.Should().Be(true); result.IsSingleResult.Should().Be(true); result.SingleResult.Should().NotBeNull(); var outCount = 2; var o1Index = 0; var o2Index = 1; if (o1 == null) { outCount--; o1Index = -1; o2Index--; } if (o2 == null) { outCount--; o2Index = -1; } result.SingleResult.Should().HaveCount(outCount); if (o1Index >= 0) { var output1 = result.SingleResult[o1Index]; output1.Should().NotBeNull(); output1.Name.Should().Be("o1"); output1.Value.Should().Be(o1).And.BeOfType <string>(); output1.Type.Should().Be(typeof(string)); } // ReSharper disable once InvertIf if (o2Index >= 0) { var output2 = result.SingleResult[o2Index]; output2.Should().NotBeNull(); output2.Name.Should().Be("o2"); output2.Value.Should().Be(o2).And.BeOfType <int>(); output2.Type.Should().Be(typeof(int)); } }
public void UniqueHitPolicyMultiOutTest(int?a, int?b, string o1, int?o2, bool hasHit) { var dir = AppDomain.CurrentDomain.BaseDirectory; var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_MultiOut_Unique.dmn"); var ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file)); ctx.WithInputParameter("a", a); ctx.WithInputParameter("b", b); var result = ctx.ExecuteDecision("Unique"); result.Should().NotBeNull(); result.Results.Should().NotBeNull(); if (!hasHit) { result.Results.Should().HaveCount(0); result.HasResult.Should().Be(false); result.IsSingleResult.Should().Be(false); return; } result.Results.Should().HaveCount(1); result.HasResult.Should().Be(true); result.IsSingleResult.Should().Be(true); result.SingleResult.Should().NotBeNull(); var outCount = 0; if (o1 != null) { outCount++; } if (o2 != null) { outCount++; } result.SingleResult.Should().HaveCount(outCount); if (o1 != null) { var output1 = result.SingleResult[0]; output1.Should().NotBeNull(); output1.Name.Should().Be("o1"); output1.Value.Should().Be(o1).And.BeOfType <string>(); output1.Type.Should().Be(typeof(string)); if (o2 == null) { return; } var output2 = result.SingleResult[1]; output2.Should().NotBeNull(); output2.Name.Should().Be("o2"); output2.Value.Should().Be(o2).And.BeOfType <int>(); output2.Type.Should().Be(typeof(int)); } else { if (o2 == null) { return; } var output2 = result.SingleResult[0]; output2.Should().NotBeNull(); output2.Name.Should().Be("o2"); output2.Value.Should().Be(o2).And.BeOfType <int>(); output2.Type.Should().Be(typeof(int)); } }