public void ErrorCode_can_be_set_differently_for_the_same_rule_in_different_contexts()
        {
            var nameNotEmpty =
                Validate
                .That <Species>(s => !string.IsNullOrEmpty(s.Name))
                .WithErrorCode("NameCannotBeEmpty");

            var plan = new ValidationPlan <Species>();

            plan.AddRule(
                s => s.Individuals.Every(
                    i => nameNotEmpty
                    .WithErrorCode("IndividualsSpeciesNameCannotBeEmpty")
                    .Check(i.Species)));
            plan.AddRule(nameNotEmpty.WithErrorCode("SpeciesNameCannotBeEmpty"));

            var cat    = new Species();
            var fluffy = new Individual {
                Species = cat
            };

            cat.Individuals.Add(fluffy);
            var report = plan.Execute(cat);

            Console.WriteLine(report);
            Assert.AreEqual(3, report.Failures.Count());
            Assert.AreEqual(1, report.Failures.Count(f => f.ErrorCode == "SpeciesNameCannotBeEmpty"));
            Assert.AreEqual(1, report.Failures.Count(f => f.ErrorCode == "IndividualsSpeciesNameCannotBeEmpty"));
        }
        public virtual void Outer_validation_scope_aggregates_rules_from_inner_scopes()
        {
            var plan = new ValidationPlan <string>
            {
                Validate.That <string>(s => true)
            };

            using (var scope = new ValidationScope())
            {
                using (new ValidationScope())
                {
                    plan.Execute("");
                }
                using (new ValidationScope())
                {
                    plan.Execute("");
                }
                using (new ValidationScope())
                {
                    plan.Execute("");
                }

                Assert.AreEqual(3, scope.Evaluations.Count());
            }
        }
Example #3
0
        /// <summary>
        ///   Adds validatiom rules for any DataAnnotations attributes on the validated type.
        /// </summary>
        /// <typeparam name="T"> The type to be validated. </typeparam>
        /// <param name="plan"> The validation plan to which to add DataAnnotations validation rules. </param>
        /// <returns> </returns>
        public static ValidationPlan <T> ConfigureFromAttributes <T>(this ValidationPlan <T> plan)
        {
            ValidationRule <T> rule = null;

            rule = Validate.That <T>(t =>
            {
                var context = new ValidationContext(t, null, null);
                var results = new List <ValidationResult>();
                var isValid = Validator.TryValidateObject(t, context, results, true);

                // add results to the validation scope
                results.ForEach(result =>
                {
                    result
                    .MemberNames
                    .ForEach(member =>
                             ValidationScope.Current.AddEvaluation(
                                 new FailedEvaluation(
                                     target: t,
                                     rule: rule)
                    {
                        Message    = result.ErrorMessage,
                        MemberPath = member
                    }));
                });

                return(isValid);
            });

            var clone = (ValidationPlan <T>)plan.Clone();

            clone.AddRule(rule);
            return(clone);
        }
Example #4
0
        /// <summary>
        ///   Adds a dynamic property to a rule, which will be copied to any <see cref="FailedEvaluation" /> generated by the rule.
        /// </summary>
        /// <typeparam name="TTarget"> The <see cref="Type" /> of the target. </typeparam>
        /// <typeparam name="T"> The <see cref="Type" /> of the dynamic property. </typeparam>
        /// <param name="plan"> The validation plan. </param>
        /// <param name="value"> The value. </param>
        /// <returns> A clone of the source validation rule. </returns>
        public static ValidationPlan <TTarget> With <TTarget, T>(this ValidationPlan <TTarget> plan, T value)
        {
            var clone = (ValidationPlan <TTarget>)plan.Clone();

            clone.Set(value);
            return(clone);
        }
Example #5
0
        private static void InitializeTwitterPlan()
        {
            isTwitterFreeUrl = new ValidationPlan <string>();
            isTwitterFreeUrl.AddRule(
                s =>
            {
                var client = new WebClient();

                try
                {
                    var response = client.DownloadString(s.As("url"));
                    return(!response.ToLower().Contains("twitter"));
                }
                catch (WebException ex)
                {
                    ex.Message.As("error");
                    return(false);
                }
                catch (Exception ex)
                {
                    ex.As("error");
                    return(false);
                }
            },
                only => only
                .When(isValidHttpUrl)
                .WithErrorMessage("Oh no! The page at {url} contains the word 'twitter'")
                .WithSuccessMessage("The page at {url} doesn't contain the word 'twitter'")
                );
        }
        public void Nested_plan_evaluates_all_rules()
        {
            var rule1Evaluated = false;
            var rule2Evaluated = false;
            var rule3Evaluated = false;
            var plan           = new ValidationPlan <string>()
                                 .AddRule(s => true)
                                 .AddRule(new ValidationPlan <string>()
                                          .AddRule(_ =>
            {
                rule1Evaluated = true;
                return(false);
            }, fail => fail.WithErrorMessage("1"))
                                          .AddRule(_ =>
            {
                rule2Evaluated = true;
                return(false);
            }, fail => fail.WithErrorMessage("2"))
                                          .AddRule(_ =>
            {
                rule3Evaluated = true;
                return(false);
            }, fail => fail.WithErrorMessage("3")));

            var report = plan.Execute(null);

            Assert.That(rule1Evaluated);
            Assert.That(rule2Evaluated);
            Assert.That(rule3Evaluated);
            Assert.That(report.Evaluations.Count(),
                        Is.EqualTo(5));
        }
Example #7
0
        public void Rules_within_a_ValidationPlan_can_use_APM_signatures_and_run_synchronously()
        {
            var hasAwesomeTag = Validate.Async <string>(
                setup: url =>
            {
                var request = new ApmOperation <string, string>(s =>
                                                                Task <string> .Factory.StartNew(() => "<div>" + s + "</div>"));
                var tcs = new TaskCompletionSource <string>();
                Task <string> .Factory
                .FromAsync(request.BeginInvoke,
                           request.EndInvoke,
                           url,
                           state: null)
                .ContinueWith(
                    t => tcs.Complete(t, () => t.Result));
                return(tcs.Task);
            },
                validate: html => html.As("page").Contains("<awesome>"))
                                .WithErrorMessage("{page} is missing the <awesome> tag!");

            var plan = new ValidationPlan <string>
            {
                isValidHttpUrl,
                hasAwesomeTag.When(isValidHttpUrl)
            };

            var result = plan.Execute("http://microsoft.com");

            Console.WriteLine(result);

            // TODO: (Rules_within_a_ValidationPlan_can_use_APM_signatures_and_run_synchronously)
            Assert.Fail("Test not written");
        }
        public void MemberPath_can_be_set_differently_for_the_same_rule_in_different_contexts()
        {
            var nameNotEmpty =
                Validate.That <Species>(s => !string.IsNullOrEmpty(s.Name));

            var plan = new ValidationPlan <Species>();

            plan.AddRule(nameNotEmpty.ForMember("species"));
            plan.AddRule(
                s => s.Individuals.Every(
                    i => nameNotEmpty.ForMember("subspecies").Check(i.Species)));

            var cat    = new Species();
            var fluffy = new Individual {
                Species = cat
            };

            cat.Individuals.Add(fluffy);
            var report = plan.Execute(cat);

            Console.WriteLine(report);
            Assert.AreEqual(3, report.Failures.Count());
            Assert.AreEqual(1, report.Failures.Where(f => f.MemberPath == "species").Count());
            Assert.AreEqual(1, report.Failures.Where(f => f.MemberPath == "subspecies").Count());
        }
        public void Same_rule_in_different_plans_can_have_different_error_codes()
        {
            var rule = Validate.That <string>(
                s => !s.Contains("A") & !s.Contains("B"));

            var planA = new ValidationPlan <string>
            {
                rule.WithErrorCode("string contains A")
            };

            var planB = new ValidationPlan <string>
            {
                rule.WithErrorCode("string contains B")
            };

            var report = planA.Execute("A");

            Console.WriteLine(report);
            Assert.IsTrue(report.Failures.Any(f => f.ErrorCode == "string contains A"),
                          "The error code for the rule changed");

            report = planB.Execute("B");
            Console.WriteLine(report);
            Assert.IsTrue(report.Failures.Any(f => f.ErrorCode == "string contains B"));
        }
        Intermediate_preconditions_that_return_true_prevent_later_rules_from_being_evaluated_using_actual_validation_rule
            ()
        {
            var speciesNotNull        = Validate.That <Species>(t => t != null);
            var validSpeciesName      = Validate.That <Species>(t => !string.IsNullOrEmpty(t.Name));
            var notTooManyIndividuals = Validate
                                        .That <Species>(t => t.Individuals.Count() <= 45)
                                        .When(s => s.Individuals != null);
            var noDuplicates =
                Validate.That <Species>(t => t.Individuals.Distinct().Count() == t.Individuals.Count());

            var plan = new ValidationPlan <Species>
            {
                speciesNotNull,
                new ValidationPlan <Species>
                {
                    validSpeciesName,
                    notTooManyIndividuals,
                    noDuplicates.When(notTooManyIndividuals),
                }.When(speciesNotNull)
            };

            var report = plan.Execute(new Species {
                Name = "cat", Individuals = null
            });

            Assert.AreEqual(0, report.Failures.Count());
        }
        When_precondition_is_first_class_rule_in_plan_and_has_different_error_code_assigned_precondition_is_only_evaluated_once
            ()
        {
            var count = 0;
            Func <Species, bool> counter = s =>
            {
                count++;
                return(false);
            };

            var precondition = Validate.That <Species>(s => counter(s));

            var plan = new ValidationPlan <Species>
            {
                precondition.WithErrorCode("some code"),
                // these rules will throw if the precondition does not short circuit them
                Validate.That <Species>(species => species.Name.Length > 0)
                .When(precondition),
                Validate.That <Species>(species => !species.Name.Contains("!"))
                .When(precondition)
            };

            var nameless = new Species {
                Name = null
            };

            Assert.DoesNotThrow(() => plan.Execute(nameless));

            Assert.AreEqual(1, count);
        }
        public void One_rule_can_be_evaluated_inside_another_without_framework_being_aware_of_it()
        {
            var individualNameRule = Validate.That <Individual>(i => !string.IsNullOrEmpty(i.Name))
                                     .WithErrorCode("Name");
            var speciesNameRule = Validate
                                  .That <Species>(s => !string.IsNullOrEmpty(s.Name))
                                  .WithErrorCode("Name");
            var speciesIndividualsRule = Validate.That <Species>(s => s.Individuals.All(individualNameRule.Check));

            var plan = new ValidationPlan <Species>();

            plan.AddRule(speciesNameRule);
            plan.AddRule(speciesIndividualsRule);

            var cat    = new Species("Felis silvestris");
            var fluffy = new Individual {
                Name = "Fluffy", Species = cat
            };
            var boots = new Individual {
                Name = "Boots", Species = cat
            };

            cat.Individuals.AddRange(new[] { fluffy, boots });

            Assert.IsFalse(plan.Execute(cat).HasFailures);

            // adding an individual without a name causes the plan to evaluate to false
            cat.Individuals.Add(new Individual {
                Species = cat
            });
            var report = plan.Execute(cat);

            Console.WriteLine(report);
            Assert.IsTrue(report.HasFailures);
        }
        public void Rules_can_be_aggregated_from_function_calls()
        {
            var plan = new ValidationPlan <Species>();

            plan.AddRule(Validate.That <Species>(IndividualsAreAllOfSpecies().Check));

            var cat    = new Species("Felis silvestris");
            var fluffy = new Individual {
                Name = "Fluffy", Species = cat
            };
            var boots = new Individual {
                Name = "Boots", Species = cat
            };

            cat.Individuals.AddRange(new[] { fluffy, boots });

            Assert.IsFalse(plan.Execute(cat).HasFailures);

            // adding an individual without a name causes the plan to evaluate to false
            var fido = new Individual {
                Name = "Fido", Species = new Species("Canis familiaris")
            };

            cat.Individuals.Add(fido);

            var report = plan.Execute(cat);

            Assert.IsTrue(report.HasFailures);
            Console.WriteLine(report);
            Assert.AreEqual(3, report.Failures.Count());
            Assert.That(report.Failures.Any(failure => failure.Target == fido));
            Assert.That(report.Failures.Any(failure => failure.Target == cat));
        }
        public virtual void When_precondition_is_used_in_nested_plans_it_is_not_reevaluated()
        {
            var count = 0;
            Func <string, bool> counter = s =>
            {
                count++;
                return(true);
            };

            var precondition = Validate.That(counter).WithMessage("precondition");

            var plan = new ValidationPlan <string>
            {
                Validate.That <string>(s => s.Length > 0).When(precondition),
                new ValidationPlan <string>
                {
                    Validate.That <string>(s => s.Contains("a")).When(precondition),
                    Validate.That <string>(s => s.Contains("b")).When(precondition),
                }
            };

            plan.Execute("ab");

            Assert.AreEqual(1, count);
        }
        public virtual void When_precondition_is_not_in_plan_and_precondition_fails_precondition_is_only_evaluated_once
            ()
        {
            var count = 0;
            Func <Species, bool> counter = s =>
            {
                count++;
                return(false);
            };

            var precondition = Validate.That <Species>(s => counter(s));

            var plan = new ValidationPlan <Species>
            {
                // these rules will throw if the precondition does not short circuit them
                Validate.That <Species>(species => true)
                .When(precondition),
                Validate.That <Species>(species => true)
                .When(precondition)
            };

            plan.Execute(null);

            // we only want the precondition called once. the value should be stored.
            Assert.AreEqual(1, count);
        }
        When_specifying_multiple_preconditions_and_one_precondition_fails_subsequent_preconditions_are_not_evaluated
            ()
        {
            var falsePreconditionCallCount = 0;
            var truePreconditionCallCount  = 0;
            var falsePrecondition          = Validate.That <string>(_ =>
            {
                falsePreconditionCallCount++;
                return(false);
            });
            var truePrecondition = Validate.That <string>(_ =>
            {
                truePreconditionCallCount++;
                return(true);
            });

            // this rule will fail but should be short circuited
            var rule = Validate.That <string>(s => false)
                       .When(falsePrecondition)
                       .When(truePrecondition);

            var plan = new ValidationPlan <string> {
                rule
            };

            var report = plan.Execute("");

            falsePreconditionCallCount.Should().Be(1);
            truePreconditionCallCount.Should().Be(0);
            Assert.True(!report.Failures.Any(f => f.Rule == rule));
        }
        public void ConfigureFromAttributes_returns_a_new_instance_of_the_ValidationPlan()
        {
            var plan           = new ValidationPlan <Account>();
            var configuredPlan = plan.ConfigureFromAttributes();

            Assert.That(plan != configuredPlan);
        }
Example #18
0
        public void SetUp()
        {
            thePlan = new ValidationPlan(typeof(string), new ValidationStep[0]);

            theDescription = Description.For(thePlan);
            theStepList    = theDescription.BulletLists.Single();
        }
Example #19
0
        public void When_items_are_validated_in_parallel_the_rule_evaluations_are_reported_correctly()
        {
            DescribeThread();
            var plan = new ValidationPlan <IEnumerable <string> >();

            plan.AddRule(urls => urls.Parallel(url =>
            {
                if (string.IsNullOrWhiteSpace(Thread.CurrentThread.Name))
                {
                    Thread.CurrentThread.Name = url;
                }
                Console.WriteLine(
                    "checking {0} in scope {2} on thread {1} ", url,
                    Thread.CurrentThread.ManagedThreadId,
                    ValidationScope.Current);
                return(isReachableUrl.Check(url));
            }));

            var report = plan.Execute(Urls());

            Console.WriteLine(report);

            Assert.That(report.Evaluations.Count(),
                        Is.GreaterThan(Urls().Count()));
        }
        public void ValidationPlan_collection_initializer_can_be_used_to_combine_plans()
        {
            var plan1 = new ValidationPlan <string>
            {
                Validate.That <string>(s => s != "a").WithErrorCode("RULE 1")
            };
            var plan2 = new ValidationPlan <string>
            {
                Validate.That <string>(s => s.Length > 1).WithErrorCode("RULE 2")
            };

            plan1.WithErrorCode("PLAN 1");
            plan2.WithErrorCode("PLAN 2");

            var combinedPlan = new ValidationPlan <string>
            {
                plan1,
                plan2
            };

            var report = combinedPlan.Execute("a");

            Console.WriteLine(report);
            Assert.AreEqual(4, report.Failures.Count());
        }
Example #21
0
        public void When_the_same_plan_is_run_on_multiple_threads_simultaneously_they_each_report_parameters_correctly()
        {
            var barrier = new Barrier(20);
            var plan    = new ValidationPlan <string>(new DebugMessageGenerator())
            {
                Validate.That <string>(s =>
                {
                    DescribeThread();

                    // report input parameter
                    s.As("s");
                    barrier.SignalAndWait();
                    return(false);
                }).WithErrorMessage("the parameter was {s}")
            };

            var tasks =
                new ConcurrentBag <Task <ValidationReport> >(
                    Enumerable.Range(1, 20).Select(
                        i => Task <ValidationReport> .Factory.StartNew(() =>
            {
                var report = plan.Execute(i.ToString());
                Console.WriteLine(report);
                return(report);
            })));

            Task.WaitAll(tasks.ToArray());

            Enumerable.Range(1, 20).ForEach(i =>
                                            tasks.Any(
                                                t => t.Result.Failures.Any(f => f.Parameters["s"].Equals(i.ToString()))));
        }
        public void Dependencies_can_be_declared_within_expression_using_Validate_That()
        {
            var plan = new ValidationPlan <IEnumerable <Species> >();

            plan
            .AddRule(list =>
                     list.Every(species =>
                                Validate
                                .That <Species>(s => s.Name.Length < 20)
                                .WithErrorCode("name too long")
                                .When(
                                    Validate
                                    .That <Species>(s => s.Name != null)
                                    .WithErrorCode("name null"))
                                .Check(species)));

            var listToValidate = new[]
            {
                new Species {
                    Name = null
                },
                new Species {
                    Name = "this name is way too "
                }
            };

            var report = plan.Execute(listToValidate);

            Console.WriteLine(report);
            Assert.AreEqual(2, report.Failures.Count());
            Assert.AreEqual(1, report.Failures.Count(f => f.ErrorCode == "name too long"));
        }
        public void When_precondition_is_first_class_rule_in_plan_precondition_is_only_evaluated_once()
        {
            var callCount    = 0;
            var precondition = Validate.That <Species>(_ =>
            {
                callCount++;
                return(false);
            });

            var plan = new ValidationPlan <Species>
            {
                precondition,
                // these rules will throw if the precondition does not short circuit them
                Validate.That <Species>(species => species.Name.Length > 0)
                .When(precondition),
                Validate.That <Species>(species => !species.Name.Contains("!"))
                .When(precondition)
            };

            var nameless = new Species {
                Name = null
            };

            plan.Execute(nameless);

            callCount.Should().Be(1);
        }
Example #24
0
        public void Continuation_rules_do_not_start_setup_tasks_when_precondition_fails()
        {
            // TODO: (Continuation_rules_do_not_start_setup_tasks_when_precondition_fails)
            var setupStarted  = false;
            var hasAwesomeTag = Validate.Async <string>(
                setup: url =>
            {
                setupStarted = true;
                return(Task <string> .Factory.StartNew(() => "<div>not awesome</div>"));
            },
                validate: html => html.As("page").Contains("<awesome>"))
                                .WithErrorMessage("{page} is missing the <awesome> tag!");

            var plan = new ValidationPlan <string>
            {
                isValidHttpUrl,
                hasAwesomeTag.When(isValidHttpUrl)
            };

            var task = plan.ExecuteAsync("hhttp://bing.com");

            task.Wait();
            Console.WriteLine(task.Result);
            Assert.That(setupStarted, Is.False);
        }
        public void ValidationPlans_can_be_combined()
        {
            var plan1 = new ValidationPlan <Species>();

            plan1.AddRule(
                Validate.That <Species>(
                    s =>
                    s.Individuals.Every(
                        i => Validate.That <Individual>(
                            ind => ind.Species == s)
                        .WithErrorCode("species mismatch")
                        .Check(i))
                    )
                );

            var plan2 = new ValidationPlan <Species>();

            plan2.AddRule(
                Validate.That <Species>(
                    s =>
                    s.Individuals.Every(
                        Validate.That <Individual>(
                            ind => !string.IsNullOrEmpty(ind.Name))
                        .WithErrorCode("empty name")
                        .Check)
                    )
                );

            var species = new Species {
                Name = "Felis silvestris"
            };
            var nameless = new Individual {
                Name = "", Species = species
            };

            species.Individuals.Add(nameless);
            species.Individuals.Add(new Individual {
                Name = "Garfield", Species = species
            });
            species.Individuals.Add(new Individual {
                Name = "Morris", Species = species
            });
            var fido = new Individual {
                Name = "Fido"
            };

            species.Individuals.Add(fido);

            var report = ValidationPlan <Species> .Merge(
                new KeyValuePair <string, ValidationPlan <Species> >("one", plan1),
                new KeyValuePair <string, ValidationPlan <Species> >("two", plan2)
                ).Execute(species);

            Assert.That(report.Failures.Count(f => f.ErrorCode == "one"), Is.EqualTo(2));
            Assert.That(report.Failures.Count(f => f.ErrorCode == "two"), Is.EqualTo(2));
            Assert.That(report.Failures.Count(f => f.Target == fido), Is.EqualTo(1));
            Assert.That(report.Failures.Count(f => f.Target == nameless), Is.EqualTo(1));
        }
        public void Rules_within_ValidationPlan_can_be_iterated()
        {
            var plan = new ValidationPlan <string>();

            Enumerable.Range(1, 10).ForEach(_AppDomain =>
                                            plan.AddRule(Validate.That <string>(s => false)));

            Assert.AreEqual(10, plan.Count());
        }
        public void FailedEvaluation_Message_is_set_from_data_annotation_ErrorMessage()
        {
            ValidationPlan <Account> plan = new ValidationPlan <Account>()
                                            .ConfigureFromAttributes();

            ValidationReport report = plan.Execute(new Account());

            Assert.That(report.Failures.Any(f => f.Message == "What's your name?"));
        }
        public void Null_rules_cannot_be_added_to_a_ValidationPlans()
        {
            var plan = new ValidationPlan <string>();

            IValidationRule <string> nullRule = null;

            Action addNullRule = () => plan.Add(nullRule);

            addNullRule.ShouldThrow <ArgumentNullException>();
        }
        public void FailedEvaluation_target_is_set_to_the_instance_that_was_evaluated()
        {
            ValidationPlan <Account> plan = new ValidationPlan <Account>()
                                            .ConfigureFromAttributes();
            var account = new Account();

            ValidationReport report = plan.Execute(account);

            Assert.That(report.Failures.Any(f => f.Target == account));
        }
        public void ForMember_using_func_returns_expected_member_name_for_chained_property()
        {
            var rule = new ValidationPlan <Phylum>
            {
                Validate.That <Phylum>(s => false).ForMember(p => p.Kingdom.Name)
            };

            var report = rule.Execute(new Phylum());

            Assert.AreEqual("Kingdom.Name", report.Failures.Single().MemberPath);
        }
        public void finds_the_rules_from_all_steps()
        {
            var r1 = new StubRule();
            var r2 = new StubRule();
            var r3 = new ClassFieldValidationRules();
            var r4 = new ClassFieldValidationRules();

            var src1 = new ConfiguredValidationSource(new IValidationRule[] { r1, r3 });
            var src2 = new ConfiguredValidationSource(new IValidationRule[] { r2, r4 });

            var step1 = ValidationStep.FromSource(typeof(object), src1);
            var step2 = ValidationStep.FromSource(typeof(object), src2);

            var plan = new ValidationPlan(typeof (object), new[] {step1, step2});
            plan.FindRules<StubRule>().ShouldHaveTheSameElementsAs(r1, r2);
        }
        public void SetUp()
        {
            theModel = new ContactModel();
            theType = theModel.GetType();

            r1 = MockRepository.GenerateStub<IValidationRule>();
            r2 = MockRepository.GenerateStub<IValidationRule>();
            r3 = MockRepository.GenerateStub<IValidationRule>();

            theMatchingSource = ConfiguredValidationSource.For(type => type == theType, r1, r2);
            theOtherSource = ConfiguredValidationSource.For(type => type == typeof(int), r3);

            theGraph = ValidationGraph.BasicGraph();
            theGraph.RegisterSource(theMatchingSource);
            theGraph.RegisterSource(theOtherSource);

            theContext = ValidationContext.For(theModel);

            thePlan = ValidationPlan.For(theType, theGraph);
        }
        public void SetUp()
        {
            thePlan = new ValidationPlan(typeof(string), new ValidationStep[0]);

            theDescription = Description.For(thePlan);
            theStepList = theDescription.BulletLists.Single();
        }