Ejemplo n.º 1
0
        public void EnsureValid_GivenOptionsWithInvalidDefaultForDataType_ThrowsInvalidRulesEngineOptionsExceptionClaimingInvalidDefault(DataTypes dataType, object defaultValue)
        {
            // Arrange
            RulesEngineOptions rulesEngineOptions = RulesEngineOptions.NewWithDefaults();

            rulesEngineOptions.DataTypeDefaults[dataType] = defaultValue;

            InvalidRulesEngineOptionsException actual = Assert.Throws <InvalidRulesEngineOptionsException>(() =>
            {
                // Act
                RulesEngineOptionsValidator.EnsureValid(rulesEngineOptions);
            });

            actual.Message.Should().Be($"Specified invalid default value for data type {dataType}: {defaultValue ?? "null"}.");
        }
Ejemplo n.º 2
0
        public void GetDeferredEvalFor_GivenStringConditionNodeWithNoConditionSuppliedAndRulesEngineConfiguredToUseDataTypeDefaultWhenMissing_ReturnsFuncThatEvalsFalse()
        {
            // Arrange
            StringConditionNode <ConditionType> conditionNode = new StringConditionNode <ConditionType>(ConditionType.IsoCurrency, Operators.Equal, "EUR");

            Mock <IOperatorEvalStrategy> mockOperatorEvalStrategy = new Mock <IOperatorEvalStrategy>();

            mockOperatorEvalStrategy.Setup(x => x.Eval(It.IsAny <string>(), It.IsAny <string>()))
            .Returns(false);

            Mock <IOperatorEvalStrategyFactory> mockOperatorEvalStrategyFactory = new Mock <IOperatorEvalStrategyFactory>();

            mockOperatorEvalStrategyFactory.Setup(x => x.GetOperatorEvalStrategy(It.IsAny <Operators>()))
            .Returns(mockOperatorEvalStrategy.Object);

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

            MatchModes matchMode = MatchModes.Exact;

            RulesEngineOptions rulesEngineOptions = RulesEngineOptions.NewWithDefaults();

            rulesEngineOptions.MissingConditionBehavior = MissingConditionBehaviors.UseDataTypeDefault;

            DeferredEval sut = new DeferredEval(mockOperatorEvalStrategyFactory.Object, rulesEngineOptions);

            // Act
            Func <IEnumerable <Condition <ConditionType> >, bool> actual = sut.GetDeferredEvalFor(conditionNode, matchMode);
            bool actualEvalResult = actual.Invoke(conditions);

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

            mockOperatorEvalStrategyFactory.Verify(x => x.GetOperatorEvalStrategy(It.IsAny <Operators>()), Times.Once());
            mockOperatorEvalStrategy.Verify(x => x.Eval(It.IsAny <string>(), It.IsAny <string>()), Times.Once());
        }
Ejemplo n.º 3
0
        public void GetDeferredEvalFor_GivenUnknownConditionNodeType_ThrowsNotSupportedException()
        {
            // Arrange
            Mock <IValueConditionNode <ConditionType> > mockValueConditionNode = new Mock <IValueConditionNode <ConditionType> >();

            Mock <IOperatorEvalStrategyFactory> mockOperatorEvalStrategyFactory = new Mock <IOperatorEvalStrategyFactory>();

            MatchModes matchMode = MatchModes.Exact;

            RulesEngineOptions rulesEngineOptions = RulesEngineOptions.NewWithDefaults();

            DeferredEval sut = new DeferredEval(mockOperatorEvalStrategyFactory.Object, rulesEngineOptions);

            // Act
            NotSupportedException notSupportedException = Assert.Throws <NotSupportedException>(() => sut.GetDeferredEvalFor(mockValueConditionNode.Object, matchMode));

            // Assert
            notSupportedException.Should().NotBeNull();
            notSupportedException.Message.Should().Be($"Unsupported value condition node: '{mockValueConditionNode.Object.GetType().Name}'.");
        }
Ejemplo n.º 4
0
        public void GetDeferredEvalFor_GivenDecimalConditionNode_ReturnsFuncToEvalConditionsCollection()
        {
            // Arrange
            DecimalConditionNode <ConditionType> conditionNode = new DecimalConditionNode <ConditionType>(ConditionType.PluviosityRate, Operators.GreaterThan, 50);

            Mock <IOperatorEvalStrategy> mockOperatorEvalStrategy = new Mock <IOperatorEvalStrategy>();

            mockOperatorEvalStrategy.Setup(x => x.Eval(It.IsAny <decimal>(), It.IsAny <decimal>()))
            .Returns(true);

            Mock <IOperatorEvalStrategyFactory> mockOperatorEvalStrategyFactory = new Mock <IOperatorEvalStrategyFactory>();

            mockOperatorEvalStrategyFactory.Setup(x => x.GetOperatorEvalStrategy(It.IsAny <Operators>()))
            .Returns(mockOperatorEvalStrategy.Object);

            IEnumerable <Condition <ConditionType> > conditions = new Condition <ConditionType>[]
            {
                new Condition <ConditionType>
                {
                    Type  = ConditionType.PluviosityRate,
                    Value = 78
                }
            };

            MatchModes matchMode = MatchModes.Exact;

            RulesEngineOptions rulesEngineOptions = RulesEngineOptions.NewWithDefaults();

            DeferredEval sut = new DeferredEval(mockOperatorEvalStrategyFactory.Object, rulesEngineOptions);

            // Act
            Func <IEnumerable <Condition <ConditionType> >, bool> actual = sut.GetDeferredEvalFor(conditionNode, matchMode);
            bool actualEvalResult = actual.Invoke(conditions);

            // Assert
            actualEvalResult.Should().BeTrue();

            mockOperatorEvalStrategyFactory.Verify(x => x.GetOperatorEvalStrategy(It.IsAny <Operators>()), Times.Once());
            mockOperatorEvalStrategy.Verify(x => x.Eval(It.IsAny <decimal>(), It.IsAny <decimal>()), Times.Once());
        }
        public async Task MatchOneAsync_GivenContentTypeDateAndConditions_FetchesRulesForDayFailsEvalsAndReturnsNull()
        {
            // Arrange
            DateTime    matchDateTime = new DateTime(2018, 07, 01, 18, 19, 30);
            ContentType contentType   = ContentType.Type1;
            IEnumerable <Condition <ConditionType> > conditions = new[]
            {
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsoCountryCode,
                    Value = "BRZ"
                },
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsoCurrency,
                    Value = "USD"
                }
            };

            IEnumerable <Rule <ContentType, ConditionType> > rules = new[]
            {
                new Rule <ContentType, ConditionType>
                {
                    ContentContainer = new ContentContainer <ContentType>(contentType, (t) => new object()),
                    DateBegin        = new DateTime(2018, 01, 01),
                    DateEnd          = new DateTime(2019, 01, 01),
                    Name             = "Expected rule",
                    Priority         = 3,
                    RootCondition    = new StringConditionNode <ConditionType>(ConditionType.IsoCountryCode, Operators.Equal, "USA")
                },
                new Rule <ContentType, ConditionType>
                {
                    ContentContainer = new ContentContainer <ContentType>(contentType, (t) => new object()),
                    DateBegin        = new DateTime(2010, 01, 01),
                    DateEnd          = new DateTime(2021, 01, 01),
                    Name             = "Expected rule",
                    Priority         = 200,
                    RootCondition    = new StringConditionNode <ConditionType>(ConditionType.IsoCountryCode, Operators.Equal, "USA")
                }
            };

            EvaluationOptions evaluationOptions = new EvaluationOptions
            {
                MatchMode = MatchModes.Exact
            };
            Mock <IRulesDataSource <ContentType, ConditionType> > mockRulesDataSource      = SetupMockForRulesDataSource(rules);
            Mock <IConditionsEvalEngine <ConditionType> >         mockConditionsEvalEngine = SetupMockForConditionsEvalEngine(false, evaluationOptions);
            RulesEngineOptions rulesEngineOptions = RulesEngineOptions.NewWithDefaults();

            RulesEngine <ContentType, ConditionType> sut = new RulesEngine <ContentType, ConditionType>(mockConditionsEvalEngine.Object, mockRulesDataSource.Object, rulesEngineOptions);

            // Act
            Rule <ContentType, ConditionType> actual = await sut.MatchOneAsync(contentType, matchDateTime, conditions);

            // Assert
            actual.Should().BeNull();
            mockRulesDataSource.Verify(x => x.GetRulesAsync(It.IsAny <ContentType>(), It.IsAny <DateTime>(), It.IsAny <DateTime>()), Times.Once());
            mockConditionsEvalEngine.Verify(x => x.Eval(
                                                It.IsAny <IConditionNode <ConditionType> >(),
                                                It.IsAny <IEnumerable <Condition <ConditionType> > >(),
                                                It.Is <EvaluationOptions>(eo => eo == evaluationOptions)), Times.AtLeastOnce());
        }
        public async Task MatchManyAsync_GivenContentTypeDateAndConditions_FetchesRulesForDayEvalsAndReturnsAllMatches()
        {
            // Arrange
            DateTime    matchDateTime = new DateTime(2018, 07, 01, 18, 19, 30);
            ContentType contentType   = ContentType.Type1;
            IEnumerable <Condition <ConditionType> > conditions = new[]
            {
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsoCountryCode,
                    Value = "USA"
                },
                new Condition <ConditionType>
                {
                    Type  = ConditionType.IsoCurrency,
                    Value = "USD"
                }
            };

            Rule <ContentType, ConditionType> expected1 = new Rule <ContentType, ConditionType>
            {
                ContentContainer = new ContentContainer <ContentType>(contentType, (t) => new object()),
                DateBegin        = new DateTime(2018, 01, 01),
                DateEnd          = new DateTime(2019, 01, 01),
                Name             = "Expected rule 1",
                Priority         = 3,
                RootCondition    = new StringConditionNode <ConditionType>(ConditionType.IsoCountryCode, Operators.Equal, "USA")
            };

            Rule <ContentType, ConditionType> expected2 = new Rule <ContentType, ConditionType>
            {
                ContentContainer = new ContentContainer <ContentType>(contentType, (t) => new object()),
                DateBegin        = new DateTime(2010, 01, 01),
                DateEnd          = new DateTime(2021, 01, 01),
                Name             = "Expected rule 2",
                Priority         = 200,
                RootCondition    = new StringConditionNode <ConditionType>(ConditionType.IsoCountryCode, Operators.Equal, "USA")
            };

            Rule <ContentType, ConditionType> notExpected = new Rule <ContentType, ConditionType>
            {
                ContentContainer = new ContentContainer <ContentType>(contentType, (t) => new object()),
                DateBegin        = new DateTime(2018, 01, 01),
                DateEnd          = new DateTime(2019, 01, 01),
                Name             = "Not expected rule",
                Priority         = 1, // Topmost rule, should be the one that wins if options are set to topmost wins.
                RootCondition    = new StringConditionNode <ConditionType>(ConditionType.IsoCountryCode, Operators.Equal, "CHE")
            };

            IEnumerable <Rule <ContentType, ConditionType> > rules = new[]
            {
                expected1,
                expected2,
                notExpected
            };

            EvaluationOptions evaluationOptions = new EvaluationOptions
            {
                MatchMode = MatchModes.Exact
            };
            Mock <IRulesDataSource <ContentType, ConditionType> > mockRulesDataSource      = SetupMockForRulesDataSource(rules);
            Mock <IConditionsEvalEngine <ConditionType> >         mockConditionsEvalEngine = SetupMockForConditionsEvalEngine((rootConditionNode, inputConditions, evalOptions) =>
            {
                switch (rootConditionNode)
                {
                case StringConditionNode <ConditionType> stringConditionNode:
                    return(stringConditionNode.Operand == "USA");

                default:
                    return(false);
                }
            }, evaluationOptions);
            RulesEngineOptions rulesEngineOptions = RulesEngineOptions.NewWithDefaults();

            RulesEngine <ContentType, ConditionType> sut = new RulesEngine <ContentType, ConditionType>(mockConditionsEvalEngine.Object, mockRulesDataSource.Object, rulesEngineOptions);

            // Act
            IEnumerable <Rule <ContentType, ConditionType> > actual = await sut.MatchManyAsync(contentType, matchDateTime, conditions);

            // Assert
            actual.Should().Contain(expected1)
            .And.Contain(expected2)
            .And.NotContain(notExpected);
            mockRulesDataSource.Verify(x => x.GetRulesAsync(It.IsAny <ContentType>(), It.IsAny <DateTime>(), It.IsAny <DateTime>()), Times.Once());
            mockConditionsEvalEngine.Verify(x => x.Eval(
                                                It.IsAny <IConditionNode <ConditionType> >(),
                                                It.IsAny <IEnumerable <Condition <ConditionType> > >(),
                                                It.Is <EvaluationOptions>(eo => eo == evaluationOptions)), Times.AtLeastOnce());
        }
Ejemplo n.º 7
0
 public ConfiguredRulesEngineBuilder(IRulesDataSource <TContentType, TConditionType> rulesDataSource)
 {
     this.rulesDataSource    = rulesDataSource;
     this.rulesEngineOptions = RulesEngineOptions.NewWithDefaults();
 }