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 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 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());
            }
        }
        public void Success_and_failure_messages_can_be_configured_separately()
        {
            var plan = new ValidationPlan <string>
            {
                Validate.That <string>(s => s.As("value").Length.As("length") > 3.As("min"))
                .WithErrorMessage("Fail! Your string {value} is only {length} characters.")
                .WithSuccessMessage("Win! '{value}' is more than {min} characters.")
            };

            var failure = plan.Execute("hi").Evaluations.Single();
            var success = plan.Execute("hello").Evaluations.Single();

            StringAssert.Contains("Fail!", failure.Message);
            StringAssert.Contains("Win!", success.Message);
        }
Beispiel #5
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 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));
        }
        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 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());
        }
        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());
        }
        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);
        }
        public void executes_each_step()
        {
            thePlan.Execute(theContext);

            r1.AssertWasCalled(x => x.Validate(theContext));
            r2.AssertWasCalled(x => x.Validate(theContext));
        }
        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"));
        }
        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 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 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"));
        }
        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);
        }
Beispiel #18
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()));
        }
Beispiel #19
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 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 virtual void When_precondition_and_cloned_precondition_are_both_used_they_are_evaluated_as_equivalent()
        {
            var notEmptyRule = Validate.That <string>(s => !string.IsNullOrEmpty(s));
            var tooLongRule  = Validate.That <string>(s => s.Length < 10);

            var plan = new ValidationPlan <string>
            {
                notEmptyRule.WithErrorCode("empty!"),
                tooLongRule.When(notEmptyRule).WithErrorCode("too long!"),
            };

            var report = plan.Execute("");

            Assert.AreEqual(1, report.Failures.Count(f => f.ErrorCode == "empty!"));

            report = plan.Execute("sdff3'4otj;4kth;kdfjsekfjpf4");
            Assert.AreEqual(1, report.Failures.Count(f => f.ErrorCode == "too long!"));
        }
        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 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 Dependencies_can_be_declared_using_optional_parameter_on_AddRule()
        {
            var plan = new ValidationPlan <Species>();

            plan.AddRule(s => s.Name.Length < 20,
                         only => only.When(s => s.Name != null));

            var speciesWithNullName = new Species {
                Name = null
            };
            var speciesWithLongName = new Species {
                Name = "this name is way too long"
            };

            var reportOnSpeciesWithNullName = plan.Execute(speciesWithNullName);
            var reportOnSpeciesWithLongName = plan.Execute(speciesWithLongName);

            Assert.AreEqual(0, reportOnSpeciesWithNullName.Failures.Count());
            Assert.AreEqual(1, reportOnSpeciesWithLongName.Failures.Count());
        }
        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);
        }
        ValidationPlan_collection_initializer_can_be_used_to_combine_rules_with_error_code_assignments()
        {
            var rule1 = Validate.That <string>(s => s != null);
            var rule2 = Validate.That <string>(s => s.Length > 0);

            var plan = new ValidationPlan <string>
            {
                rule1.WithErrorCode("null check"),
                rule2.When(rule1).WithErrorCode("length check")
            };

            var report = plan.Execute(null);

            Assert.AreEqual(1, report.Failures.Count(), report.ToString());
            Assert.AreEqual("null check", report.Failures.First().ErrorCode);

            report = plan.Execute(string.Empty);
            Assert.AreEqual(1, report.Failures.Count());
            Assert.AreEqual("length check", report.Failures.First().ErrorCode);
        }
        public void ForMember_using_func_returns_expected_member_name_for_immediate_property()
        {
            var rule = new ValidationPlan <Species>
            {
                Validate.That <Species>(s => false).ForMember(s => s.Individuals)
            };

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

            Assert.AreEqual("Individuals", report.Failures.Single().MemberPath);
        }
        public void Parameters_are_flushed_after_rule_evaluation_when_rule_passes()
        {
            var plan = new ValidationPlan <string>
            {
                Validate.That <string>(s => true.As("pass")),
                Validate.That <string>(s => false.As("fail"))
            };

            var report = plan.Execute("");

            Assert.IsFalse(report.Failures.First().Parameters.ContainsKey("pass"));
        }
        public void IValidationRule_when_check_passes_no_failures_are_added_to_report()
        {
            var rule = Validate.That <string>(_ => true);

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

            var report = plan.Execute("");

            Assert.AreEqual(0, report.Failures.Count());
        }
        public void Multiple_validation_parameters_can_be_written_to_error_message_with_params_in_order()
        {
            var rule = Validate
                       .That <int>(i => i > 0.As("start") & i < 365.As("end"))
                       .WithMessage("must be between {start} and {end}");
            var plan = new ValidationPlan <int> {
                rule
            };
            var report = plan.Execute(9785);

            Assert.AreEqual("must be between 0 and 365", report.Failures.First().Message);
        }