コード例 #1
0
 private ISpecification <IEnumerable <Condition <TConditionType> > > BuildSpecification(IConditionNode <TConditionType> conditionNode, MatchModes matchMode)
 {
     return(conditionNode switch
     {
         IValueConditionNode <TConditionType> valueConditionNode => this.BuildSpecificationForValueNode(valueConditionNode, matchMode),
         ComposedConditionNode <TConditionType> composedConditionNode => this.BuildSpecificationForComposedNode(composedConditionNode, matchMode),
         _ => throw new NotSupportedException($"Unsupported condition node: '{conditionNode.GetType().Name}'."),
     });
コード例 #2
0
        public void Eval_GivenComposedConditionNodeWithAndOperatorAndUnknownConditionNodeWithSearchMode_ThrowsNotSupportedException()
        {
            // Arrange
            StubConditionNode <ConditionType>   condition1 = new StubConditionNode <ConditionType>();
            StringConditionNode <ConditionType> condition2 = new StringConditionNode <ConditionType>(ConditionType.IsoCurrency, Operators.NotEqual, "SGD");

            ComposedConditionNode <ConditionType> composedConditionNode = new ComposedConditionNode <ConditionType>(
                LogicalOperators.Or,
                new IConditionNode <ConditionType>[] { condition1, condition2 });

            IEnumerable <Condition <ConditionType> > conditions = new[]
            {
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsoCurrency,
                    Value = "SGD"
                },
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsoCountryCode,
                    Value = "PT"
                }
            };

            EvaluationOptions evaluationOptions = new EvaluationOptions
            {
                MatchMode = MatchModes.Search,
                ExcludeRulesWithoutSearchConditions = true
            };

            Mock <IDeferredEval> mockDeferredEval = new Mock <IDeferredEval>();

            mockDeferredEval.SetupSequence(x => x.GetDeferredEvalFor(It.IsAny <IValueConditionNode <ConditionType> >(), It.Is <MatchModes>(mm => mm == MatchModes.Exact)))
            .Returns(() =>
            {
                return((c) => false);
            })
            .Returns(() =>
            {
                return((c) => true);
            })
            .Throws(new NotImplementedException("Shouldn't have gotten any more deferred evals."));

            ConditionsEvalEngine <ConditionType> sut = new ConditionsEvalEngine <ConditionType>(mockDeferredEval.Object);

            // Act
            NotSupportedException notSupportedException = Assert.Throws <NotSupportedException>(() => sut.Eval(composedConditionNode, conditions, evaluationOptions));

            // Assert
            notSupportedException.Should().NotBeNull();
            notSupportedException.Message.Should().Be("Unsupported condition node: 'StubConditionNode`1'.");
            mockDeferredEval.Verify(x => x.GetDeferredEvalFor(It.IsAny <IValueConditionNode <ConditionType> >(), It.Is <MatchModes>(mm => mm == MatchModes.Exact)), Times.Exactly(0));
        }
コード例 #3
0
        public void Eval_GivenComposedConditionNodeWithAndOperatorAndMissingConditionWithSearchMode_EvalsAndReturnsResult()
        {
            // Arrange
            BooleanConditionNode <ConditionType> condition1 = new BooleanConditionNode <ConditionType>(ConditionType.IsVip, Operators.Equal, true);
            StringConditionNode <ConditionType>  condition2 = new StringConditionNode <ConditionType>(ConditionType.IsoCurrency, Operators.NotEqual, "SGD");

            ComposedConditionNode <ConditionType> composedConditionNode = new ComposedConditionNode <ConditionType>(
                LogicalOperators.Or,
                new IConditionNode <ConditionType>[] { condition1, condition2 });

            IEnumerable <Condition <ConditionType> > conditions = new[]
            {
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsoCurrency,
                    Value = "SGD"
                },
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsoCountryCode,
                    Value = "PT"
                }
            };

            EvaluationOptions evaluationOptions = new EvaluationOptions
            {
                MatchMode = MatchModes.Search,
                ExcludeRulesWithoutSearchConditions = true
            };

            Mock <IDeferredEval> mockDeferredEval = new Mock <IDeferredEval>();

            mockDeferredEval.SetupSequence(x => x.GetDeferredEvalFor(It.IsAny <IValueConditionNode <ConditionType> >(), It.Is <MatchModes>(mm => mm == MatchModes.Exact)))
            .Returns(() =>
            {
                return((c) => false);
            })
            .Returns(() =>
            {
                return((c) => true);
            })
            .Throws(new NotImplementedException("Shouldn't have gotten any more deferred evals."));

            ConditionsEvalEngine <ConditionType> sut = new ConditionsEvalEngine <ConditionType>(mockDeferredEval.Object);

            // Act
            bool actual = sut.Eval(composedConditionNode, conditions, evaluationOptions);

            // Assert
            actual.Should().BeFalse();

            mockDeferredEval.Verify(x => x.GetDeferredEvalFor(It.IsAny <IValueConditionNode <ConditionType> >(), It.Is <MatchModes>(mm => mm == MatchModes.Exact)), Times.Exactly(0));
        }
コード例 #4
0
        public void ComposedConditionNode_Init_GivenSetupWithChildConditionsAndLogicalOperator_ReturnsSettedValues()
        {
            // Arrange
            LogicalOperators expectedLogicalOperator = LogicalOperators.Eval;
            IEnumerable <IConditionNode <ConditionType> > expectedChildConditionNodes = new IConditionNode <ConditionType>[]
            {
                new Mock <IConditionNode <ConditionType> >().Object,
                new Mock <IConditionNode <ConditionType> >().Object
            };

            ComposedConditionNode <ConditionType> sut = new ComposedConditionNode <ConditionType>(expectedLogicalOperator, expectedChildConditionNodes);

            // Act
            LogicalOperators actualLogicalOperator = sut.LogicalOperator;
            IEnumerable <IConditionNode <ConditionType> > actualChildConditionNodes = sut.ChildConditionNodes;

            // Assert
            actualLogicalOperator.Should().Be(expectedLogicalOperator);
            actualChildConditionNodes.Should().NotBeNull().And.BeSameAs(expectedChildConditionNodes);
        }
コード例 #5
0
        public void Eval_GivenComposedConditionNodeWithEvalOperator_ThrowsNotSupportedException()
        {
            // Arrange
            BooleanConditionNode <ConditionType> condition1 = new BooleanConditionNode <ConditionType>(ConditionType.IsVip, Operators.Equal, true);
            StringConditionNode <ConditionType>  condition2 = new StringConditionNode <ConditionType>(ConditionType.IsoCurrency, Operators.NotEqual, "SGD");

            ComposedConditionNode <ConditionType> composedConditionNode = new ComposedConditionNode <ConditionType>(
                LogicalOperators.Eval,
                new IConditionNode <ConditionType>[] { condition1, condition2 });

            IEnumerable <Condition <ConditionType> > conditions = new[]
            {
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsoCurrency,
                    Value = "SGD"
                },
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsVip,
                    Value = true
                }
            };

            EvaluationOptions evaluationOptions = new EvaluationOptions
            {
                MatchMode = MatchModes.Exact
            };

            Mock <IDeferredEval> mockDeferredEval = new Mock <IDeferredEval>();

            ConditionsEvalEngine <ConditionType> sut = new ConditionsEvalEngine <ConditionType>(mockDeferredEval.Object);

            // Act
            NotSupportedException notSupportedException = Assert.Throws <NotSupportedException>(() => sut.Eval(composedConditionNode, conditions, evaluationOptions));

            // Assert
            notSupportedException.Should().NotBeNull();
            notSupportedException.Message.Should().Be("Unsupported logical operator: 'Eval'.");
            mockDeferredEval.Verify(x => x.GetDeferredEvalFor(It.IsAny <IValueConditionNode <ConditionType> >(), It.Is <MatchModes>(mm => mm == MatchModes.Exact)), Times.Never());
        }
コード例 #6
0
        public void CreateRule_GivenRuleDataModelWithComposedNodeAndChildNodesOfEachDataType_ReturnsRuleInstance()
        {
            // Arrange
            dynamic content = new ExpandoObject();

            content.Prop1 = 123;
            content.Prop2 = "Sample string";
            content.Prop3 = 500.34m;

            ValueConditionNodeDataModel integerConditionNodeDataModel = new ValueConditionNodeDataModel
            {
                ConditionType   = "SampleIntegerCondition",
                DataType        = DataTypes.Integer,
                LogicalOperator = LogicalOperators.Eval,
                Operand         = 20,
                Operator        = Operators.GreaterThan
            };

            ValueConditionNodeDataModel stringConditionNodeDataModel = new ValueConditionNodeDataModel
            {
                ConditionType   = "SampleStringCondition",
                DataType        = DataTypes.String,
                LogicalOperator = LogicalOperators.Eval,
                Operand         = "TEST",
                Operator        = Operators.Equal
            };

            ValueConditionNodeDataModel decimalConditionNodeDataModel = new ValueConditionNodeDataModel
            {
                ConditionType   = "SampleDecimalCondition",
                DataType        = DataTypes.Decimal,
                LogicalOperator = LogicalOperators.Eval,
                Operand         = 50.3m,
                Operator        = Operators.LesserThanOrEqual
            };

            ValueConditionNodeDataModel booleanConditionNodeDataModel = new ValueConditionNodeDataModel
            {
                ConditionType   = "SampleBooleanCondition",
                DataType        = DataTypes.Boolean,
                LogicalOperator = LogicalOperators.Eval,
                Operand         = true,
                Operator        = Operators.NotEqual
            };

            RuleDataModel ruleDataModel = new RuleDataModel
            {
                Content       = content,
                ContentType   = "ContentTypeSample",
                DateBegin     = new System.DateTime(2020, 1, 1),
                DateEnd       = null,
                Id            = ObjectId.GenerateNewId(),
                Name          = "My rule used for testing purposes",
                Priority      = 1,
                RootCondition = new ComposedConditionNodeDataModel
                {
                    LogicalOperator     = LogicalOperators.And,
                    ChildConditionNodes = new ConditionNodeDataModel[]
                    {
                        integerConditionNodeDataModel,
                        stringConditionNodeDataModel,
                        decimalConditionNodeDataModel,
                        booleanConditionNodeDataModel
                    }
                }
            };

            IContentSerializationProvider <ContentType> contentSerializationProvider = Mock.Of <IContentSerializationProvider <ContentType> >();

            RuleFactory <ContentType, ConditionType> ruleFactory = new RuleFactory <ContentType, ConditionType>(contentSerializationProvider);

            // Act
            Rule <ContentType, ConditionType> rule = ruleFactory.CreateRule(ruleDataModel);

            // Assert
            rule.Should().NotBeNull();
            rule.ContentContainer.Should().NotBeNull()
            .And.BeOfType <SerializedContentContainer <ContentType> >();
            rule.DateBegin.Should().Be(ruleDataModel.DateBegin);
            rule.DateEnd.Should().BeNull();
            rule.Name.Should().Be(ruleDataModel.Name);
            rule.Priority.Should().Be(ruleDataModel.Priority);
            rule.RootCondition.Should().BeOfType <ComposedConditionNode <ConditionType> >();

            ComposedConditionNode <ConditionType> composedConditionNode = rule.RootCondition.As <ComposedConditionNode <ConditionType> >();

            composedConditionNode.LogicalOperator.Should().Be(LogicalOperators.And);
            composedConditionNode.ChildConditionNodes.Should().HaveCount(4);

            IEnumerable <IntegerConditionNode <ConditionType> > integerConditionNodes = composedConditionNode.ChildConditionNodes.OfType <IntegerConditionNode <ConditionType> >();

            integerConditionNodes.Should().HaveCount(1);
            IntegerConditionNode <ConditionType> integerConditionNode = integerConditionNodes.First();

            integerConditionNode.Should().NotBeNull();
            integerConditionNode.ConditionType.Should().Match <ConditionType>(x => x == Enum.Parse <ConditionType>(integerConditionNodeDataModel.ConditionType));
            integerConditionNode.DataType.Should().Be(integerConditionNodeDataModel.DataType);
            integerConditionNode.LogicalOperator.Should().Be(integerConditionNodeDataModel.LogicalOperator);
            integerConditionNode.Operand.Should().Match(x => object.Equals(x, integerConditionNodeDataModel.Operand));
            integerConditionNode.Operator.Should().Be(integerConditionNodeDataModel.Operator);

            IEnumerable <StringConditionNode <ConditionType> > stringConditionNodes = composedConditionNode.ChildConditionNodes.OfType <StringConditionNode <ConditionType> >();

            stringConditionNodes.Should().HaveCount(1);
            StringConditionNode <ConditionType> stringConditionNode = stringConditionNodes.First();

            stringConditionNode.Should().NotBeNull();
            stringConditionNode.ConditionType.Should().Match <ConditionType>(x => x == Enum.Parse <ConditionType>(stringConditionNodeDataModel.ConditionType));
            stringConditionNode.DataType.Should().Be(stringConditionNodeDataModel.DataType);
            stringConditionNode.LogicalOperator.Should().Be(stringConditionNodeDataModel.LogicalOperator);
            stringConditionNode.Operand.Should().Match(x => object.Equals(x, stringConditionNodeDataModel.Operand));
            stringConditionNode.Operator.Should().Be(stringConditionNodeDataModel.Operator);

            IEnumerable <DecimalConditionNode <ConditionType> > decimalConditionNodes = composedConditionNode.ChildConditionNodes.OfType <DecimalConditionNode <ConditionType> >();

            decimalConditionNodes.Should().HaveCount(1);
            DecimalConditionNode <ConditionType> decimalConditionNode = decimalConditionNodes.First();

            decimalConditionNode.Should().NotBeNull();
            decimalConditionNode.ConditionType.Should().Match <ConditionType>(x => x == Enum.Parse <ConditionType>(decimalConditionNodeDataModel.ConditionType));
            decimalConditionNode.DataType.Should().Be(decimalConditionNodeDataModel.DataType);
            decimalConditionNode.LogicalOperator.Should().Be(decimalConditionNodeDataModel.LogicalOperator);
            decimalConditionNode.Operand.Should().Match(x => object.Equals(x, decimalConditionNodeDataModel.Operand));
            decimalConditionNode.Operator.Should().Be(decimalConditionNodeDataModel.Operator);

            IEnumerable <BooleanConditionNode <ConditionType> > booleanConditionNodes = composedConditionNode.ChildConditionNodes.OfType <BooleanConditionNode <ConditionType> >();

            booleanConditionNodes.Should().HaveCount(1);
            BooleanConditionNode <ConditionType> booleanConditionNode = booleanConditionNodes.First();

            booleanConditionNode.Should().NotBeNull();
            booleanConditionNode.ConditionType.Should().Match <ConditionType>(x => x == Enum.Parse <ConditionType>(booleanConditionNodeDataModel.ConditionType));
            booleanConditionNode.DataType.Should().Be(booleanConditionNodeDataModel.DataType);
            booleanConditionNode.LogicalOperator.Should().Be(booleanConditionNodeDataModel.LogicalOperator);
            booleanConditionNode.Operand.Should().Be(Convert.ToBoolean(booleanConditionNodeDataModel.Operand));
            booleanConditionNode.Operator.Should().Be(booleanConditionNodeDataModel.Operator);
        }