// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Xunit; namespace Microsoft.AspNetCore.Mvc.Internal { public class ExplicitIndexCollectionValidationStrategyTest { [Fact] public void EnumerateElements_List() { // Arrange var model = new List() { 2, 3, 5 }; var metadata = TestModelMetadataProvider.CreateDefaultProvider().GetMetadataForType(typeof(List)); var strategy = new ExplicitIndexCollectionValidationStrategy(new string[] { "zero", "one", "two" }); // Act var enumerator = strategy.GetChildren(metadata, "prefix", model); // Assert Assert.Collection( BufferEntries(enumerator).OrderBy(e => e.Key), e => { Assert.Equal("prefix[one]", e.Key); Assert.Equal(3, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }, e => { Assert.Equal("prefix[two]", e.Key); Assert.Equal(5, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }, e => { Assert.Equal("prefix[zero]", e.Key); Assert.Equal(2, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }); } [Fact] public void EnumerateElements_Dictionary() { // Arrange var model = new Dictionary() { { 2, "two" }, { 3, "three" }, { 5, "five" }, }; var metadata = TestModelMetadataProvider.CreateDefaultProvider().GetMetadataForType(typeof(List)); var strategy = new ExplicitIndexCollectionValidationStrategy(new string[] { "zero", "one", "two" }); // Act var enumerator = strategy.GetChildren(metadata, "prefix", model); // Assert Assert.Collection( BufferEntries(enumerator).OrderBy(e => e.Key), e => { Assert.Equal("prefix[one]", e.Key); Assert.Equal(new KeyValuePair(3, "three"), e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }, e => { Assert.Equal("prefix[two]", e.Key); Assert.Equal(new KeyValuePair(5, "five"), e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }, e => { Assert.Equal("prefix[zero]", e.Key); Assert.Equal(new KeyValuePair(2, "two"), e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }); } [Fact] public void EnumerateElements_TwoEnumerableImplemenations() { // Arrange var model = new TwiceEnumerable(new int[] { 2, 3, 5 }); var metadata = TestModelMetadataProvider.CreateDefaultProvider().GetMetadataForType(typeof(TwiceEnumerable)); var strategy = new ExplicitIndexCollectionValidationStrategy(new string[] { "zero", "one", "two" }); // Act var enumerator = strategy.GetChildren(metadata, "prefix", model); // Assert Assert.Collection( BufferEntries(enumerator).OrderBy(e => e.Key), e => { Assert.Equal("prefix[one]", e.Key); Assert.Equal(3, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }, e => { Assert.Equal("prefix[two]", e.Key); Assert.Equal(5, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }, e => { Assert.Equal("prefix[zero]", e.Key); Assert.Equal(2, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }); } [Fact] public void EnumerateElements_RunOutOfIndices() { // Arrange var model = new List() { 2, 3, 5 }; var metadata = TestModelMetadataProvider.CreateDefaultProvider().GetMetadataForType(typeof(List)); var strategy = new ExplicitIndexCollectionValidationStrategy(new string[] { "zero", "one", }); // Act var enumerator = strategy.GetChildren(metadata, "prefix", model); // Assert Assert.Collection( BufferEntries(enumerator).OrderBy(e => e.Key), e => { Assert.Equal("prefix[one]", e.Key); Assert.Equal(3, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }, e => { Assert.Equal("prefix[zero]", e.Key); Assert.Equal(2, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }); } [Fact] public void EnumerateElements_RunOutOfElements() { // Arrange var model = new List() { 2, 3, }; var metadata = TestModelMetadataProvider.CreateDefaultProvider().GetMetadataForType(typeof(List)); var strategy = new ExplicitIndexCollectionValidationStrategy(new string[] { "zero", "one", "two" }); // Act var enumerator = strategy.GetChildren(metadata, "prefix", model); // Assert Assert.Collection( BufferEntries(enumerator).OrderBy(e => e.Key), e => { Assert.Equal("prefix[one]", e.Key); Assert.Equal(3, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }, e => { Assert.Equal("prefix[zero]", e.Key); Assert.Equal(2, e.Model); Assert.Same(metadata.ElementMetadata, e.Metadata); }); } // 'int' is chosen by validation because it's declared on the more derived type. private class TwiceEnumerable : List, IEnumerable { private readonly IEnumerable _enumerable; public TwiceEnumerable(IEnumerable enumerable) { _enumerable = enumerable; } IEnumerator IEnumerable.GetEnumerator() { return _enumerable.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { throw new InvalidOperationException(); } } private List BufferEntries(IEnumerator enumerator) { var entries = new List(); while (enumerator.MoveNext()) { entries.Add(enumerator.Current); } return entries; } } }