internal BuilderContext(ValidatorBuilder <TState> builder, bool threadSafe)
        {
            _hasConstraints = 0;
            _validators     = TypeDictionary <TypeValidator <TState> > .Create(builder.Types.Count);

            _threadSafe = threadSafe;
            _state      = new StateManager();

            Builder = builder;
        }
        private Validator <object> GetValidator()
        {
            var builder = new ValidatorBuilder <object>();

            builder.AddPropertyFilter(_ => true);
            builder.AddKnownType <TestClass>();
            builder.AddEmptyConstraint();

            return(builder.Build());
        }
Example #3
0
        public async Task AsyncValidation()
        {
            const int ParallelCount = 2;

            var list    = new HashSet <int>();
            var cts     = new CancellationTokenSource();
            var builder = new ValidatorBuilder <object>();

            builder.AddKnownType <RecursiveClass>();
            builder.AddPropertyFilter <RecursiveClass>();
            builder.AddConstraint(_ => new DelegateConstraint(instanceValue =>
            {
                lock (list)
                {
                    if (Task.CurrentId.HasValue)
                    {
                        list.Add(Task.CurrentId.Value);
                    }
                }

                return(true);
            }));
            var validator = builder.Build();

            var instance = new RecursiveClass
            {
                Entry1 = new RecursiveClass
                {
                    Entry1 = new RecursiveClass
                    {
                    },
                    Entry2 = new RecursiveClass
                    {
                    },
                },
                Entry2 = new RecursiveClass
                {
                    Entry1 = new RecursiveClass
                    {
                    },
                    Entry2 = new RecursiveClass
                    {
                    },
                },
            };

            var context = new TestValidationContext();

            context.Context.MaxDegreeOfParallelism = ParallelCount;
            await validator.ValidateAsync(instance, context.Context).ConfigureAwait(false);

            Assert.Equal(ParallelCount, list.Count);
        }
Example #4
0
        public void PatternNoObserverNotString()
        {
            var builder = new ValidatorBuilder <object>();

            builder.AddRegexAttributeConstraint <RegexAttribute>(r => r.Pattern);
            builder.AddKnownType <TestNotString>();

            var exp = Assert.Throws <ValidatorBuilderException>(() => builder.Build());

            Assert.Equal(Errors.UnsupportedTypeForConstraint, exp.Id);
            Assert.Equal(typeof(TestNotString), exp.Type);
            Assert.Equal(typeof(TestNotString).GetProperty(nameof(TestNotString.Other)), exp.Property);
        }
        public void ThrowsIfNoConstraints()
        {
            var builder = new ValidatorBuilder <object>();

            builder.AddEmptyClass();

            var exception = Assert.Throws <ValidatorBuilderException>(() => builder.Build());

            Assert.Equal(Errors.NoConstraintsFound, exception.Id);
            Assert.NotNull(exception.Message);
            Assert.Null(exception.Property);
            Assert.Null(exception.Type);
        }
Example #6
0
        public void ThrowsOnUnknown()
        {
            var builder = new ValidatorBuilder <object>();

            builder.AddKnownType <int>();
            builder.AddEmptyConstraint(true);
            var validator = builder.Build();
            var exception = Assert.Throws <ValidatorBuilderException>(() => validator.Validate(string.Empty, null));

            Assert.Equal(typeof(string), exception.Type);
            Assert.Equal(Errors.UnknownType, exception.Id);
            Assert.Null(exception.Property);
        }
Example #7
0
        public void EnumerableProperties()
        {
            // Arrange
            var message = Guid.NewGuid().ToString();
            var key     = Guid.NewGuid().ToString();
            var builder = new ValidatorBuilder <object>();

            builder.AddKnownType <TestWithEnumerableProperty1>();
            builder.AddTypeConstraint <StringItem>((i, ctx) =>
            {
                if (i.Item is null)
                {
                    ctx.RaiseError(message);
                }
            }, key);

            var validator = builder.Build();

            var context = new TestValidationContext();
            var item    = new TestWithEnumerableProperty1
            {
                Items = new[]
                {
                    new StringItem {
                        Item = "1"
                    },
                    new StringItem {
                        Item = null
                    },
                    new StringItem {
                        Item = "3"
                    },
                },
            };

            // Act
            validator.Validate(item, context.Context);

            // Assert
            var error = Assert.Single(context.Errors);

            Assert.Equal(message, error.Message);
            Assert.Equal(key, error.Id);

            Assert.Collection(context.Items,
                              i => Assert.Equal(item, i),
                              i => Assert.Equal(item.Items, i),
                              i => Assert.Equal(item.Items[0], i),
                              i => Assert.Equal(item.Items[1], i),
                              i => Assert.Equal(item.Items[2], i));
        }
        public void BuilderContextIsDisposed()
        {
            var builder = new ValidatorBuilder <object>();
            var context = default(BuilderContext <object>);

            builder.AddEmptyConstraint(withType: true);
            builder.AddPropertyConstraintFactory((property, ctx) =>
            {
                context = ctx;
                return(null);
            });

            var validator = builder.Build();

            Assert.NotNull(context);
            Assert.Throws <ObjectDisposedException>(() => context.GetOrSetState(string.Empty, key => string.Empty));
        }
        public void DoesNotIncludeNoGetter()
        {
            var builder = new ValidatorBuilder <object>();

            builder.AddKnownType <NoGetter>();
            builder.AddEmptyConstraint(true);
            builder.AddConstraint(p =>
            {
                if (p == typeof(NoGetter).GetProperty(nameof(NoGetter.Test)))
                {
                    Assert.False(true, "Should not get here as there is no getter");
                }

                return(null);
            });

            Assert.NotNull(builder.Build());
        }
Example #10
0
        public void TestStruct()
        {
            var count   = 0;
            var builder = new ValidatorBuilder <object>();

            builder.AddKnownType <CustomStruct>();
            builder.AddPropertyFilter(_ => true);
            builder.AddConstraint(_ => new DelegateConstraint(() =>
            {
                count++;
                return(true);
            }));
            var validator = builder.Build();

            validator.Validate(default(CustomStruct), null);

            Assert.Equal(1, count);
        }
Example #11
0
        public void NoPattern()
        {
            var builder = new ValidatorBuilder <object>();

            builder.AddRegexAttributeConstraint <RegexAttribute>(r => r.Pattern);
            builder.AddKnownType <TestNoPattern>();
            builder.AddEmptyConstraint();

            var validator = builder.Build();
            var context   = new TestValidationContext();

            var item = new TestNoPattern {
                Test = "hello"
            };

            validator.Validate(item, context.Context);

            Assert.Empty(context.Errors);
            Assert.Single(context.Items);
        }
Example #12
0
        public void SamePatternIsCached()
        {
            var builder = new ValidatorBuilder <object>();

            builder.AddRegexAttributeConstraint <RegexAttribute>(r => r.Pattern);
            builder.AddKnownType <DuplicatePattern>();

            var validator = builder.Build();
            var instance  = new DuplicatePattern();
            var context   = new TestValidationContext();

            validator.Validate(instance, context.Context);

            Assert.Equal(2, context.Errors.Count);

            var error1 = Assert.IsType <Regex>(context.Errors[0].Context);
            var error2 = Assert.IsType <Regex>(context.Errors[1].Context);

            Assert.Same(error1, error2);
        }
Example #13
0
        public void AbstractPropertyTest()
        {
            var count   = 0;
            var builder = new ValidatorBuilder <object>();

            builder.AddKnownType <TestWithAbstractProperty>();
            builder.AddPropertyFilter <TestWithAbstractProperty>();
            builder.AddConstraint(_ => new DelegateConstraint(instanceValue =>
            {
                var value = Assert.IsType <string>(instanceValue);
                Assert.Equal(nameof(TestWithDerivedAbstractProperty), value);
                count++;
                return(true);
            }));
            var validator = builder.Build();

            validator.Validate(new TestWithDerivedAbstractProperty(), null);

            Assert.Equal(1, count);
        }
Example #14
0
        public void OverrideThrowsOnUnknown()
        {
            var count = 0;

            var builder = new ValidatorBuilder <object>();

            builder.AddEmptyConstraint(true);
            builder.AddKnownType <int>();
            var validator = builder.Build();

            var context = new ValidationContext <object>
            {
                OnUnknownType = type =>
                {
                    Assert.Equal(typeof(string), type);
                    count++;
                },
            };

            validator.Validate(string.Empty, context);

            Assert.Equal(1, count);
        }
        public void RecursiveDescentBySubtype()
        {
            var instance1 = new TestClass();
            var instance  = new TestClass
            {
                Value = instance1,
            };

            instance1.Value = instance;

            var builder = new ValidatorBuilder <object>();

            builder.AddKnownType <TestClass>();
            builder.AddPropertyFilter <TestClassBase>();
            builder.AddEmptyConstraint();
            var validator = builder.Build();
            var context   = new TestValidationContext();

            validator.Validate(instance, context.Context);

            Assert.Empty(context.Errors);
            Assert.Equal(2, context.Items.Count);
        }
Example #16
0
        public void PatternNoObserver()
        {
            var builder = new ValidatorBuilder <object>();

            builder.AddRegexAttributeConstraint <RegexAttribute>(r => r.Pattern);
            builder.AddKnownType <Test1>();
            var validator = builder.Build();

            var item    = new Test1();
            var items   = new List <object>();
            var context = new ValidationContext <object>
            {
                OnItem = items.Add,
            };

            var exception = Assert.Throws <ValidationException>(() => validator.Validate(item, context));

            Assert.Equal(item, exception.Error.Instance);
            Assert.Equal(typeof(Test1).GetProperty(nameof(Test1.Test)), exception.Error.Property);

            var single = Assert.Single(items);

            Assert.Same(item, single);
        }
        public void SimpleProperty()
        {
            const string Value   = "hello!";
            var          count   = 0;
            var          builder = new ValidatorBuilder <object>();

            builder
            .ForType <Test1>()
            .AddProperty(t => t.Instance);

            var test = new Test1
            {
                Instance = new Test2
                {
                    Member = Value,
                },
            };

            builder.AddConstraint(_ => new DelegateConstraint(value =>
            {
                if (value is string)
                {
                    Assert.Equal(Value, value);
                    count++;
                }

                return(true);
            }));

            var validator = builder.Build();
            var context   = new TestValidationContext();

            validator.Validate(test, context.Context);

            Assert.Equal(1, count);
        }
Example #18
0
        public void StaticProperty()
        {
            var builder = new ValidatorBuilder <object>();
            var count   = 0;

            builder.AddEmptyConstraint(true);
            builder.AddKnownType <StaticPropertyBoolean>();
            builder.AddPropertyConstraintFactory((property, _) =>
            {
                count++;
                Assert.NotEqual(typeof(StaticPropertyBoolean).GetProperty(nameof(StaticPropertyBoolean.Test)), property);

                return(null);
            });

            var validator = builder.Build();
            var context   = new TestValidationContext();

            validator.Validate(new StaticPropertyBoolean(), context.Context);

            Assert.Equal(1, count);
            Assert.Empty(context.Errors);
            Assert.Empty(context.UnknownTypes);
        }
 /// <summary>
 /// Adds a constraint generator that depends on a <see cref="PropertyInfo"/>.
 /// </summary>
 /// <param name="builder">Current <see cref="ValidatorBuilder{TOptions}"/>.</param>
 /// <param name="factory">The factory to create a constraint given an attribute instance.</param>
 /// <returns>A <see cref="ConstraintBuilder{TValue}"/> instance.</returns>
 public static ConstraintBuilder <TState> AddConstraint <TState>(this ValidatorBuilder <TState> builder, Func <PropertyInfo, IConstraint <TState> > factory) => builder.AddPropertyConstraintFactory((property, _) => factory(property));
Example #20
0
 /// <summary>
 /// Add a regular expression constraint using <see cref="RegularExpressionAttribute"/>.
 /// </summary>
 /// <param name="builder">The current <see cref="ValidatorBuilder{TState}"/>.</param>
 /// <typeparam name="TState">Custom type supplied for the validation.</typeparam>
 /// <returns>A constraint builder instance.</returns>
 public static ConstraintBuilder <TState, string> AddRegexAttributeConstraint <TState>(this ValidatorBuilder <TState> builder)
 {
     return(builder
            .AddRegexAttributeConstraint <RegularExpressionAttribute>(pattern => pattern.Pattern));
 }
 internal ValidatorPropertyBuilder(ValidatorBuilder <TState> builder)
 {
     _builder = builder;
     _builder.AddKnownType <TType>();
 }