Пример #1
0
        [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>();
            }
        }
Пример #2
0
        [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]);
            }
        }
Пример #3
0
        public void InitCtx()
        {
            var dir  = AppDomain.CurrentDomain.BaseDirectory;
            var file = Path.Combine(dir, "dmn/test.dmn");

            ctx = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse(file));
        }
Пример #4
0
        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));
        }
Пример #5
0
        [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");
        }
Пример #8
0
        // 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");
        }
Пример #10
0
        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");
        }
Пример #11
0
        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));
            }
        }
Пример #12
0
        // 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);
        }
Пример #13
0
        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");
        }
Пример #14
0
        [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");
        }
Пример #17
0
        private OpenCacheExecutionContext Ctx(DmnDefinition def, ParsedExpressionCacheScopeEnum?cacheType)
        {
            if (!cacheType.HasValue) //default
            {
                return((OpenCacheExecutionContext)DmnExecutionContextFactory
                       .CreateCustomExecutionContext <OpenCacheExecutionContext>(def));
            }

            return((OpenCacheExecutionContext)DmnExecutionContextFactory
                   .CreateCustomExecutionContext <OpenCacheExecutionContext>(
                       def,
                       o => o.ParsedExpressionCacheScope = cacheType.Value));
        }
        [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 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");
        }
        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);
        }
Пример #23
0
        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 #");
        }
Пример #25
0
        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));
        }
Пример #27
0
        [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));
        }
Пример #29
0
        [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++;
            }
        }
Пример #30
0
        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));
            }
        }