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 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 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)); }
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 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 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 ValidationPlan_executes_multiple_rules_and_ValidationFailure_count_is_correct() { var plan = new ValidationPlan <Species>(); var rule1 = Validate.That <Species>(s => s.Name != "cat"); var rule2 = Validate.That <Species>(s => s.Genus.Name != "felis"); plan.AddRule(rule1); plan.AddRule(rule2); var report = plan.Execute(new Species { Name = "cat", Genus = new Genus { Name = "felis" } }); Assert.AreEqual(2, report.Failures.Count()); }
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 Nested_Rules_within_ValidationPlan_are_not_iterated_when_plan_is_iterated() { var plan = new ValidationPlan <string>(); Enumerable.Range(1, 10).ForEach(_ => plan.AddRule(new ValidationPlan <string> { Validate.That <string>(s => false), Validate.That <string>(s => false) })); Assert.AreEqual(10, plan.Count()); }
public void ValidationFailures_use_MessageGenerator_assigned_to_ValidationPlan() { var messageGenerator = new MessageTemplate("result"); var plan = new ValidationPlan <string>(messageGenerator); // always fail plan.AddRule(s => false); var failure = plan.Execute("test").Failures.First(); failure.Message.Should().Be("result"); }
public void ValidationReport_contains_rules_that_were_called() { var plan = new ValidationPlan <string>(); for (var i = 0; i < 10; i++) { var rule = Validate.That <string>(_ => true); plan.AddRule(rule); } var report = plan.Execute(string.Empty); Assert.AreEqual(10, report.RulesExecuted.Count()); }
public void ValidationPlan_evaluates_all_when_strategy_is_EvaluateAll() { var plan = new ValidationPlan <string> { Strategy = EvaluationStrategy <string> .EvaluateAll }; for (int i = 0; i < 10; i++) { plan.AddRule(_ => false); } Assert.That(plan.Execute(null).Evaluations.Count(), Is.EqualTo(10)); }
public void ErrorCode_can_be_declared_using_optional_parameter_on_AddRule() { var plan = new ValidationPlan <Species>(); plan.AddRule(s => s.Name.Length < 20, rule => rule.WithErrorCode("oops")); var speciesWithLongName = new Species { Name = "this name is way too long" }; var reportOnSpeciesWithLongName = plan.Execute(speciesWithLongName); Assert.AreEqual("oops", reportOnSpeciesWithLongName.Failures.First().ErrorCode); }
public void ValidationPlan_halts_on_first_failure_when_strategy_is_HaltOnFirstFailure() { // TODO: (ValidationPlan_halts_on_first_failure_when_strategy_is_HaltOnFirstFailure) var plan = new ValidationPlan <string> { Strategy = EvaluationStrategy <string> .HaltOnFirstFailure }; for (int i = 0; i < 10; i++) { plan.AddRule(_ => false); } Assert.That(plan.Execute(null).Evaluations.Count(), Is.EqualTo(1)); }
public void Nested_validations_can_be_supported() { ValidationPlan <Account> accountValidator = new ValidationPlan <Account>() .ConfigureFromAttributes(); ValidationPlan <Order> orderValidator = new ValidationPlan <Order>() .ConfigureFromAttributes(); orderValidator.AddRule(o => accountValidator.Check(o.Account)); var order = new Order { Account = new Account() }; ValidationReport report = orderValidator.Execute(order); Assert.That(report.Failures.Any(f => f.Message == "What's your name?" && f.Target == order.Account)); Assert.That(report.Failures.Any(f => f.Message == "You can't place an order for nothing." && f.Target == order)); }
public void ValidationScope_raises_events_as_evaluations_are_added_to_child_scopes_on_other_threads() { int evaluationCount = 0; var plan = new ValidationPlan <IEnumerable <string> >(); // parallelize plan.AddRule( ss => ss.Parallel(Validate.That <string>(s => false).Check)); using (var scope = new ValidationScope()) { scope.RuleEvaluated += (o, e) => Interlocked.Increment(ref evaluationCount); plan.Execute(Enumerable.Range(1, 30).Select(i => i.ToString())); } Assert.AreEqual(31, evaluationCount); }
public void Iterative_nested_tasks_can_be_executed_with_short_circuiting() { var innerRule = Validate.That <Individual>(i => false); var plan = new ValidationPlan <Species>(); plan.AddRule(s => s.Individuals.All(innerRule.Check)); var species = new Species(); species.Individuals.Add(new Individual()); species.Individuals.Add(new Individual()); species.Individuals.Add(new Individual()); species.Individuals.Add(new Individual()); var task = plan.ExecuteAsync(species); var report = task.Result; Assert.That(report.Failures.Count(f => f.Target is Individual), Is.EqualTo(1)); }
public void Iterative_nested_tasks_are_all_executed() { var innerRule = Validate.That <Individual>(i => false); var plan = new ValidationPlan <Species>(); plan.AddRule(s => s.Individuals.Every(innerRule.Check)); var species = new Species(); species.Individuals.Add(new Individual()); species.Individuals.Add(new Individual()); species.Individuals.Add(new Individual()); species.Individuals.Add(new Individual()); var task = plan.ExecuteAsync(species); var report = task.Result; Assert.AreEqual(4, report.Failures.Where(f => f.Target is Individual).Count()); }
public void Iterative_nested_rules_can_be_executed_with_short_circuiting() { var innerRule = Validate.That <Individual>(i => false); var plan = new ValidationPlan <Species>(); plan.AddRule(s => s.Individuals.All(innerRule.Check)); var species = new Species(); species.Individuals.Add(new Individual()); species.Individuals.Add(new Individual()); species.Individuals.Add(new Individual()); species.Individuals.Add(new Individual()); var report = plan.Execute(species); Assert.AreEqual(1, report.Failures.Where(f => f.Target is Individual).Count()); }
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 When_the_same_plan_is_run_on_two_threads_simultaneously_they_each_report_success_and_failure_correctly() { var barrier = new Barrier(2); var plan = new ValidationPlan <string>(); plan.AddRule(s => { barrier.SignalAndWait(); return(s != "fail"); }); var succeed = Task <ValidationReport> .Factory.StartNew(() => plan.Execute("succeed")); var fail = Task <ValidationReport> .Factory.StartNew(() => plan.Execute("fail")); succeed.Wait(); fail.Wait(); Assert.That(succeed.Result.HasFailures, Is.False); Assert.That(fail.Result.HasFailures, Is.True); }
/// <summary> /// Specifies an authorization rule for a principal applying a specific command type to a specific resource type. /// </summary> /// <param name="requirement">The requirement.</param> /// <param name="message">A message indicating the reason for the authorization failure. This message is intended for diagnostic and monitoring purposes only.</param> public static void Requires(Func <TPrincipal, TCommand, TResource, bool> requirement, string message = null) { ValidateTypeParameters(); ValidationPlan <IAuthorizationQuery <TResource, TCommand, TPrincipal> > plan = AuthorizationPolicy.For <TResource, TCommand, TPrincipal>().ValidationPlan; var defaultRule = AuthorizationPolicy <TResource, TCommand, TPrincipal> .Default; if (plan.Any(rule => rule == defaultRule)) { // the default rule will cause the authz check to fail, so we remove it plan.Remove(defaultRule); } var authzRule = Validate .That <IAuthorizationQuery <TResource, TCommand, TPrincipal> >(query => requirement(query.Principal, query.Command, query.Resource)) .WithErrorMessage(message ?? ("Requirement for " + typeof(TCommand))); plan.AddRule(authzRule); }
public void Can_customize_message_differently_for_the_same_rule_in_different_plans() { IValidationMessageGenerator generator1 = new MessageTemplate("one"); IValidationMessageGenerator generator2 = new MessageTemplate("two"); var rule = Validate.That <string>(s => false); var plan1 = new ValidationPlan <string>(generator1); var plan2 = new ValidationPlan <string>(generator2); plan1.AddRule(rule); plan2.AddRule(rule); var report1 = plan1.Execute(""); var report2 = plan2.Execute(""); Assert.AreEqual(1, report1.Failures.Count()); Assert.AreEqual(1, report2.Failures.Count()); Assert.AreEqual("one", report1.Failures.First().Message); Assert.AreEqual("two", report2.Failures.First().Message); }
public void A_rule_can_be_instantiated_and_evaluated_during_another_rules_execution() { var plan = new ValidationPlan <Species>(); plan.AddRule( s => s.Individuals.Every( Validate.That <Individual>(ind => ind.Species == s).Check)); Console.WriteLine(plan); 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 }); plan.Execute(cat).HasFailures.Should().BeFalse(); 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(2, report.Failures.Count()); Assert.That(report.Failures.Any(failure => failure.Target == fido)); Assert.That(report.Failures.Any(failure => failure.Target == cat)); }