void FindAndAddChildrenToOpenList(ValidatedValueBasis currentBasis, ValidatedValue currentValue, Queue <ValidatedValueBasis> openList, ResolvedValidationOptions options) { if (!currentValue.ValueResponse.IsSuccess) { return; } var actualValue = currentValue.GetActualValue(); if (!(currentBasis.ManifestValue.CollectionItemValue is null || actualValue is null)) { openList.Enqueue(new ValidatedValueBasis(currentBasis.ManifestValue.CollectionItemValue, currentValue.ValueResponse, currentValue)); } foreach (var childManifestValue in currentBasis.GetChildManifestValues()) { var valueResponse = valueProvider.GetValueToBeValidated(childManifestValue, actualValue, options); openList.Enqueue(new ValidatedValueBasis(childManifestValue, valueResponse, currentValue)); } }
/// <summary> /// Gets the validated value. /// </summary> /// <param name="basis">A validated-value basis.</param> /// <returns>A validated value.</returns> public ValidatedValue GetValidatedValue(ValidatedValueBasis basis) { var valueIdentity = GetIdentity(basis); var value = new ValidatedValue { ManifestValue = basis.ManifestValue, ValueResponse = basis.ValidatedValueResponse, ValueIdentity = valueIdentity, ParentValue = basis.Parent, CollectionItemOrder = basis.CollectionOrder, }; value.Rules = basis.GetManifestRules() .Select(manifestRule => new ExecutableRule { ValidatedValue = value, ManifestRule = manifestRule, RuleLogic = validationLogicFactory.GetValidationLogic(manifestRule), RuleIdentifier = new RuleIdentifier(manifestRule, valueIdentity), }) .ToList(); return(value); }
/// <summary> /// Gets the validated value from the specified manifest value and object to be validated. /// </summary> /// <param name="manifestValue">The manifest value.</param> /// <param name="objectToBeValidated">The object to be validated.</param> /// <param name="options">The validation options.</param> /// <returns>A validated value, including a hierarchy of descendent values and /// the rules which may be executed upon those values.</returns> public ValidatedValue GetValidatedValue(ManifestValue manifestValue, object objectToBeValidated, ResolvedValidationOptions options) { if (manifestValue is null) { throw new ArgumentNullException(nameof(manifestValue)); } if (options is null) { throw new ArgumentNullException(nameof(options)); } var openList = new Queue <ValidatedValueBasis>(new [] { new ValidatedValueBasis(manifestValue, new SuccessfulGetValueToBeValidatedResponse(objectToBeValidated), null) }); ValidatedValue rootValidatedValue = null; while (openList.Any()) { var currentBasis = openList.Dequeue(); if (currentBasis.IsCircularReference()) { continue; } if (currentBasis.ValidatedValueResponse is IgnoredGetValueToBeValidatedResponse) { continue; } var currentValues = GetValidatedValues(currentBasis); if (rootValidatedValue is null && currentValues.Any()) { rootValidatedValue = currentValues.First(); } foreach (var value in currentValues) { FindAndAddChildrenToOpenList(currentBasis, value, openList, options); } } return(rootValidatedValue); }
/// <summary> /// Gets all of the executable rules from the validated value and all of that value's descendents. /// </summary> /// <remarks> /// <para> /// This is a linear, forwards-only breadth-first search which traverses the complete hierarchy of validated values /// and collects all of the <see cref="ExecutableRule"/> instances from all of them. /// </para> /// </remarks> /// <param name="validatedValue">The root validated value for which to get all rules.</param> /// <returns>A flattened collection of executable rules from the manifest value.</returns> static IEnumerable <ExecutableRule> GetFlattenedExecutableRules(ValidatedValue validatedValue) { var openList = new Queue <ValidatedValue>(new [] { validatedValue }); while (openList.Any()) { var currentValue = openList.Dequeue(); foreach (var rule in currentValue.Rules) { yield return(rule); } foreach (var child in currentValue.ChildValues) { openList.Enqueue(child); } foreach (var collectionItem in currentValue.CollectionItems) { openList.Enqueue(collectionItem); } } }
static ValidatedValue GetMatchingValidatedValue(ManifestRuleIdentifier dependencyIdentifier, ValidatedValue validatedValue) { if (Equals(validatedValue.ManifestValue, dependencyIdentifier.ManifestValue)) { return(validatedValue); } return(validatedValue.ChildValues .FirstOrDefault(child => Equals(child.ManifestValue, dependencyIdentifier.ManifestValue))); }
public void GetRulesWithDependenciesShouldReturnAnObjectWithDependencyExecutableRulesWhereItHasADependencyUponAParentValue([Frozen] IGetsAllExecutableRules executableRulesProvider, [ManifestModel] ManifestValue manifestValue, object objectToBeValidated, IValidationLogic logic, ManifestRule manifestRule, ManifestRule manifestDependency, [ExecutableModel] ValidatedValue validatedValue, [ExecutableModel] ValidatedValue parentValue, ExecutableRulesAndDependenciesProvider sut, ResolvedValidationOptions validationOptions) { var rule = new ExecutableRule { ValidatedValue = validatedValue, ManifestRule = manifestRule, RuleLogic = logic }; validatedValue.ParentValue = parentValue; var dependency = new ExecutableRule { ValidatedValue = parentValue, ManifestRule = manifestDependency, RuleLogic = logic }; parentValue.ManifestValue = manifestDependency.Identifier.ManifestValue; parentValue.Rules.Add(dependency); Mock.Get(executableRulesProvider) .Setup(x => x.GetExecutableRules(manifestValue, objectToBeValidated, validationOptions)) .Returns(new [] { rule, dependency }); rule.ManifestRule.DependencyRules.Clear(); rule.ManifestRule.DependencyRules.Add(manifestDependency.Identifier); var result = sut.GetRulesWithDependencies(manifestValue, objectToBeValidated, validationOptions); Assert.That(result.First(x => x.ExecutableRule == rule).Dependencies, Is.EqualTo(new[] { dependency })); }
public void GetRulesWithDependenciesShouldThrowIfTheMatchingValueDoesNotHaveTheSpecifiedRule([Frozen] IGetsAllExecutableRules executableRulesProvider, [ManifestModel] ManifestValue manifestValue, object objectToBeValidated, IValidationLogic logic, ManifestRule manifestRule, ManifestRule manifestDependency, [ExecutableModel] ValidatedValue validatedValue, [ExecutableModel] ValidatedValue parentValue, ExecutableRulesAndDependenciesProvider sut, ResolvedValidationOptions validationOptions) { var rule = new ExecutableRule { ValidatedValue = validatedValue, ManifestRule = manifestRule, RuleLogic = logic }; validatedValue.ParentValue = parentValue; var dependency = new ExecutableRule { ValidatedValue = parentValue, ManifestRule = manifestDependency, RuleLogic = logic }; parentValue.ManifestValue = manifestDependency.Identifier.ManifestValue; Mock.Get(executableRulesProvider) .Setup(x => x.GetExecutableRules(manifestValue, objectToBeValidated, validationOptions)) .Returns(new [] { rule, dependency }); rule.ManifestRule.DependencyRules.Clear(); rule.ManifestRule.DependencyRules.Add(manifestDependency.Identifier); Assert.That(() => sut.GetRulesWithDependencies(manifestValue, objectToBeValidated, validationOptions), Throws.InstanceOf <ValidationException>()); }
public void GetExecutableRulesShouldReturnAFlattenedListOfRulesIncludingCollectionItemRules([Frozen] IGetsValidatedValue validatedValueProvider, [ExecutableModel] ValidatedValue rootValue, [ExecutableModel] ValidatedValue childVal1, [ExecutableModel] ValidatedValue childVal2, [ExecutableModel] ValidatedValue collectionValue1, [ExecutableModel] ValidatedValue collectionValue2, [ExecutableModel] ExecutableRule rule1, [ExecutableModel] ExecutableRule rule2, [ExecutableModel] ExecutableRule rule3, [ExecutableModel] ExecutableRule rule4, [ExecutableModel] ExecutableRule rule5, [ExecutableModel] ExecutableRule rule6, ExecutableRulesFromValidatedValueProvider sut, [ManifestModel] ManifestValue manifestValue, object valueToBeValidated, ResolvedValidationOptions validationOptions) { rootValue.ChildValues.Add(childVal1); rootValue.ChildValues.Add(childVal2); childVal2.CollectionItems.Add(collectionValue1); childVal2.CollectionItems.Add(collectionValue2); rootValue.Rules.Add(rule1); childVal1.Rules.Add(rule2); childVal1.Rules.Add(rule3); childVal2.Rules.Add(rule4); collectionValue1.Rules.Add(rule5); collectionValue2.Rules.Add(rule6); Mock.Get(validatedValueProvider).Setup(x => x.GetValidatedValue(manifestValue, valueToBeValidated, validationOptions)).Returns(rootValue); var expected = new[] { rule1, rule2, rule3, rule4, rule5, rule6 }; Assert.That(() => sut.GetExecutableRules(manifestValue, valueToBeValidated, validationOptions), Is.EquivalentTo(expected)); }
public void GetValidatedValueShouldCreateCollectionValueFromFactoryIfManifestHasACollectionItemWithinAChildItem([Frozen] IGetsValidatedValueFromBasis valueFromBasisFactory, [Frozen] IGetsEnumerableItemsToBeValidated enumerableProvider, ValidatedValueFactory sut, IEnumerable <object> validatedValue, ResolvedValidationOptions validationOptions, [ExecutableModel] ValidatedValue value, [ExecutableModel] ValidatedValue childValue, [ExecutableModel] ValidatedValue collectionValue, object item) { var manifestValue = new ManifestValue { ValidatedType = typeof(object), Children = new[] { new ManifestValue { ValidatedType = typeof(IEnumerable <object>), CollectionItemValue = new ManifestCollectionItem { ValidatedType = typeof(object) }, } } }; Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue.Children.First()))) .Returns(childValue); Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue))) .Returns(value); value.ManifestValue = manifestValue; childValue.ManifestValue = manifestValue.Children.First(); collectionValue.ManifestValue = manifestValue.Children.First().CollectionItemValue; childValue.ValueResponse = new SuccessfulGetValueToBeValidatedResponse(validatedValue); Mock.Get(enumerableProvider) .Setup(x => x.GetEnumerableItems(validatedValue, manifestValue.Children.First().CollectionItemValue.ValidatedType)) .Returns(new[] { item }); Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue.Children.First().CollectionItemValue&& b.GetActualValue() == item))) .Returns(collectionValue); var result = sut.GetValidatedValue(manifestValue, validatedValue, validationOptions); Assert.Multiple(() => { Assert.That(result.CollectionItems, Is.Empty, "Root value has no collection items"); Assert.That(result.ChildValues, Has.Count.EqualTo(1), "Root value has one child value"); Assert.That(result.ChildValues.FirstOrDefault()?.CollectionItems, Has.Count.EqualTo(1), "Root value has one collection item"); }); }
public void GetValidatedValueShouldCreateCollectionValueFromFactoryIfManifestHasACollectionItem([Frozen] IGetsValidatedValueFromBasis valueFromBasisFactory, [Frozen] IGetsEnumerableItemsToBeValidated enumerableProvider, ValidatedValueFactory sut, IEnumerable <object> validatedValue, ResolvedValidationOptions validationOptions, [ExecutableModel] ValidatedValue value, [ExecutableModel] ValidatedValue collectionValue, object item) { var manifestValue = new ManifestValue { ValidatedType = typeof(IEnumerable <object>), CollectionItemValue = new ManifestCollectionItem { ValidatedType = typeof(object) }, }; Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue))) .Returns(value); value.ValueResponse = new SuccessfulGetValueToBeValidatedResponse(validatedValue); Mock.Get(enumerableProvider) .Setup(x => x.GetEnumerableItems(validatedValue, manifestValue.CollectionItemValue.ValidatedType)) .Returns(new[] { item }); Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue.CollectionItemValue && b.GetActualValue() == item))) .Returns(collectionValue); sut.GetValidatedValue(manifestValue, validatedValue, validationOptions); Mock.Get(valueFromBasisFactory) .Verify(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue.CollectionItemValue)), Times.Once); }
public void GetValidatedValueShouldBeAbleToProcessACollectionWithinACollection([Frozen] IGetsValidatedValueFromBasis valueFromBasisFactory, [Frozen] IGetsValueToBeValidated valueProvider, [Frozen] IGetsEnumerableItemsToBeValidated enumerableProvider, ValidatedValueFactory sut, [NoAutoProperties] ComplexObject validatedValue, ResolvedValidationOptions validationOptions, [ExecutableModel] ValidatedValue val, [ExecutableModel] ValidatedValue firstCollection, [ExecutableModel] ValidatedValue secondCollection, [ExecutableModel] ValidatedValue item) { var manifestValue = new ManifestValue { ValidatedType = typeof(ComplexObject), Children = new [] { new ManifestValue { ValidatedType = typeof(ICollection <List <ComplexObject> >), MemberName = nameof(ComplexObject.DoubleCollection), AccessorFromParent = obj => ((ComplexObject)obj).DoubleCollection, CollectionItemValue = new ManifestCollectionItem { ValidatedType = typeof(List <ComplexObject>), CollectionItemValue = new ManifestCollectionItem { ValidatedType = typeof(ComplexObject), } }, }, }, }; var child = (ManifestValue)manifestValue.Children.Single(); child.Parent = manifestValue; child.CollectionItemValue.Parent = manifestValue; child.CollectionItemValue.CollectionItemValue.Parent = manifestValue; validatedValue.DoubleCollection = new List <List <ComplexObject> > { new List <ComplexObject> { new ComplexObject() } }; Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue))) .Returns(val); val.ValueResponse = new SuccessfulGetValueToBeValidatedResponse(validatedValue); Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == child))) .Returns(firstCollection); firstCollection.ValueResponse = new SuccessfulGetValueToBeValidatedResponse(validatedValue.DoubleCollection); Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == child.CollectionItemValue))) .Returns(secondCollection); secondCollection.ValueResponse = new SuccessfulGetValueToBeValidatedResponse(validatedValue.DoubleCollection.First()); Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == child.CollectionItemValue.CollectionItemValue))) .Returns(item); item.ValueResponse = new SuccessfulGetValueToBeValidatedResponse(validatedValue.DoubleCollection.First().First()); object validatedVal = validatedValue; Mock.Get(valueProvider) .Setup(x => x.GetValueToBeValidated(manifestValue, validatedValue, validationOptions)) .Returns(new SuccessfulGetValueToBeValidatedResponse(validatedValue)); object doubleCollection = firstCollection.ValueResponse; Mock.Get(valueProvider) .Setup(x => x.GetValueToBeValidated(child, validatedValue, validationOptions)) .Returns(new SuccessfulGetValueToBeValidatedResponse(doubleCollection)); Mock.Get(enumerableProvider) .Setup(x => x.GetEnumerableItems(validatedValue.DoubleCollection, child.CollectionItemValue.ValidatedType)) .Returns(validatedValue.DoubleCollection); Mock.Get(enumerableProvider) .Setup(x => x.GetEnumerableItems(validatedValue.DoubleCollection.First(), child.CollectionItemValue.CollectionItemValue.ValidatedType)) .Returns(validatedValue.DoubleCollection.First()); var result = sut.GetValidatedValue(manifestValue, validatedValue, validationOptions); Mock.Get(valueFromBasisFactory) .Verify(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == child.CollectionItemValue.CollectionItemValue)), Times.Once); }
public void GetValidatedValueShouldBeAbleToProcessAGrandchildManifestValue([Frozen] IGetsValidatedValueFromBasis valueFromBasisFactory, [Frozen] IGetsValueToBeValidated valueProvider, ValidatedValueFactory sut, [NoAutoProperties] ComplexObject validatedValue, [NoAutoProperties] ComplexObject childValue, string grandchildValue, ResolvedValidationOptions validationOptions, [ExecutableModel] ValidatedValue val, [ExecutableModel] ValidatedValue childVal, [ExecutableModel] ValidatedValue grandchildVal) { var manifestValue = new ManifestValue { ValidatedType = typeof(ComplexObject), }; var childManifest = new ManifestValue { Parent = manifestValue, ValidatedType = typeof(ComplexObject), }; var grandchildManifest = new ManifestValue { Parent = childManifest, ValidatedType = typeof(string), }; manifestValue.Children.Add(childManifest); childManifest.Children.Add(grandchildManifest); Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue))) .Returns(val); val.ValueResponse = new SuccessfulGetValueToBeValidatedResponse(validatedValue); val.ManifestValue = manifestValue; Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == childManifest))) .Returns(childVal); childVal.ValueResponse = new SuccessfulGetValueToBeValidatedResponse(childValue); childVal.ManifestValue = childManifest;; Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == grandchildManifest))) .Returns(grandchildVal); grandchildVal.ValueResponse = new SuccessfulGetValueToBeValidatedResponse(grandchildValue); grandchildVal.ManifestValue = grandchildManifest; object child = childValue; Mock.Get(valueProvider) .Setup(x => x.GetValueToBeValidated(childManifest, validatedValue, validationOptions)) .Returns(new SuccessfulGetValueToBeValidatedResponse(child)); object grandchild = grandchildValue; Mock.Get(valueProvider) .Setup(x => x.GetValueToBeValidated(grandchildManifest, childValue, validationOptions)) .Returns(new SuccessfulGetValueToBeValidatedResponse(grandchild)); var result = sut.GetValidatedValue(manifestValue, validatedValue, validationOptions); Mock.Get(valueFromBasisFactory) .Verify(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == childManifest && b.GetActualValue() == child)), Times.Once); Mock.Get(valueFromBasisFactory) .Verify(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == grandchildManifest && b.GetActualValue() == grandchild)), Times.Once); }
public void GetValidatedValueShouldNotProcessAChildManifestValueIfTheActualValueCannotBeRetrieved([Frozen] IGetsValidatedValueFromBasis valueFromBasisFactory, [Frozen] IGetsValueToBeValidated valueProvider, ValidatedValueFactory sut, [NoAutoProperties] ComplexObject validatedValue, string childValue, ResolvedValidationOptions validationOptions, [ExecutableModel] ValidatedValue val, [ExecutableModel] ValidatedValue childVal) { var manifestValue = new ManifestValue { ValidatedType = typeof(ComplexObject), }; var childManifest = new ManifestValue { Parent = manifestValue, ValidatedType = typeof(string), }; manifestValue.Children.Add(childManifest); Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue))) .Returns(val); Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == childManifest))) .Returns(childVal); object child = childValue; Mock.Get(valueProvider) .Setup(x => x.GetValueToBeValidated(childManifest, validatedValue, validationOptions)) .Returns(new IgnoredGetValueToBeValidatedResponse()); var result = sut.GetValidatedValue(manifestValue, validatedValue, validationOptions); Mock.Get(valueFromBasisFactory) .Verify(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == childManifest && b.ValidatedValueResponse == child)), Times.Never); }
public void GetValidatedValueShouldReturnSingleValueForManifestValueWithNoParentOrChildrenOrRules([Frozen] IGetsValidatedValueFromBasis valueFromBasisFactory, ValidatedValueFactory sut, object validatedValue, ResolvedValidationOptions validationOptions, [ExecutableModel] ValidatedValue value) { var manifestValue = new ManifestValue { ValidatedType = typeof(object) }; Mock.Get(valueFromBasisFactory) .Setup(x => x.GetValidatedValue(It.Is <ValidatedValueBasis>(b => b.ManifestValue == manifestValue))) .Returns(value); var result = sut.GetValidatedValue(manifestValue, validatedValue, validationOptions); Assert.That(result, Is.SameAs(value)); }
public async Task ExecuteRuleAsyncShouldExecuteRuleLogicWithCorrectValidatedInstances([Frozen] IGetsRuleContext contextFactory, [RuleContext] RuleContext context, [ExecutableModel] ExecutableRule rule, SingleRuleExecutor sut, ValidatedValue validatedValue, ValidatedValue parentValue, [RuleResult] RuleResult expectedResult) { rule.ValidatedValue = validatedValue; validatedValue.ParentValue = parentValue; Mock.Get(contextFactory).Setup(x => x.GetRuleContext(rule)).Returns(context); Mock.Get(rule.RuleLogic) .Setup(x => x.GetResultAsync(It.IsAny <object>(), It.IsAny <object>(), It.IsAny <RuleContext>(), It.IsAny <CancellationToken>())) .Returns(() => Task.FromResult(expectedResult)); await sut.ExecuteRuleAsync(rule); Mock.Get(rule.RuleLogic) .Verify(x => x.GetResultAsync(validatedValue.GetActualValue(), parentValue.GetActualValue(), It.IsAny <RuleContext>(), It.IsAny <CancellationToken>()), Times.Once); }