Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,396 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Web.Http.Metadata;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.ModelBinding;
using System.Web.Http.ValueProviders;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Internal
{
public class CollectionModelBinderUtilTest
{
[Fact]
public void CreateOrReplaceCollection_OriginalModelImmutable_CreatesNewInstance()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new ReadOnlyCollection<int>(new int[0]), typeof(ICollection<int>))
};
// Act
CollectionModelBinderUtil.CreateOrReplaceCollection(bindingContext, new[] { 10, 20, 30 }, () => new List<int>());
// Assert
int[] newModel = (bindingContext.Model as ICollection<int>).ToArray();
Assert.Equal(new[] { 10, 20, 30 }, newModel);
}
[Fact]
public void CreateOrReplaceCollection_OriginalModelMutable_UpdatesOriginalInstance()
{
// Arrange
List<int> originalInstance = new List<int> { 10, 20, 30 };
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => originalInstance, typeof(ICollection<int>))
};
// Act
CollectionModelBinderUtil.CreateOrReplaceCollection(bindingContext, new[] { 40, 50, 60 }, () => new List<int>());
// Assert
Assert.Same(originalInstance, bindingContext.Model);
Assert.Equal(new[] { 40, 50, 60 }, originalInstance.ToArray());
}
[Fact]
public void CreateOrReplaceCollection_OriginalModelNotCollection_CreatesNewInstance()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ICollection<int>))
};
// Act
CollectionModelBinderUtil.CreateOrReplaceCollection(bindingContext, new[] { 10, 20, 30 }, () => new List<int>());
// Assert
int[] newModel = (bindingContext.Model as ICollection<int>).ToArray();
Assert.Equal(new[] { 10, 20, 30 }, newModel);
}
[Fact]
public void CreateOrReplaceDictionary_DisallowsDuplicateKeys()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(Dictionary<string, int>))
};
// Act
CollectionModelBinderUtil.CreateOrReplaceDictionary(
bindingContext,
new[]
{
new KeyValuePair<string, int>("forty-two", 40),
new KeyValuePair<string, int>("forty-two", 2),
new KeyValuePair<string, int>("forty-two", 42)
},
() => new Dictionary<string, int>());
// Assert
IDictionary<string, int> newModel = bindingContext.Model as IDictionary<string, int>;
Assert.Equal(new[] { "forty-two" }, newModel.Keys.ToArray());
Assert.Equal(42, newModel["forty-two"]);
}
[Fact]
public void CreateOrReplaceDictionary_DisallowsNullKeys()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(Dictionary<string, int>))
};
// Act
CollectionModelBinderUtil.CreateOrReplaceDictionary(
bindingContext,
new[]
{
new KeyValuePair<string, int>("forty-two", 42),
new KeyValuePair<string, int>(null, 84)
},
() => new Dictionary<string, int>());
// Assert
IDictionary<string, int> newModel = bindingContext.Model as IDictionary<string, int>;
Assert.Equal(new[] { "forty-two" }, newModel.Keys.ToArray());
Assert.Equal(42, newModel["forty-two"]);
}
[Fact]
public void CreateOrReplaceDictionary_OriginalModelImmutable_CreatesNewInstance()
{
// Arrange
ReadOnlyDictionary<string, string> originalModel = new ReadOnlyDictionary<string, string>();
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => originalModel, typeof(IDictionary<string, string>))
};
// Act
CollectionModelBinderUtil.CreateOrReplaceDictionary(
bindingContext,
new Dictionary<string, string>
{
{ "Hello", "World" }
},
() => new Dictionary<string, string>());
// Assert
IDictionary<string, string> newModel = bindingContext.Model as IDictionary<string, string>;
Assert.NotSame(originalModel, newModel);
Assert.Equal(new[] { "Hello" }, newModel.Keys.ToArray());
Assert.Equal("World", newModel["Hello"]);
}
[Fact]
public void CreateOrReplaceDictionary_OriginalModelMutable_UpdatesOriginalInstance()
{
// Arrange
Dictionary<string, string> originalInstance = new Dictionary<string, string>
{
{ "dog", "Canidae" },
{ "cat", "Felidae" }
};
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => originalInstance, typeof(IDictionary<string, string>))
};
// Act
CollectionModelBinderUtil.CreateOrReplaceDictionary(
bindingContext,
new Dictionary<string, string>
{
{ "horse", "Equidae" },
{ "bear", "Ursidae" }
},
() => new Dictionary<string, string>());
// Assert
Assert.Same(originalInstance, bindingContext.Model);
Assert.Equal(new[] { "horse", "bear" }, originalInstance.Keys.ToArray());
Assert.Equal("Equidae", originalInstance["horse"]);
Assert.Equal("Ursidae", originalInstance["bear"]);
}
[Fact]
public void CreateOrReplaceDictionary_OriginalModelNotDictionary_CreatesNewInstance()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IDictionary<string, string>))
};
// Act
CollectionModelBinderUtil.CreateOrReplaceDictionary(
bindingContext,
new Dictionary<string, string>
{
{ "horse", "Equidae" },
{ "bear", "Ursidae" }
},
() => new Dictionary<string, string>());
// Assert
IDictionary<string, string> newModel = bindingContext.Model as IDictionary<string, string>;
Assert.Equal(new[] { "horse", "bear" }, newModel.Keys.ToArray());
Assert.Equal("Equidae", newModel["horse"]);
Assert.Equal("Ursidae", newModel["bear"]);
}
[Fact]
public void GetIndexNamesFromValueProviderResult_ValueProviderResultIsNull_ReturnsNull()
{
// Act
IEnumerable<string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(null);
// Assert
Assert.Null(indexNames);
}
[Fact]
public void GetIndexNamesFromValueProviderResult_ValueProviderResultReturnsEmptyArray_ReturnsNull()
{
// Arrange
ValueProviderResult vpResult = new ValueProviderResult(new string[0], "", null);
// Act
IEnumerable<string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(vpResult);
// Assert
Assert.Null(indexNames);
}
[Fact]
public void GetIndexNamesFromValueProviderResult_ValueProviderResultReturnsNonEmptyArray_ReturnsArray()
{
// Arrange
ValueProviderResult vpResult = new ValueProviderResult(new[] { "foo", "bar", "baz" }, "foo,bar,baz", null);
// Act
IEnumerable<string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(vpResult);
// Assert
Assert.NotNull(indexNames);
Assert.Equal(new[] { "foo", "bar", "baz" }, indexNames.ToArray());
}
[Fact]
public void GetIndexNamesFromValueProviderResult_ValueProviderResultReturnsNull_ReturnsNull()
{
// Arrange
ValueProviderResult vpResult = new ValueProviderResult(null, null, null);
// Act
IEnumerable<string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(vpResult);
// Assert
Assert.Null(indexNames);
}
[Fact]
public void GetTypeArgumentsForUpdatableGenericCollection_ModelTypeNotGeneric_Fail()
{
// Arrange
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int));
// Act
Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(null, null, modelMetadata);
// Assert
Assert.Null(typeArguments);
}
[Fact]
public void GetTypeArgumentsForUpdatableGenericCollection_ModelTypeOpenGeneric_Fail()
{
// Arrange
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IList<>));
// Act
Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(null, null, modelMetadata);
// Assert
Assert.Null(typeArguments);
}
[Fact]
public void GetTypeArgumentsForUpdatableGenericCollection_ModelTypeWrongNumberOfGenericArguments_Fail()
{
// Arrange
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair<int, string>));
// Act
Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(ICollection<>), null, modelMetadata);
// Assert
Assert.Null(typeArguments);
}
[Fact]
public void GetTypeArgumentsForUpdatableGenericCollection_ReadOnlyReference_ModelInstanceImmutable_Valid()
{
// Arrange
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new int[0], typeof(IList<int>));
modelMetadata.IsReadOnly = true;
// Act
Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(IList<>), typeof(List<>), modelMetadata);
// Assert
Assert.Null(typeArguments);
}
[Fact]
public void GetTypeArgumentsForUpdatableGenericCollection_ReadOnlyReference_ModelInstanceMutable_Valid()
{
// Arrange
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new List<int>(), typeof(IList<int>));
modelMetadata.IsReadOnly = true;
// Act
Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(IList<>), typeof(List<>), modelMetadata);
// Assert
Assert.Equal(new[] { typeof(int) }, typeArguments);
}
[Fact]
public void GetTypeArgumentsForUpdatableGenericCollection_ReadOnlyReference_ModelInstanceOfWrongType_Fail()
{
// Arrange
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new HashSet<int>(), typeof(ICollection<int>));
modelMetadata.IsReadOnly = true;
// Act
Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(IList<>), typeof(List<>), modelMetadata);
// Assert
// HashSet<> is not an IList<>, so we can't update
Assert.Null(typeArguments);
}
[Fact]
public void GetTypeArgumentsForUpdatableGenericCollection_ReadOnlyReference_ModelIsNull_Fail()
{
// Arrange
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IList<int>));
modelMetadata.IsReadOnly = true;
// Act
Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(ICollection<>), typeof(List<>), modelMetadata);
// Assert
Assert.Null(typeArguments);
}
[Fact]
public void GetTypeArgumentsForUpdatableGenericCollection_ReadWriteReference_NewInstanceAssignableToModelType_Success()
{
// Arrange
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IList<int>));
modelMetadata.IsReadOnly = false;
// Act
Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(ICollection<>), typeof(List<>), modelMetadata);
// Assert
Assert.Equal(new[] { typeof(int) }, typeArguments);
}
[Fact]
public void GetTypeArgumentsForUpdatableGenericCollection_ReadWriteReference_NewInstanceNotAssignableToModelType_MutableInstance_Success()
{
// Arrange
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new Collection<int>(), typeof(Collection<int>));
modelMetadata.IsReadOnly = false;
// Act
Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(ICollection<>), typeof(List<>), modelMetadata);
// Assert
Assert.Equal(new[] { typeof(int) }, typeArguments);
}
[Fact]
public void GetZeroBasedIndexes()
{
// Act
string[] indexes = CollectionModelBinderUtil.GetZeroBasedIndexes().Take(5).ToArray();
// Assert
Assert.Equal(new[] { "0", "1", "2", "3", "4" }, indexes);
}
private class ReadOnlyDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>
{
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
{
get { return true; }
}
}
}
}

View File

@@ -0,0 +1,160 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Web.Http.Controllers;
using Microsoft.TestCommon;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Internal
{
public class TypeActivatorTest
{
[Fact]
public void TypeIsCorrect()
{
Assert.Type.HasProperties(typeof(TypeActivator), TypeAssert.TypeProperties.IsClass | TypeAssert.TypeProperties.IsStatic);
}
public static TheoryDataSet<Type, Type> ValidTypeParameters
{
get
{
return new TheoryDataSet<Type, Type>
{
{ typeof(List<int>), typeof(IList<int>)},
{ typeof(Dictionary<int, int>), typeof(IDictionary<int, int>)},
{ typeof(HttpRequestMessage), typeof(HttpRequestMessage)},
{ typeof(HttpConfiguration), typeof(HttpConfiguration)},
{ typeof(ReflectedHttpActionDescriptor), typeof(HttpActionDescriptor) },
{ typeof(ApiControllerActionSelector), typeof(IHttpActionSelector)},
{ typeof(ApiControllerActionInvoker), typeof(IHttpActionInvoker)},
{ typeof(List<HttpStatusCode>), typeof(IEnumerable<HttpStatusCode>)},
};
}
}
[Theory]
[PropertyData("ValidTypeParameters")]
public void CreateType(Type instanceType, Type baseType)
{
// Arrange
Func<object> instanceDelegate = TypeActivator.Create(instanceType);
// Act
object instance = instanceDelegate();
// Assert
Assert.IsType(instanceType, instance);
}
[Theory]
[InlineData(typeof(int))]
[InlineData(typeof(Guid))]
[InlineData(typeof(HttpStatusCode))]
[InlineData(typeof(string))]
[InlineData(typeof(Uri))]
[InlineData(typeof(IDictionary<object, object>))]
[InlineData(typeof(List<>))]
public void CreateTypeInvalidThrowsInvalidArgument(Type type)
{
// Value types, interfaces, and open generics cause ArgumentException
Assert.Throws<ArgumentException>(() => TypeActivator.Create(type));
}
[Theory]
[InlineData(typeof(HttpContent))]
[InlineData(typeof(HttpActionDescriptor))]
public void CreateTypeInvalidThrowsInvalidOperation(Type type)
{
// Abstract types cause InvalidOperationException
Assert.Throws<InvalidOperationException>(() => TypeActivator.Create(type));
}
[Theory]
[PropertyData("ValidTypeParameters")]
public void CreateOfT(Type instanceType, Type baseType)
{
// Arrange
Type activatorType = typeof(TypeActivator);
MethodInfo createMethodInfo = activatorType.GetMethod("Create", Type.EmptyTypes);
MethodInfo genericCreateMethodInfo = createMethodInfo.MakeGenericMethod(instanceType);
Func<object> instanceDelegate = (Func<object>)genericCreateMethodInfo.Invoke(null, null);
// Act
object instance = instanceDelegate();
// Assert
Assert.IsType(instanceType, instance);
}
[Fact]
public void CreateOfTInvalid()
{
// string doesn't have a default ctor
Assert.Throws<ArgumentException>(() => TypeActivator.Create<string>());
// Uri doesn't have a default ctor
Assert.Throws<ArgumentException>(() => TypeActivator.Create<Uri>());
// HttpContent is abstract
Assert.Throws<InvalidOperationException>(() => TypeActivator.Create<HttpContent>());
// HttpActionDescriptor is abstract
Assert.Throws<InvalidOperationException>(() => TypeActivator.Create<HttpActionDescriptor>());
}
[Theory]
[PropertyData("ValidTypeParameters")]
public void CreateOfTBase(Type instanceType, Type baseType)
{
// Arrange
Type activatorType = typeof(TypeActivator);
MethodInfo createMethodInfo = null;
foreach (MethodInfo methodInfo in activatorType.GetMethods())
{
ParameterInfo[] parameterInfo = methodInfo.GetParameters();
if (methodInfo.Name == "Create" && methodInfo.ContainsGenericParameters && parameterInfo.Length == 1 && parameterInfo[0].ParameterType == typeof(Type))
{
createMethodInfo = methodInfo;
break;
}
}
MethodInfo genericCreateMethodInfo = createMethodInfo.MakeGenericMethod(baseType);
Func<object> instanceDelegate = (Func<object>)genericCreateMethodInfo.Invoke(null, new object[] { instanceType });
// Act
object instance = instanceDelegate();
// Assert
Assert.IsType(instanceType, instance);
}
[Fact]
public void CreateOfTBaseInvalid()
{
// int not being a ref type
Assert.Throws<ArgumentException>(() => TypeActivator.Create<object>(typeof(int)));
// GUID is not a ref type
Assert.Throws<ArgumentException>(() => TypeActivator.Create<object>(typeof(Guid)));
// HttpStatusCode is not a ref type
Assert.Throws<ArgumentException>(() => TypeActivator.Create<object>(typeof(HttpStatusCode)));
// string does not have a default ctor
Assert.Throws<ArgumentException>(() => TypeActivator.Create<string>(typeof(string)));
// ObjectContent does not have a default ctor
Assert.Throws<ArgumentException>(() => TypeActivator.Create<HttpContent>(typeof(ObjectContent)));
// Base type and instance type flipped
Assert.Throws<ArgumentException>(() => TypeActivator.Create<ReflectedHttpActionDescriptor>(typeof(HttpActionDescriptor)));
}
}
}