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,73 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.IO;
using System.Reflection;
using System.Web.Compilation;
using System.Web.Hosting;
namespace System.Web.WebPages.TestUtils
{
public static class AppDomainUtils
{
// Allow a test to modify static fields in an independent appdomain so that
// other tests will not be affected.
public static void RunInSeparateAppDomain(Action action)
{
RunInSeparateAppDomain(new AppDomainSetup(), action);
}
public static void RunInSeparateAppDomain(AppDomainSetup setup, Action action)
{
var dir = Path.GetDirectoryName(typeof(AppDomainUtils).Assembly.CodeBase).Replace("file:\\", "");
setup.PrivateBinPath = dir;
setup.ApplicationBase = dir;
setup.ApplicationName = Guid.NewGuid().ToString();
setup.ShadowCopyFiles = "true";
setup.ShadowCopyDirectories = setup.ApplicationBase;
setup.CachePath = Path.Combine(Path.GetTempPath(), setup.ApplicationName);
AppDomain appDomain = null;
try
{
appDomain = AppDomain.CreateDomain(setup.ApplicationName, null, setup);
AppDomainHelper helper = appDomain.CreateInstanceAndUnwrap(typeof(AppDomainUtils).Assembly.FullName, typeof(AppDomainHelper).FullName) as AppDomainHelper;
helper.Run(action);
}
finally
{
if (appDomain != null)
{
AppDomain.Unload(appDomain);
}
}
}
public class AppDomainHelper : MarshalByRefObject
{
public void Run(Action action)
{
action();
}
}
public static void SetPreAppStartStage()
{
var stage = typeof(BuildManager).GetProperty("PreStartInitStage", BindingFlags.Static | BindingFlags.NonPublic);
var value = ((FieldInfo)typeof(BuildManager).Assembly.GetType("System.Web.Compilation.PreStartInitStage").GetMember("DuringPreStartInit")[0]).GetValue(null);
stage.SetValue(null, value, new object[] { });
SetAppData();
var env = new HostingEnvironment();
}
public static void SetAppData()
{
var appdomain = AppDomain.CurrentDomain;
// Set some dummy values to make the appdomain seem more like a ASP.NET hosted one
appdomain.SetData(".appDomain", "*");
appdomain.SetData(".appId", "appId");
appdomain.SetData(".appPath", "appPath");
appdomain.SetData(".appVPath", "/WebSite1");
appdomain.SetData(".domainId", "1");
}
}
}

View File

@@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Xunit;
namespace Microsoft.TestCommon
{
// This extends xUnit.net's Assert class, and makes it partial so that we can
// organize the extension points by logical functionality (rather than dumping them
// all into this single file).
//
// See files named XxxAssertions for root extensions to AssertEx.
public partial class AssertEx : Assert
{
public static readonly ReflectionAssert Reflection = new ReflectionAssert();
public static readonly TypeAssert Type = new TypeAssert();
public static readonly HttpAssert Http = new HttpAssert();
public static readonly MediaTypeAssert MediaType = new MediaTypeAssert();
public static readonly GenericTypeAssert GenericType = new GenericTypeAssert();
public static readonly SerializerAssert Serializer = new SerializerAssert();
public static readonly StreamAssert Stream = new StreamAssert();
public static readonly TaskAssert Task = new TaskAssert();
public static readonly XmlAssert Xml = new XmlAssert();
}
}

View File

@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Globalization;
using System.Threading;
using Xunit;
namespace System.Web.TestUtil
{
public class CultureReplacer : IDisposable
{
private readonly CultureInfo _originalCulture;
private readonly long _threadId;
public CultureReplacer(string culture = "en-us")
{
_originalCulture = Thread.CurrentThread.CurrentCulture;
_threadId = Thread.CurrentThread.ManagedThreadId;
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing)
{
Assert.True(Thread.CurrentThread.ManagedThreadId == _threadId, "The current thread is not the same as the thread invoking the constructor. This should never happen.");
Thread.CurrentThread.CurrentCulture = _originalCulture;
}
}
}
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using Xunit;
namespace Microsoft.TestCommon
{
/// <summary>
/// An override of <see cref="FactAttribute"/> that provides a default timeout.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class DefaultTimeoutFactAttribute : FactAttribute
{
public DefaultTimeoutFactAttribute()
{
Timeout = TimeoutConstant.DefaultTimeout;
}
}
}

View File

@@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using Xunit.Extensions;
namespace Microsoft.TestCommon
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class DefaultTimeoutTheoryAttribute : TheoryAttribute
{
public DefaultTimeoutTheoryAttribute()
{
Timeout = TimeoutConstant.DefaultTimeout;
}
}
}

View File

@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace Microsoft.TestCommon
{
public class DictionaryEqualityComparer : IEqualityComparer<IDictionary<string, object>>
{
public bool Equals(IDictionary<string, object> x, IDictionary<string, object> y)
{
if (x.Count != y.Count)
{
return false;
}
foreach (string key in x.Keys)
{
object xVal = x[key];
object yVal;
if (!y.TryGetValue(key, out yVal))
{
return false;
}
if (xVal == null)
{
if (yVal == null)
{
continue;
}
return false;
}
if (!xVal.Equals(yVal))
{
return false;
}
}
return true;
}
public int GetHashCode(IDictionary<string, object> obj)
{
return 1;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Reflection;
using Xunit;
namespace Microsoft.TestCommon
{
public class ForceGCAttribute : BeforeAfterTestAttribute
{
public override void After(MethodInfo methodUnderTest)
{
GC.Collect(99);
GC.Collect(99);
GC.Collect(99);
}
}
}

View File

@@ -0,0 +1,383 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.TestUtil
{
public static class MemberHelper
{
private static ConstructorInfo GetConstructorInfo(object instance, Type[] parameterTypes)
{
if (instance == null)
{
throw new ArgumentNullException("instance");
}
ConstructorInfo constructorInfo = instance.GetType().GetConstructor(parameterTypes);
if (constructorInfo == null)
{
throw new ArgumentException(String.Format(
"A matching constructor on type '{0}' could not be found.",
instance.GetType().FullName));
}
return constructorInfo;
}
private static EventInfo GetEventInfo(object instance, string eventName)
{
if (instance == null)
{
throw new ArgumentNullException("instance");
}
if (String.IsNullOrEmpty(eventName))
{
throw new ArgumentException("An event must be specified.", "eventName");
}
EventInfo eventInfo = instance.GetType().GetEvent(eventName);
if (eventInfo == null)
{
throw new ArgumentException(String.Format(
"An event named '{0}' on type '{1}' could not be found.",
eventName, instance.GetType().FullName));
}
return eventInfo;
}
private static MethodInfo GetMethodInfo(object instance, string methodName, Type[] types = null, MethodAttributes attrs = MethodAttributes.Public)
{
if (instance == null)
{
throw new ArgumentNullException("instance");
}
if (String.IsNullOrEmpty(methodName))
{
throw new ArgumentException("A method must be specified.", "methodName");
}
MethodInfo methodInfo;
if (types != null)
{
methodInfo = instance.GetType().GetMethod(methodName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
null,
types,
null);
}
else
{
methodInfo = instance.GetType().GetMethod(methodName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (methodInfo == null)
{
throw new ArgumentException(String.Format(
"A method named '{0}' on type '{1}' could not be found.",
methodName, instance.GetType().FullName));
}
if ((methodInfo.Attributes & attrs) != attrs)
{
throw new ArgumentException(String.Format(
"Method '{0}' on type '{1}' with attributes '{2}' does not match the attributes '{3}'.",
methodName, instance.GetType().FullName, methodInfo.Attributes, attrs));
}
return methodInfo;
}
private static PropertyInfo GetPropertyInfo(object instance, string propertyName)
{
if (instance == null)
{
throw new ArgumentNullException("instance");
}
if (String.IsNullOrEmpty(propertyName))
{
throw new ArgumentException("A property must be specified.", "propertyName");
}
PropertyInfo propInfo = instance.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (propInfo == null)
{
throw new ArgumentException(String.Format(
"A property named '{0}' on type '{1}' could not be found.",
propertyName, instance.GetType().FullName));
}
return propInfo;
}
private static void TestAttribute<TAttribute>(MemberInfo memberInfo, TAttribute attributeValue)
where TAttribute : Attribute
{
object[] attrs = memberInfo.GetCustomAttributes(typeof(TAttribute), true);
if (attributeValue == null)
{
Assert.True(attrs.Length == 0, "Member should not have an attribute of type " + typeof(TAttribute));
}
else
{
Assert.True(attrs != null && attrs.Length > 0,
"Member does not have an attribute of type " + typeof(TAttribute));
Assert.Equal(attributeValue, attrs[0]);
}
}
public static void TestBooleanProperty(object instance, string propertyName, bool initialValue, bool testDefaultValue)
{
// Assert initial value
TestGetPropertyValue(instance, propertyName, initialValue);
if (testDefaultValue)
{
// Assert DefaultValue attribute matches inital value
TestDefaultValue(instance, propertyName);
}
TestPropertyValue(instance, propertyName, true);
TestPropertyValue(instance, propertyName, false);
}
public static void TestDefaultValue(object instance, string propertyName)
{
PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
object initialValue = propInfo.GetValue(instance, null);
TestAttribute(propInfo, new DefaultValueAttribute(initialValue));
}
public static void TestEvent<TEventArgs>(object instance, string eventName, TEventArgs eventArgs) where TEventArgs : EventArgs
{
EventInfo eventInfo = GetEventInfo(instance, eventName);
// Assert category "Action"
TestAttribute(eventInfo, new CategoryAttribute("Action"));
// Call protected method with no event handlers, assert no error
MethodInfo methodInfo = GetMethodInfo(instance, "On" + eventName, attrs: MethodAttributes.Family | MethodAttributes.Virtual);
methodInfo.Invoke(instance, new object[] { eventArgs });
// Attach handler, call method, assert fires once
List<object> eventHandlerArgs = new List<object>();
EventHandler<TEventArgs> handler = new EventHandler<TEventArgs>(delegate(object sender, TEventArgs t)
{
eventHandlerArgs.Add(sender);
eventHandlerArgs.Add(t);
});
eventInfo.AddEventHandler(instance, handler);
methodInfo.Invoke(instance, new object[] { eventArgs });
Assert.Equal(new[] { instance, eventArgs }, eventHandlerArgs.ToArray());
// Detach handler, call method, assert not fired
eventHandlerArgs = new List<object>();
eventInfo.RemoveEventHandler(instance, handler);
methodInfo.Invoke(instance, new object[] { eventArgs });
Assert.Empty(eventHandlerArgs);
}
public static void TestGetPropertyValue(object instance, string propertyName, object valueToCheck)
{
PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
object value = propInfo.GetValue(instance, null);
Assert.Equal(valueToCheck, value);
}
public static void TestEnumProperty<TEnumValue>(object instance, string propertyName, TEnumValue initialValue, bool testDefaultValue)
{
// Assert initial value
TestGetPropertyValue(instance, propertyName, initialValue);
if (testDefaultValue)
{
// Assert DefaultValue attribute matches inital value
TestDefaultValue(instance, propertyName);
}
PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
// Values are sorted numerically
TEnumValue[] values = (TEnumValue[])Enum.GetValues(propInfo.PropertyType);
// Assert get/set works for all valid enum values
foreach (TEnumValue value in values)
{
TestPropertyValue(instance, propertyName, value);
}
// Assert ArgumentOutOfRangeException is thrown for value one less than smallest
// enum value, and one more than largest enum value
var targetException = Assert.Throws<TargetInvocationException>(() => propInfo.SetValue(instance, Convert.ToInt32(values[0]) - 1, null));
Assert.IsType<ArgumentOutOfRangeException>(targetException.InnerException);
targetException = Assert.Throws<TargetInvocationException>(() => propInfo.SetValue(instance, Convert.ToInt32(values[values.Length - 1]) + 1, null));
Assert.IsType<ArgumentOutOfRangeException>(targetException.InnerException);
}
public static void TestInt32Property(object instance, string propertyName, int value1, int value2)
{
TestPropertyValue(instance, propertyName, value1);
TestPropertyValue(instance, propertyName, value2);
}
public static void TestPropertyWithDefaultInstance(object instance, string propertyName, object valueToSet)
{
PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
// Set to explicit property
propInfo.SetValue(instance, valueToSet, null);
object value = propInfo.GetValue(instance, null);
Assert.Equal(valueToSet, value);
// Set to null
propInfo.SetValue(instance, null, null);
value = propInfo.GetValue(instance, null);
Assert.IsAssignableFrom(propInfo.PropertyType, value);
}
public static void TestPropertyWithDefaultInstance(object instance, string propertyName, object valueToSet, object defaultValue)
{
PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
// Set to explicit property
propInfo.SetValue(instance, valueToSet, null);
object value = propInfo.GetValue(instance, null);
Assert.Same(valueToSet, value);
// Set to null
propInfo.SetValue(instance, null, null);
value = propInfo.GetValue(instance, null);
Assert.Equal(defaultValue, value);
}
public static void TestPropertyValue(object instance, string propertyName, object value)
{
TestPropertyValue(instance, propertyName, value, value);
}
public static void TestPropertyValue(object instance, string propertyName, object valueToSet, object valueToCheck)
{
PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
propInfo.SetValue(instance, valueToSet, null);
object value = propInfo.GetValue(instance, null);
Assert.Equal(valueToCheck, value);
}
public static void TestStringParams(object instance, Type[] constructorParameterTypes, object[] parameters)
{
ConstructorInfo ctor = GetConstructorInfo(instance, constructorParameterTypes);
TestStringParams(ctor, instance, parameters);
}
public static void TestStringParams(object instance, string methodName, object[] parameters)
{
TestStringParams(instance, methodName, null, parameters);
}
public static void TestStringParams(object instance, string methodName, Type[] types, object[] parameters)
{
MethodInfo method = GetMethodInfo(instance, methodName, types);
TestStringParams(method, instance, parameters);
}
private static void TestStringParams(MethodBase method, object instance, object[] parameters)
{
ParameterInfo[] parameterInfos = method.GetParameters();
foreach (ParameterInfo parameterInfo in parameterInfos)
{
if (parameterInfo.ParameterType == typeof(String))
{
object originalParameter = parameters[parameterInfo.Position];
parameters[parameterInfo.Position] = null;
Assert.ThrowsArgumentNullOrEmpty(
delegate()
{
try
{
method.Invoke(instance, parameters);
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
},
parameterInfo.Name);
parameters[parameterInfo.Position] = String.Empty;
Assert.ThrowsArgumentNullOrEmpty(
delegate()
{
try
{
method.Invoke(instance, parameters);
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
},
parameterInfo.Name);
parameters[parameterInfo.Position] = originalParameter;
}
}
}
public static void TestStringProperty(object instance, string propertyName, string initialValue,
bool testDefaultValueAttribute = false, bool allowNullAndEmpty = true,
string nullAndEmptyReturnValue = "")
{
// Assert initial value
TestGetPropertyValue(instance, propertyName, initialValue);
if (testDefaultValueAttribute)
{
// Assert DefaultValue attribute matches inital value
TestDefaultValue(instance, propertyName);
}
if (allowNullAndEmpty)
{
// Assert get/set works for null
TestPropertyValue(instance, propertyName, null, nullAndEmptyReturnValue);
// Assert get/set works for String.Empty
TestPropertyValue(instance, propertyName, String.Empty, nullAndEmptyReturnValue);
}
else
{
Assert.ThrowsArgumentNullOrEmpty(
delegate()
{
try
{
TestPropertyValue(instance, propertyName, null);
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
},
"value");
Assert.ThrowsArgumentNullOrEmpty(
delegate()
{
try
{
TestPropertyValue(instance, propertyName, String.Empty);
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
},
"value");
}
// Assert get/set works for arbitrary value
TestPropertyValue(instance, propertyName, "TestValue");
}
}
}

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Runtime.sln))\tools\WebStack.settings.targets" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.TestCommon</RootNamespace>
<AssemblyName>Microsoft.TestCommon</AssemblyName>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>$(WebStackRootPath)\bin\Debug\Test\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>$(WebStackRootPath)\bin\Release\Test\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'CodeCoverage' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>$(WebStackRootPath)\bin\CodeCoverage\Test\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Net.Http.2.0.20326.1\lib\net40\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Net.Http.2.0.20326.1\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="xunit">
<HintPath>..\..\packages\xunit.1.9.0.1566\lib\xunit.dll</HintPath>
</Reference>
<Reference Include="xunit.extensions">
<HintPath>..\..\packages\xunit.extensions.1.9.0.1566\lib\xunit.extensions.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="PartialTrustRunner.cs" />
<Compile Include="RestoreThreadPrincipalAttribute.cs" />
<Compile Include="AppDomainUtils.cs" />
<Compile Include="AssertEx.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="CultureReplacer.cs" />
<Compile Include="DefaultTimeoutFactAttribute.cs" />
<Compile Include="DefaultTimeoutTheoryAttribute.cs" />
<Compile Include="DictionaryEqualityComparer.cs" />
<Compile Include="ExceptionAssertions.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ForceGCAttribute.cs" />
<Compile Include="MemberHelper.cs" />
<Compile Include="Microsoft\TestCommon\DataSets\RefTypeTestData.cs" />
<Compile Include="Microsoft\TestCommon\DataSets\TestDataVariations.cs" />
<Compile Include="Microsoft\TestCommon\DataSets\ValueTypeTestData.cs" />
<Compile Include="Microsoft\TestCommon\GenericTypeAssert.cs" />
<Compile Include="Microsoft\TestCommon\HttpAssert.cs" />
<Compile Include="Microsoft\TestCommon\MediaTypeAssert.cs" />
<Compile Include="Microsoft\TestCommon\MediaTypeHeaderValueComparer.cs" />
<Compile Include="Microsoft\TestCommon\ParsedMediaTypeHeaderValue.cs" />
<Compile Include="Microsoft\TestCommon\RegexReplacement.cs" />
<Compile Include="Microsoft\TestCommon\RuntimeEnvironment.cs" />
<Compile Include="Microsoft\TestCommon\SerializerAssert.cs" />
<Compile Include="Microsoft\TestCommon\StreamAssert.cs" />
<Compile Include="Microsoft\TestCommon\TaskAssert.cs" />
<Compile Include="Microsoft\TestCommon\DataSets\TestData.cs" />
<Compile Include="Microsoft\TestCommon\TestDataSetAttribute.cs" />
<Compile Include="Microsoft\TestCommon\TimeoutConstant.cs" />
<Compile Include="Microsoft\TestCommon\TypeAssert.cs" />
<Compile Include="Microsoft\TestCommon\Types\FlagsEnum.cs" />
<Compile Include="Microsoft\TestCommon\Types\INameAndIdContainer.cs" />
<Compile Include="Microsoft\TestCommon\Types\ISerializableType.cs" />
<Compile Include="Microsoft\TestCommon\Types\LongEnum.cs" />
<Compile Include="Microsoft\TestCommon\Types\SimpleEnum.cs" />
<Compile Include="Microsoft\TestCommon\DataSets\CommonUnitTestDataSets.cs" />
<Compile Include="Microsoft\TestCommon\XmlAssert.cs" />
<Compile Include="PreAppStartTestHelper.cs" />
<Compile Include="PreserveSyncContextAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReflectionAssert.cs" />
<Compile Include="TaskExtensions.cs" />
<Compile Include="TestFile.cs" />
<Compile Include="TestHelper.cs" />
<Compile Include="TheoryDataSet.cs" />
<Compile Include="ThreadPoolSyncContext.cs" />
<Compile Include="WebUtils.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.ObjectModel;
using Microsoft.TestCommon.Types;
namespace Microsoft.TestCommon
{
public class CommonUnitTestDataSets
{
public static ValueTypeTestData<char> Chars { get { return TestData.CharTestData; } }
public static ValueTypeTestData<int> Ints { get { return TestData.IntTestData; } }
public static ValueTypeTestData<uint> Uints { get { return TestData.UintTestData; } }
public static ValueTypeTestData<short> Shorts { get { return TestData.ShortTestData; } }
public static ValueTypeTestData<ushort> Ushorts { get { return TestData.UshortTestData; } }
public static ValueTypeTestData<long> Longs { get { return TestData.LongTestData; } }
public static ValueTypeTestData<ulong> Ulongs { get { return TestData.UlongTestData; } }
public static ValueTypeTestData<byte> Bytes { get { return TestData.ByteTestData; } }
public static ValueTypeTestData<sbyte> SBytes { get { return TestData.SByteTestData; } }
public static ValueTypeTestData<bool> Bools { get { return TestData.BoolTestData; } }
public static ValueTypeTestData<double> Doubles { get { return TestData.DoubleTestData; } }
public static ValueTypeTestData<float> Floats { get { return TestData.FloatTestData; } }
public static ValueTypeTestData<DateTime> DateTimes { get { return TestData.DateTimeTestData; } }
public static ValueTypeTestData<Decimal> Decimals { get { return TestData.DecimalTestData; } }
public static ValueTypeTestData<TimeSpan> TimeSpans { get { return TestData.TimeSpanTestData; } }
public static ValueTypeTestData<Guid> Guids { get { return TestData.GuidTestData; } }
public static ValueTypeTestData<DateTimeOffset> DateTimeOffsets { get { return TestData.DateTimeOffsetTestData; } }
public static ValueTypeTestData<SimpleEnum> SimpleEnums { get { return TestData.SimpleEnumTestData; } }
public static ValueTypeTestData<LongEnum> LongEnums { get { return TestData.LongEnumTestData; } }
public static ValueTypeTestData<FlagsEnum> FlagsEnums { get { return TestData.FlagsEnumTestData; } }
public static TestData<string> EmptyStrings { get { return TestData.EmptyStrings; } }
public static RefTypeTestData<string> Strings { get { return TestData.StringTestData; } }
public static TestData<string> NonNullEmptyStrings { get { return TestData.NonNullEmptyStrings; } }
public static RefTypeTestData<ISerializableType> ISerializableTypes { get { return TestData.ISerializableTypeTestData; } }
public static ReadOnlyCollection<TestData> ValueTypeTestDataCollection { get { return TestData.ValueTypeTestDataCollection; } }
public static ReadOnlyCollection<TestData> RefTypeTestDataCollection { get { return TestData.RefTypeTestDataCollection; } }
public static ReadOnlyCollection<TestData> ValueAndRefTypeTestDataCollection { get { return TestData.ValueTypeTestDataCollection; } }
public static ReadOnlyCollection<TestData> RepresentativeValueAndRefTypeTestDataCollection { get { return TestData.RepresentativeValueAndRefTypeTestDataCollection; } }
}
}

View File

@@ -0,0 +1,69 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.TestCommon
{
public class RefTypeTestData<T> : TestData<T> where T : class
{
private Func<IEnumerable<T>> testDataProvider;
private Func<IEnumerable<T>> derivedTypeTestDataProvider;
private Func<IEnumerable<T>> knownTypeTestDataProvider;
public RefTypeTestData(Func<IEnumerable<T>> testDataProvider)
{
if (testDataProvider == null)
{
throw new ArgumentNullException("testDataProvider");
}
this.testDataProvider = testDataProvider;
}
public RefTypeTestData(
Func<IEnumerable<T>> testDataProvider,
Func<IEnumerable<T>> derivedTypeTestDataProvider,
Func<IEnumerable<T>> knownTypeTestDataProvider)
: this(testDataProvider)
{
this.derivedTypeTestDataProvider = derivedTypeTestDataProvider;
if (this.derivedTypeTestDataProvider != null)
{
this.RegisterTestDataVariation(TestDataVariations.AsDerivedType, this.Type, this.GetTestDataAsDerivedType);
}
this.knownTypeTestDataProvider = knownTypeTestDataProvider;
if (this.knownTypeTestDataProvider != null)
{
this.RegisterTestDataVariation(TestDataVariations.AsKnownType, this.Type, this.GetTestDataAsDerivedKnownType);
}
}
public IEnumerable<T> GetTestDataAsDerivedType()
{
if (this.derivedTypeTestDataProvider != null)
{
return this.derivedTypeTestDataProvider();
}
return Enumerable.Empty<T>();
}
public IEnumerable<T> GetTestDataAsDerivedKnownType()
{
if (this.knownTypeTestDataProvider != null)
{
return this.knownTypeTestDataProvider();
}
return Enumerable.Empty<T>();
}
protected override IEnumerable<T> GetTypedTestData()
{
return this.testDataProvider();
}
}
}

View File

@@ -0,0 +1,446 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.TestCommon.Types;
namespace Microsoft.TestCommon
{
/// <summary>
/// A base class for test data. A <see cref="TestData"/> instance is associated with a given type, and the <see cref="TestData"/> instance can
/// provide instances of the given type to use as data in tests. The same <see cref="TestData"/> instance can also provide instances
/// of types related to the given type, such as a <see cref="List<>"/> of the type. See the <see cref="TestDataVariations"/> enum for all the
/// variations of test data that a <see cref="TestData"/> instance can provide.
/// </summary>
public abstract class TestData
{
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="char"/>.
/// </summary>
public static readonly ValueTypeTestData<char> CharTestData = new ValueTypeTestData<char>('a', Char.MinValue, Char.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="int"/>.
/// </summary>
public static readonly ValueTypeTestData<int> IntTestData = new ValueTypeTestData<int>(-1, 0, 1, Int32.MinValue, Int32.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="uint"/>.
/// </summary>
public static readonly ValueTypeTestData<uint> UintTestData = new ValueTypeTestData<uint>(0, 1, UInt32.MinValue, UInt32.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="short"/>.
/// </summary>
public static readonly ValueTypeTestData<short> ShortTestData = new ValueTypeTestData<short>(-1, 0, 1, Int16.MinValue, Int16.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="ushort"/>.
/// </summary>
public static readonly ValueTypeTestData<ushort> UshortTestData = new ValueTypeTestData<ushort>(0, 1, UInt16.MinValue, UInt16.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="long"/>.
/// </summary>
public static readonly ValueTypeTestData<long> LongTestData = new ValueTypeTestData<long>(-1, 0, 1, Int64.MinValue, Int64.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="ulong"/>.
/// </summary>
public static readonly ValueTypeTestData<ulong> UlongTestData = new ValueTypeTestData<ulong>(0, 1, UInt64.MinValue, UInt64.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="byte"/>.
/// </summary>
public static readonly ValueTypeTestData<byte> ByteTestData = new ValueTypeTestData<byte>(0, 1, Byte.MinValue, Byte.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="sbyte"/>.
/// </summary>
public static readonly ValueTypeTestData<sbyte> SByteTestData = new ValueTypeTestData<sbyte>(-1, 0, 1, SByte.MinValue, SByte.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="bool"/>.
/// </summary>
public static readonly ValueTypeTestData<bool> BoolTestData = new ValueTypeTestData<bool>(true, false);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="double"/>.
/// </summary>
public static readonly ValueTypeTestData<double> DoubleTestData = new ValueTypeTestData<double>(
-1.0,
0.0,
1.0,
double.MinValue,
double.MaxValue,
double.PositiveInfinity,
double.NegativeInfinity);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="float"/>.
/// </summary>
public static readonly ValueTypeTestData<float> FloatTestData = new ValueTypeTestData<float>(
-1.0f,
0.0f,
1.0f,
float.MinValue,
float.MaxValue,
float.PositiveInfinity,
float.NegativeInfinity);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="decimal"/>.
/// </summary>
public static readonly ValueTypeTestData<decimal> DecimalTestData = new ValueTypeTestData<decimal>(
-1M,
0M,
1M,
decimal.MinValue,
decimal.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="DateTime"/>.
/// </summary>
public static readonly ValueTypeTestData<DateTime> DateTimeTestData = new ValueTypeTestData<DateTime>(
DateTime.Now,
DateTime.UtcNow,
DateTime.MaxValue,
DateTime.MinValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="TimeSpan"/>.
/// </summary>
public static readonly ValueTypeTestData<TimeSpan> TimeSpanTestData = new ValueTypeTestData<TimeSpan>(
TimeSpan.MinValue,
TimeSpan.MaxValue);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="Guid"/>.
/// </summary>
public static readonly ValueTypeTestData<Guid> GuidTestData = new ValueTypeTestData<Guid>(
Guid.NewGuid(),
Guid.Empty);
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="DateTimeOffset"/>.
/// </summary>
public static readonly ValueTypeTestData<DateTimeOffset> DateTimeOffsetTestData = new ValueTypeTestData<DateTimeOffset>(
DateTimeOffset.MaxValue,
DateTimeOffset.MinValue,
new DateTimeOffset(DateTime.Now));
/// <summary>
/// Common <see cref="TestData"/> for an <c>enum</c>.
/// </summary>
public static readonly ValueTypeTestData<SimpleEnum> SimpleEnumTestData = new ValueTypeTestData<SimpleEnum>(
SimpleEnum.First,
SimpleEnum.Second,
SimpleEnum.Third);
/// <summary>
/// Common <see cref="TestData"/> for an <c>enum</c> implemented with a <see cref="long"/>.
/// </summary>
public static readonly ValueTypeTestData<LongEnum> LongEnumTestData = new ValueTypeTestData<LongEnum>(
LongEnum.FirstLong,
LongEnum.SecondLong,
LongEnum.ThirdLong);
/// <summary>
/// Common <see cref="TestData"/> for an <c>enum</c> decorated with a <see cref="FlagsAttribtute"/>.
/// </summary>
public static readonly ValueTypeTestData<FlagsEnum> FlagsEnumTestData = new ValueTypeTestData<FlagsEnum>(
FlagsEnum.One,
FlagsEnum.Two,
FlagsEnum.Four);
/// <summary>
/// Expected permutations of non supported file paths.
/// </summary>
public static readonly TestData<string> NotSupportedFilePaths = new RefTypeTestData<string>(() => new List<string>() {
"cc:\\a\\b",
});
/// <summary>
/// Expected permutations of invalid file paths.
/// </summary>
public static readonly TestData<string> InvalidNonNullFilePaths = new RefTypeTestData<string>(() => new List<string>() {
String.Empty,
"",
" ",
" ",
"\t\t \n ",
"c:\\a<b",
"c:\\a>b",
"c:\\a\"b",
"c:\\a\tb",
"c:\\a|b",
"c:\\a\bb",
"c:\\a\0b",
});
/// <summary>
/// All expected permutations of an empty string.
/// </summary>
public static readonly TestData<string> NonNullEmptyStrings = new RefTypeTestData<string>(() => new List<string>() { String.Empty, "", " ", "\t\r\n" });
/// <summary>
/// All expected permutations of an empty string.
/// </summary>
public static readonly TestData<string> EmptyStrings = new RefTypeTestData<string>(() => new List<string>() { null, String.Empty, "", " ", "\t\r\n" });
/// <summary>
/// Common <see cref="TestData"/> for a <see cref="string"/>.
/// </summary>
public static readonly RefTypeTestData<string> StringTestData = new RefTypeTestData<string>(() => new List<string>() {
"",
" ", // one space
" ", // multiple spaces
" data ", // leading and trailing whitespace
"\t\t \n ",
"Some String!"});
/// <summary>
/// Common <see cref="TestData"/> for a class that implements <see cref="ISerializable"/>.
/// </summary>
public static readonly RefTypeTestData<ISerializableType> ISerializableTypeTestData = new RefTypeTestData<ISerializableType>(
ISerializableType.GetTestData);
/// <summary>
/// A read-only collection of value type test data.
/// </summary>
public static readonly ReadOnlyCollection<TestData> ValueTypeTestDataCollection = new ReadOnlyCollection<TestData>(new TestData[] {
CharTestData,
IntTestData,
UintTestData,
ShortTestData,
UshortTestData,
LongTestData,
UlongTestData,
ByteTestData,
SByteTestData,
BoolTestData,
DoubleTestData,
FloatTestData,
DecimalTestData,
TimeSpanTestData,
GuidTestData,
DateTimeOffsetTestData,
SimpleEnumTestData,
LongEnumTestData,
FlagsEnumTestData});
/// <summary>
/// A read-only collection of reference type test data.
/// </summary>
public static readonly ReadOnlyCollection<TestData> RefTypeTestDataCollection = new ReadOnlyCollection<TestData>(new TestData[] {
StringTestData,
ISerializableTypeTestData});
/// <summary>
/// A read-only collection of value and reference type test data.
/// </summary>
public static readonly ReadOnlyCollection<TestData> ValueAndRefTypeTestDataCollection = new ReadOnlyCollection<TestData>(
ValueTypeTestDataCollection.Concat(RefTypeTestDataCollection).ToList());
/// <summary>
/// A read-only collection of representative values and reference type test data.
/// Uses where exhaustive coverage is not required.
/// </summary>
public static readonly ReadOnlyCollection<TestData> RepresentativeValueAndRefTypeTestDataCollection = new ReadOnlyCollection<TestData>(new TestData[] {
IntTestData,
BoolTestData,
SimpleEnumTestData,
StringTestData,
});
private Dictionary<TestDataVariations, TestDataVariationProvider> registeredTestDataVariations;
/// <summary>
/// Initializes a new instance of the <see cref="TestData"/> class.
/// </summary>
/// <param name="type">The type associated with the <see cref="TestData"/> instance.</param>
protected TestData(Type type)
{
if (type.ContainsGenericParameters)
{
throw new InvalidOperationException("Only closed generic types are supported.");
}
this.Type = type;
this.registeredTestDataVariations = new Dictionary<TestDataVariations, TestDataVariationProvider>();
}
/// <summary>
/// Gets the type associated with the <see cref="TestData"/> instance.
/// </summary>
public Type Type { get; private set; }
/// <summary>
/// Gets the supported test data variations.
/// </summary>
/// <returns></returns>
public IEnumerable<TestDataVariations> GetSupportedTestDataVariations()
{
return this.registeredTestDataVariations.Keys;
}
/// <summary>
/// Gets the related type for the given test data variation or returns null if the <see cref="TestData"/> instance
/// doesn't support the given variation.
/// </summary>
/// <param name="variation">The test data variation with which to create the related <see cref="Type"/>.</param>
/// <returns>The related <see cref="Type"/> for the <see cref="TestData.Type"/> as given by the test data variation.</returns>
/// <example>
/// For example, if the given <see cref="TestData"/> was created for <see cref="string"/> test data and the varation parameter
/// was <see cref="TestDataVariations.AsList"/> then the returned type would be <see cref="List<string>"/>.
/// </example>
public Type GetAsTypeOrNull(TestDataVariations variation)
{
TestDataVariationProvider testDataVariation = null;
if (this.registeredTestDataVariations.TryGetValue(variation, out testDataVariation))
{
return testDataVariation.Type;
}
return null;
}
/// <summary>
/// Gets test data for the given test data variation or returns null if the <see cref="TestData"/> instance
/// doesn't support the given variation.
/// </summary>
/// <param name="variation">The test data variation with which to create the related test data.</param>
/// <returns>Test data of the type specified by the <see cref="TestData.GetAsTypeOrNull"/> method.</returns>
public object GetAsTestDataOrNull(TestDataVariations variation)
{
TestDataVariationProvider testDataVariation = null;
if (this.registeredTestDataVariations.TryGetValue(variation, out testDataVariation))
{
return testDataVariation.TestDataProvider();
}
return null;
}
/// <summary>
/// Allows derived classes to register a <paramref name="testDataProvider "/> <see cref="Func<>"/> that will
/// provide test data for a given variation.
/// </summary>
/// <param name="variation">The variation with which to register the <paramref name="testDataProvider "/>r.</param>
/// <param name="type">The type of the test data created by the <paramref name="testDataProvider "/></param>
/// <param name="testDataProvider">A <see cref="Func<>"/> that will provide test data.</param>
protected void RegisterTestDataVariation(TestDataVariations variation, Type type, Func<object> testDataProvider)
{
this.registeredTestDataVariations.Add(variation, new TestDataVariationProvider(type, testDataProvider));
}
private class TestDataVariationProvider
{
public TestDataVariationProvider(Type type, Func<object> testDataProvider)
{
this.Type = type;
this.TestDataProvider = testDataProvider;
}
public Func<object> TestDataProvider { get; private set; }
public Type Type { get; private set; }
}
}
/// <summary>
/// A generic base class for test data.
/// </summary>
/// <typeparam name="T">The type associated with the test data.</typeparam>
public abstract class TestData<T> : TestData, IEnumerable<T>
{
private static readonly Type OpenIEnumerableType = typeof(IEnumerable<>);
private static readonly Type OpenListType = typeof(List<>);
private static readonly Type OpenIQueryableType = typeof(IQueryable<>);
/// <summary>
/// Initializes a new instance of the <see cref="TestData&lt;T&gt;"/> class.
/// </summary>
protected TestData()
: base(typeof(T))
{
Type[] typeParams = new Type[] { this.Type };
Type arrayType = this.Type.MakeArrayType();
Type listType = OpenListType.MakeGenericType(typeParams);
Type iEnumerableType = OpenIEnumerableType.MakeGenericType(typeParams);
Type iQueryableType = OpenIQueryableType.MakeGenericType(typeParams);
Type[] typeArrayParams = new Type[] { arrayType };
Type[] typeListParams = new Type[] { listType };
Type[] typeIEnumerableParams = new Type[] { iEnumerableType };
Type[] typeIQueryableParams = new Type[] { iQueryableType };
this.RegisterTestDataVariation(TestDataVariations.AsInstance, this.Type, () => GetTypedTestData());
this.RegisterTestDataVariation(TestDataVariations.AsArray, arrayType, GetTestDataAsArray);
this.RegisterTestDataVariation(TestDataVariations.AsIEnumerable, iEnumerableType, GetTestDataAsIEnumerable);
this.RegisterTestDataVariation(TestDataVariations.AsIQueryable, iQueryableType, GetTestDataAsIQueryable);
this.RegisterTestDataVariation(TestDataVariations.AsList, listType, GetTestDataAsList);
}
public IEnumerator<T> GetEnumerator()
{
return (IEnumerator<T>)this.GetTypedTestData().ToList().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)this.GetTypedTestData().ToList().GetEnumerator();
}
/// <summary>
/// Gets the test data as an array.
/// </summary>
/// <returns>An array of test data of the given type.</returns>
public T[] GetTestDataAsArray()
{
return this.GetTypedTestData().ToArray();
}
/// <summary>
/// Gets the test data as a <see cref="List<>"/>.
/// </summary>
/// <returns>A <see cref="List<>"/> of test data of the given type.</returns>
public List<T> GetTestDataAsList()
{
return this.GetTypedTestData().ToList();
}
/// <summary>
/// Gets the test data as an <see cref="IEnumerable<>"/>.
/// </summary>
/// <returns>An <see cref="IEnumerable<>"/> of test data of the given type.</returns>
public IEnumerable<T> GetTestDataAsIEnumerable()
{
return this.GetTypedTestData().AsEnumerable();
}
/// <summary>
/// Gets the test data as an <see cref="IQueryable<>"/>.
/// </summary>
/// <returns>An <see cref="IQueryable<>"/> of test data of the given type.</returns>
public IQueryable<T> GetTestDataAsIQueryable()
{
return this.GetTypedTestData().AsQueryable();
}
/// <summary>
/// Must be implemented by derived types to return test data of the given type.
/// </summary>
/// <returns>Test data of the given type.</returns>
protected abstract IEnumerable<T> GetTypedTestData();
}
}

View File

@@ -0,0 +1,97 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
namespace Microsoft.TestCommon
{
/// <summary>
/// An flags enum that can be used to indicate different variations of a given
/// <see cref="TestData"/> instance.
/// </summary>
[Flags]
public enum TestDataVariations
{
/// <summary>
/// An individual instance of a given <see cref="TestData"/> type.
/// </summary>
AsInstance = 0x1,
/// <summary>
/// An individual instance of a type that derives from a given <see cref="TestData"/> type.
/// </summary>
AsDerivedType = 0x2,
/// <summary>
/// An individual instance of a given <see cref="TestData"/> type that has a property value
/// that is a known type of the declared property type.
/// </summary>
AsKnownType = 0x4,
/// <summary>
/// A <see cref="Nullable<>"/> instance of a given <see cref="TestData"/> type. Only applies to
/// instances of <see cref="ValueTypeTestData"/>.
/// </summary>
AsNullable = 0x8,
/// <summary>
/// An instance of a <see cref="System.Collections.Generic.List<>"/> of a given <see cref="TestData"/> type.
/// </summary>
AsList = 0x10,
/// <summary>
/// An instance of a array of the <see cref="TestData"/> type.
/// </summary>
AsArray = 0x20,
/// <summary>
/// An instance of an <see cref="System.Collections.Generic.IEnumerable<>"/> of a given <see cref="TestData"/> type.
/// </summary>
AsIEnumerable = 0x40,
/// <summary>
/// An instance of an <see cref="System.Linq.IQueryable<>"/> of a given <see cref="TestData"/> type.
/// </summary>
AsIQueryable = 0x80,
/// <summary>
/// An instance of a DataContract type in which a given <see cref="TestData"/> type is a member.
/// </summary>
AsDataMember = 0x100,
/// <summary>
/// An instance of a type in which a given <see cref="TestData"/> type is decorated with a
/// <see cref="System.Xml.Serialization.XmlElementAttribute"/>.
/// </summary>
AsXmlElementProperty = 0x200,
/// <summary>
/// All of the flags for single instance variations of a given <see cref="TestData"/> type.
/// </summary>
AllSingleInstances = AsInstance | AsDerivedType | AsKnownType | AsNullable,
/// <summary>
/// All of the flags for collection variations of a given <see cref="TestData"/> type.
/// </summary>
AllCollections = AsList | AsArray | AsIEnumerable | AsIQueryable,
/// <summary>
/// All of the flags for variations in which a given <see cref="TestData"/> type is a property on another type.
/// </summary>
AllProperties = AsDataMember | AsXmlElementProperty,
/// <summary>
/// All of the flags for interface collection variations of a given <see cref="TestData"/> type.
/// </summary>
AllInterfaces = AsIEnumerable | AsIQueryable,
/// <summary>
/// All of the flags except for the interface collection variations of a given <see cref="TestData"/> type.
/// </summary>
AllNonInterfaces = All & ~AllInterfaces,
/// <summary>
/// All of the flags for all of the variations of a given <see cref="TestData"/> type.
/// </summary>
All = AllSingleInstances | AllCollections | AllProperties
}
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.TestCommon
{
public class ValueTypeTestData<T> : TestData<T> where T : struct
{
private static readonly Type OpenNullableType = typeof(Nullable<>);
private T[] testData;
public ValueTypeTestData(params T[] testData)
: base()
{
this.testData = testData;
Type[] typeParams = new Type[] { this.Type };
this.RegisterTestDataVariation(TestDataVariations.AsNullable, OpenNullableType.MakeGenericType(typeParams), GetTestDataAsNullable);
}
public IEnumerable<Nullable<T>> GetTestDataAsNullable()
{
return this.GetTypedTestData().Select(d => new Nullable<T>(d));
}
protected override IEnumerable<T> GetTypedTestData()
{
return this.testData;
}
}
}

View File

@@ -0,0 +1,491 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Reflection;
using Xunit;
namespace Microsoft.TestCommon
{
/// <summary>
/// MSTest assertion class to provide convenience and assert methods for generic types
/// whose type parameters are not known at compile time.
/// </summary>
public class GenericTypeAssert
{
private static readonly GenericTypeAssert singleton = new GenericTypeAssert();
public static GenericTypeAssert Singleton { get { return singleton; } }
/// <summary>
/// Asserts the given <paramref name="genericBaseType"/> is a generic type and creates a new
/// bound generic type using <paramref name="genericParameterType"/>. It then asserts there
/// is a constructor that will accept <paramref name="parameterTypes"/> and returns it.
/// </summary>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterType">The type of the single generic parameter to apply to create a bound generic type.</param>
/// <param name="parameterTypes">The list of parameter types for a constructor that must exist.</param>
/// <returns>The <see cref="ConstructorInfo"/> of that constructor which may be invoked to create that new generic type.</returns>
public ConstructorInfo GetConstructor(Type genericBaseType, Type genericParameterType, params Type[] parameterTypes)
{
Assert.NotNull(genericBaseType);
Assert.True(genericBaseType.IsGenericTypeDefinition);
Assert.NotNull(genericParameterType);
Assert.NotNull(parameterTypes);
Type genericType = genericBaseType.MakeGenericType(new Type[] { genericParameterType });
ConstructorInfo ctor = genericType.GetConstructor(parameterTypes);
Assert.True(ctor != null, String.Format("Test error: failed to locate generic ctor for type '{0}<{1}>',", genericBaseType.Name, genericParameterType.Name));
return ctor;
}
/// <summary>
/// Asserts the given <paramref name="genericBaseType"/> is a generic type and creates a new
/// bound generic type using <paramref name="genericParameterType"/>. It then asserts there
/// is a constructor that will accept <paramref name="parameterTypes"/> and returns it.
/// </summary>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterTypes">The types of the generic parameters to apply to create a bound generic type.</param>
/// <param name="parameterTypes">The list of parameter types for a constructor that must exist.</param>
/// <returns>The <see cref="ConstructorInfo"/> of that constructor which may be invoked to create that new generic type.</returns>
public ConstructorInfo GetConstructor(Type genericBaseType, Type[] genericParameterTypes, params Type[] parameterTypes)
{
Assert.NotNull(genericBaseType);
Assert.True(genericBaseType.IsGenericTypeDefinition);
Assert.NotNull(genericParameterTypes);
Assert.NotNull(parameterTypes);
Type genericType = genericBaseType.MakeGenericType(genericParameterTypes);
ConstructorInfo ctor = genericType.GetConstructor(parameterTypes);
Assert.True(ctor != null, String.Format("Test error: failed to locate generic ctor for type '{0}<>',", genericBaseType.Name));
return ctor;
}
/// <summary>
/// Creates a new bound generic type and invokes the constructor matched from <see cref="parameterTypes"/>.
/// </summary>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterType">The type of the single generic parameter to apply to create a bound generic type.</param>
/// <param name="parameterTypes">The list of parameter types for a constructor that must exist.</param>
/// <param name="parameterValues">The list of values to supply to the constructor</param>
/// <returns>The instance created by calling that constructor.</returns>
public object InvokeConstructor(Type genericBaseType, Type genericParameterType, Type[] parameterTypes, object[] parameterValues)
{
ConstructorInfo ctor = GetConstructor(genericBaseType, genericParameterType, parameterTypes);
Assert.NotNull(parameterValues);
Assert.Equal(parameterTypes.Length, parameterValues.Length);
return ctor.Invoke(parameterValues);
}
/// <summary>
/// Creates a new bound generic type and invokes the constructor matched from <see cref="parameterTypes"/>.
/// </summary>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterTypse">The types of the generic parameters to apply to create a bound generic type.</param>
/// <param name="parameterTypes">The list of parameter types for a constructor that must exist.</param>
/// <param name="parameterValues">The list of values to supply to the constructor</param>
/// <returns>The instance created by calling that constructor.</returns>
public object InvokeConstructor(Type genericBaseType, Type[] genericParameterTypes, Type[] parameterTypes, object[] parameterValues)
{
ConstructorInfo ctor = GetConstructor(genericBaseType, genericParameterTypes, parameterTypes);
Assert.NotNull(parameterValues);
Assert.Equal(parameterTypes.Length, parameterValues.Length);
return ctor.Invoke(parameterValues);
}
/// <summary>
/// Creates a new bound generic type and invokes the constructor matched from the types of <paramref name="parameterValues"/>.
/// </summary>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterType">The type of the single generic parameter to apply to create a bound generic type.</param>
/// <param name="parameterValues">The list of values to supply to the constructor. It must be possible to determine the</param>
/// <returns>The instance created by calling that constructor.</returns>
public object InvokeConstructor(Type genericBaseType, Type genericParameterType, params object[] parameterValues)
{
Assert.NotNull(genericBaseType);
Assert.True(genericBaseType.IsGenericTypeDefinition);
Assert.NotNull(genericParameterType);
Type genericType = genericBaseType.MakeGenericType(new Type[] { genericParameterType });
ConstructorInfo ctor = FindConstructor(genericType, parameterValues);
Assert.True(ctor != null, String.Format("Test error: failed to locate generic ctor for type '{0}<{1}>',", genericBaseType.Name, genericParameterType.Name));
return ctor.Invoke(parameterValues);
}
/// <summary>
/// Creates a new bound generic type and invokes the constructor matched from the types of <paramref name="parameterValues"/>.
/// </summary>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterTypes">The types of the generic parameters to apply to create a bound generic type.</param>
/// <param name="parameterValues">The list of values to supply to the constructor. It must be possible to determine the</param>
/// <returns>The instance created by calling that constructor.</returns>
public object InvokeConstructor(Type genericBaseType, Type[] genericParameterTypes, params object[] parameterValues)
{
Assert.NotNull(genericBaseType);
Assert.True(genericBaseType.IsGenericTypeDefinition);
Assert.NotNull(genericParameterTypes);
Type genericType = genericBaseType.MakeGenericType(genericParameterTypes);
ConstructorInfo ctor = FindConstructor(genericType, parameterValues);
Assert.True(ctor != null, String.Format("Test error: failed to locate generic ctor for type '{0}<>',", genericBaseType.Name));
return ctor.Invoke(parameterValues);
}
/// <summary>
/// Creates a new bound generic type and invokes the constructor matched from <see cref="parameterTypes"/>.
/// </summary>
/// <typeparam name="T">The type of object the constuctor is expected to yield.</typeparam>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterType">The type of the single generic parameter to apply to create a bound generic type.</param>
/// <param name="parameterTypes">The list of parameter types for a constructor that must exist.</param>
/// <param name="parameterValues">The list of values to supply to the constructor</param>
/// <returns>An instance of type <typeparamref name="T"/>.</returns>
public T InvokeConstructor<T>(Type genericBaseType, Type genericParameterType, Type[] parameterTypes, object[] parameterValues)
{
ConstructorInfo ctor = GetConstructor(genericBaseType, genericParameterType, parameterTypes);
Assert.NotNull(parameterValues);
Assert.Equal(parameterTypes.Length, parameterValues.Length);
return (T)ctor.Invoke(parameterValues);
}
/// <summary>
/// Creates a new bound generic type and invokes the constructor matched from <see cref="parameterTypes"/>.
/// </summary>
/// <typeparam name="T">The type of object the constuctor is expected to yield.</typeparam>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterTypes">The types of the generic parameters to apply to create a bound generic type.</param>
/// <param name="parameterTypes">The list of parameter types for a constructor that must exist.</param>
/// <param name="parameterValues">The list of values to supply to the constructor</param>
/// <returns>An instance of type <typeparamref name="T"/>.</returns>
public T InvokeConstructor<T>(Type genericBaseType, Type[] genericParameterTypes, Type[] parameterTypes, object[] parameterValues)
{
ConstructorInfo ctor = GetConstructor(genericBaseType, genericParameterTypes, parameterTypes);
Assert.NotNull(parameterValues);
Assert.Equal(parameterTypes.Length, parameterValues.Length);
return (T)ctor.Invoke(parameterValues);
}
/// <summary>
/// Creates a new bound generic type and invokes the constructor matched from <see cref="parameterTypes"/>.
/// </summary>
/// <typeparam name="T">The type of object the constuctor is expected to yield.</typeparam>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterType">The type of the single generic parameter to apply to create a bound generic type.</param>
/// <param name="parameterValues">The list of values to supply to the constructor. It must be possible to determine the</param>
/// <returns>The instance created by calling that constructor.</returns>
/// <returns>An instance of type <typeparamref name="T"/>.</returns>
public T InvokeConstructor<T>(Type genericBaseType, Type genericParameterType, params object[] parameterValues)
{
Assert.NotNull(genericBaseType == null);
Assert.True(genericBaseType.IsGenericTypeDefinition);
Assert.NotNull(genericParameterType);
Type genericType = genericBaseType.MakeGenericType(new Type[] { genericParameterType });
ConstructorInfo ctor = FindConstructor(genericType, parameterValues);
Assert.True(ctor != null, String.Format("Test error: failed to locate generic ctor for type '{0}<{1}>',", genericBaseType.Name, genericParameterType.Name));
return (T)ctor.Invoke(parameterValues);
}
/// <summary>
/// Creates a new bound generic type and invokes the constructor matched from <see cref="parameterTypes"/>.
/// </summary>
/// <typeparam name="T">The type of object the constuctor is expected to yield.</typeparam>
/// <param name="genericBaseType">The unbound generic base type.</param>
/// <param name="genericParameterTypes">The types of the generic parameters to apply to create a bound generic type.</param>
/// <param name="parameterValues">The list of values to supply to the constructor. It must be possible to determine the</param>
/// <returns>The instance created by calling that constructor.</returns>
/// <returns>An instance of type <typeparamref name="T"/>.</returns>
public T InvokeConstructor<T>(Type genericBaseType, Type[] genericParameterTypes, params object[] parameterValues)
{
Assert.NotNull(genericBaseType);
Assert.True(genericBaseType.IsGenericTypeDefinition);
Assert.NotNull(genericParameterTypes);
Type genericType = genericBaseType.MakeGenericType(genericParameterTypes);
ConstructorInfo ctor = FindConstructor(genericType, parameterValues);
Assert.True(ctor != null, String.Format("Test error: failed to locate generic ctor for type '{0}<>',", genericBaseType.Name));
return (T)ctor.Invoke(parameterValues);
}
/// <summary>
/// Asserts the given instance is one from a generic type of the specified parameter type.
/// </summary>
/// <typeparam name="T">The type of instance.</typeparam>
/// <param name="instance">The instance to test.</param>
/// <param name="genericTypeParameter">The type of the generic parameter to which the instance's generic type should have been bound.</param>
public void IsCorrectGenericType<T>(T instance, Type genericTypeParameter)
{
Assert.NotNull(instance);
Assert.NotNull(genericTypeParameter);
Assert.True(instance.GetType().IsGenericType);
Type[] genericArguments = instance.GetType().GetGenericArguments();
Assert.Equal(1, genericArguments.Length);
Assert.Equal(genericTypeParameter, genericArguments[0]);
}
/// <summary>
/// Invokes via Reflection the method on the given instance.
/// </summary>
/// <param name="instance">The instance to use.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="parameterTypes">The types of the parameters to the method.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public object InvokeMethod(object instance, string methodName, Type[] parameterTypes, object[] parameterValues)
{
Assert.NotNull(instance);
Assert.NotNull(parameterTypes);
Assert.NotNull(parameterValues);
Assert.Equal(parameterTypes.Length, parameterValues.Length);
MethodInfo methodInfo = instance.GetType().GetMethod(methodName, parameterTypes);
Assert.NotNull(methodInfo);
return methodInfo.Invoke(instance, parameterValues);
}
/// <summary>
/// Invokes via Reflection the static method on the given type.
/// </summary>
/// <param name="type">The type containing the method.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="parameterTypes">The types of the parameters to the method.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public object InvokeMethod(Type type, string methodName, Type[] parameterTypes, object[] parameterValues)
{
Assert.NotNull(type);
Assert.NotNull(parameterTypes);
Assert.NotNull(parameterValues);
Assert.Equal(parameterTypes.Length, parameterValues.Length);
MethodInfo methodInfo = type.GetMethod(methodName, parameterTypes);
Assert.NotNull(methodInfo);
return methodInfo.Invoke(null, parameterValues);
}
/// <summary>
/// Invokes via Reflection the static method on the given type.
/// </summary>
/// <param name="type">The type containing the method.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="genericParameterType">The generic parameter type of the method.</param>
/// <param name="parameterTypes">The types of the parameters to the method.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public MethodInfo CreateGenericMethod(Type type, string methodName, Type genericParameterType, Type[] parameterTypes)
{
Assert.NotNull(type);
Assert.NotNull(parameterTypes);
Assert.NotNull(genericParameterType);
//MethodInfo methodInfo = type.GetMethod(methodName, parameterTypes);
MethodInfo methodInfo = type.GetMethods().Where((m) => m.Name.Equals(methodName, StringComparison.OrdinalIgnoreCase) && m.IsGenericMethod && AreAssignableFrom(m.GetParameters(), parameterTypes)).FirstOrDefault();
Assert.NotNull(methodInfo);
Assert.True(methodInfo.IsGenericMethod);
MethodInfo genericMethod = methodInfo.MakeGenericMethod(genericParameterType);
Assert.NotNull(genericMethod);
return genericMethod;
}
/// <summary>
/// Invokes via Reflection the static generic method on the given type.
/// </summary>
/// <param name="type">The type containing the method.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="genericParameterType">The generic parameter type of the method.</param>
/// <param name="parameterTypes">The types of the parameters to the method.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public object InvokeGenericMethod(Type type, string methodName, Type genericParameterType, Type[] parameterTypes, object[] parameterValues)
{
MethodInfo methodInfo = CreateGenericMethod(type, methodName, genericParameterType, parameterTypes);
Assert.Equal(parameterTypes.Length, parameterValues.Length);
return methodInfo.Invoke(null, parameterValues);
}
/// <summary>
/// Invokes via Reflection the generic method on the given instance.
/// </summary>
/// <param name="instance">The instance on which to invoke the method.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="genericParameterType">The generic parameter type of the method.</param>
/// <param name="parameterTypes">The types of the parameters to the method.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public object InvokeGenericMethod(object instance, string methodName, Type genericParameterType, Type[] parameterTypes, object[] parameterValues)
{
Assert.NotNull(instance);
MethodInfo methodInfo = CreateGenericMethod(instance.GetType(), methodName, genericParameterType, parameterTypes);
Assert.Equal(parameterTypes.Length, parameterValues.Length);
return methodInfo.Invoke(instance, parameterValues);
}
/// <summary>
/// Invokes via Reflection the generic method on the given instance.
/// </summary>
/// <typeparam name="T">The type of the return value from the method.</typeparam>
/// <param name="instance">The instance on which to invoke the method.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="genericParameterType">The generic parameter type of the method.</param>
/// <param name="parameterTypes">The types of the parameters to the method.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public T InvokeGenericMethod<T>(object instance, string methodName, Type genericParameterType, Type[] parameterTypes, object[] parameterValues)
{
return (T)InvokeGenericMethod(instance, methodName, genericParameterType, parameterTypes, parameterValues);
}
/// <summary>
/// Invokes via Reflection the method on the given instance.
/// </summary>
/// <param name="instance">The instance to use.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public object InvokeMethod(object instance, string methodName, params object[] parameterValues)
{
Assert.NotNull(instance);
MethodInfo methodInfo = FindMethod(instance.GetType(), methodName, parameterValues);
Assert.NotNull(methodInfo);
return methodInfo.Invoke(instance, parameterValues);
}
/// <summary>
/// Invokes via Reflection the static method on the given type.
/// </summary>
/// <param name="instance">The instance to use.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public object InvokeMethod(Type type, string methodName, params object[] parameterValues)
{
Assert.NotNull(type);
MethodInfo methodInfo = FindMethod(type, methodName, parameterValues);
Assert.NotNull(methodInfo);
return methodInfo.Invoke(null, parameterValues);
}
/// <summary>
/// Invokes via Reflection the method on the given instance.
/// </summary>
/// <param name="instance">The instance to use.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="genericParameterType">The type of the generic parameter.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public object InvokeGenericMethod(object instance, string methodName, Type genericParameterType, params object[] parameterValues)
{
Assert.NotNull(instance);
Assert.NotNull(genericParameterType);
MethodInfo methodInfo = FindMethod(instance.GetType(), methodName, parameterValues);
Assert.NotNull(methodInfo);
Assert.True(methodInfo.IsGenericMethod);
MethodInfo genericMethod = methodInfo.MakeGenericMethod(genericParameterType);
return genericMethod.Invoke(instance, parameterValues);
}
/// <summary>
/// Invokes via Reflection the method on the given instance.
/// </summary>
/// <param name="instance">The instance to use.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="genericParameterType">The type of the generic parameter.</param>
/// <param name="parameterValues">The values to supply to the method.</param>
/// <returns>The results of the method.</returns>
public object InvokeGenericMethod(Type type, string methodName, Type genericParameterType, params object[] parameterValues)
{
Assert.NotNull(type);
Assert.NotNull(genericParameterType);
MethodInfo methodInfo = FindMethod(type, methodName, parameterValues);
Assert.NotNull(methodInfo);
Assert.True(methodInfo.IsGenericMethod);
MethodInfo genericMethod = methodInfo.MakeGenericMethod(genericParameterType);
return genericMethod.Invoke(null, parameterValues);
}
/// <summary>
/// Retrieves the value from the specified property.
/// </summary>
/// <param name="instance">The instance containing the property value.</param>
/// <param name="propertyName">The name of the property.</param>
/// <param name="failureMessage">The error message to prefix any test assertions.</param>
/// <returns>The value returned from the property.</returns>
public object GetProperty(object instance, string propertyName, string failureMessage)
{
PropertyInfo propertyInfo = instance.GetType().GetProperty(propertyName);
Assert.NotNull(propertyInfo);
return propertyInfo.GetValue(instance, null);
}
private static bool AreAssignableFrom(Type[] parameterTypes, params object[] parameterValues)
{
Assert.NotNull(parameterTypes);
Assert.NotNull(parameterValues);
if (parameterTypes.Length != parameterValues.Length)
{
return false;
}
for (int i = 0; i < parameterTypes.Length; ++i)
{
if (!parameterTypes[i].IsInstanceOfType(parameterValues[i]))
{
return false;
}
}
return true;
}
private static bool AreAssignableFrom(ParameterInfo[] parameterInfos, params Type[] parameterTypes)
{
Assert.NotNull(parameterInfos);
Assert.NotNull(parameterTypes);
Type[] parameterInfoTypes = parameterInfos.Select<ParameterInfo, Type>((info) => info.ParameterType).ToArray();
if (parameterInfoTypes.Length != parameterTypes.Length)
{
return false;
}
for (int i = 0; i < parameterInfoTypes.Length; ++i)
{
// Generic parameters are assumed to be assignable
if (parameterInfoTypes[i].IsGenericParameter)
{
continue;
}
if (!parameterInfoTypes[i].IsAssignableFrom(parameterTypes[i]))
{
return false;
}
}
return true;
}
private static bool AreAssignableFrom(ParameterInfo[] parameterInfos, params object[] parameterValues)
{
Assert.NotNull(parameterInfos);
Assert.NotNull(parameterValues);
Type[] parameterTypes = parameterInfos.Select<ParameterInfo, Type>((info) => info.ParameterType).ToArray();
return AreAssignableFrom(parameterTypes, parameterValues);
}
private static ConstructorInfo FindConstructor(Type type, params object[] parameterValues)
{
Assert.NotNull(type);
Assert.NotNull(parameterValues);
return type.GetConstructors().FirstOrDefault((c) => AreAssignableFrom(c.GetParameters(), parameterValues));
}
private static MethodInfo FindMethod(Type type, string methodName, params object[] parameterValues)
{
Assert.NotNull(type);
Assert.False(String.IsNullOrWhiteSpace(methodName));
Assert.NotNull(parameterValues);
return type.GetMethods().FirstOrDefault((m) => String.Equals(m.Name, methodName, StringComparison.Ordinal) && AreAssignableFrom(m.GetParameters(), parameterValues));
}
}
}

View File

@@ -0,0 +1,257 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.RegularExpressions;
using Xunit;
namespace Microsoft.TestCommon
{
/// <summary>
/// Unit test utility for testing <see cref="HttpResponseMessage"/> instances.
/// </summary>
public class HttpAssert
{
private const string CommaSeperator = ", ";
private static readonly HttpAssert singleton = new HttpAssert();
public static HttpAssert Singleton { get { return singleton; } }
/// <summary>
/// Asserts that the expected <see cref="HttpRequestMessage"/> is equal to the actual <see cref="HttpRequestMessage"/>.
/// </summary>
/// <param name="expected">The expected <see cref="HttpRequestMessage"/>. Should not be <c>null</c>.</param>
/// <param name="actual">The actual <see cref="HttpRequestMessage"/>. Should not be <c>null</c>.</param>
public void Equal(HttpRequestMessage expected, HttpRequestMessage actual)
{
Assert.NotNull(expected);
Assert.NotNull(actual);
Assert.Equal(expected.Version, actual.Version);
Equal(expected.Headers, actual.Headers);
if (expected.Content == null)
{
Assert.Null(actual.Content);
}
else
{
string expectedContent = CleanContentString(expected.Content.ReadAsStringAsync().Result);
string actualContent = CleanContentString(actual.Content.ReadAsStringAsync().Result);
Assert.Equal(expectedContent, actualContent);
Equal(expected.Content.Headers, actual.Content.Headers);
}
}
/// <summary>
/// Asserts that the expected <see cref="HttpResponseMessage"/> is equal to the actual <see cref="HttpResponseMessage"/>.
/// </summary>
/// <param name="expected">The expected <see cref="HttpResponseMessage"/>. Should not be <c>null</c>.</param>
/// <param name="actual">The actual <see cref="HttpResponseMessage"/>. Should not be <c>null</c>.</param>
public void Equal(HttpResponseMessage expected, HttpResponseMessage actual)
{
Equal(expected, actual, null);
}
/// <summary>
/// Asserts that the expected <see cref="HttpResponseMessage"/> is equal to the actual <see cref="HttpResponseMessage"/>.
/// </summary>
/// <param name="expected">The expected <see cref="HttpResponseMessage"/>. Should not be <c>null</c>.</param>
/// <param name="actual">The actual <see cref="HttpResponseMessage"/>. Should not be <c>null</c>.</param>
/// <param name="verifyContentCallback">The callback to verify the Content string. If it is null, Assert.Equal will be used. </param>
public void Equal(HttpResponseMessage expected, HttpResponseMessage actual, Action<string, string> verifyContentStringCallback)
{
Assert.NotNull(expected);
Assert.NotNull(actual);
Assert.Equal(expected.StatusCode, actual.StatusCode);
Assert.Equal(expected.ReasonPhrase, actual.ReasonPhrase);
Assert.Equal(expected.Version, actual.Version);
Equal(expected.Headers, actual.Headers);
if (expected.Content == null)
{
Assert.Null(actual.Content);
}
else
{
string expectedContent = CleanContentString(expected.Content.ReadAsStringAsync().Result);
string actualContent = CleanContentString(actual.Content.ReadAsStringAsync().Result);
if (verifyContentStringCallback != null)
{
verifyContentStringCallback(expectedContent, actualContent);
}
else
{
Assert.Equal(expectedContent, actualContent);
}
Equal(expected.Content.Headers, actual.Content.Headers);
}
}
/// <summary>
/// Asserts that the expected <see cref="HttpHeaders"/> instance is equal to the actual <see cref="actualHeaders"/> instance.
/// </summary>
/// <param name="expectedHeaders">The expected <see cref="HttpHeaders"/> instance. Should not be <c>null</c>.</param>
/// <param name="actualHeaders">The actual <see cref="HttpHeaders"/> instance. Should not be <c>null</c>.</param>
public void Equal(HttpHeaders expectedHeaders, HttpHeaders actualHeaders)
{
Assert.NotNull(expectedHeaders);
Assert.NotNull(actualHeaders);
Assert.Equal(expectedHeaders.Count(), actualHeaders.Count());
foreach (KeyValuePair<string, IEnumerable<string>> expectedHeader in expectedHeaders)
{
KeyValuePair<string, IEnumerable<string>> actualHeader = actualHeaders.FirstOrDefault(h => h.Key == expectedHeader.Key);
Assert.NotNull(actualHeader);
if (expectedHeader.Key == "Date")
{
HandleDateHeader(expectedHeader.Value.ToArray(), actualHeader.Value.ToArray());
}
else
{
string expectedHeaderStr = string.Join(CommaSeperator, expectedHeader.Value);
string actualHeaderStr = string.Join(CommaSeperator, actualHeader.Value);
Assert.Equal(expectedHeaderStr, actualHeaderStr);
}
}
}
/// <summary>
/// Asserts the given <see cref="HttpHeaders"/> contain the given <paramref name="values"/>
/// for the given <paramref name="name"/>.
/// </summary>
/// <param name="headers">The <see cref="HttpHeaders"/> to examine. It cannot be <c>null</c>.</param>
/// <param name="name">The name of the header. It cannot be empty.</param>
/// <param name="values">The values that must all be present. It cannot be null.</param>
public void Contains(HttpHeaders headers, string name, params string[] values)
{
Assert.NotNull(headers);
Assert.False(String.IsNullOrWhiteSpace(name), "Test error: name cannot be empty.");
Assert.NotNull(values);
IEnumerable<string> headerValues = null;
bool foundIt = headers.TryGetValues(name, out headerValues);
Assert.True(foundIt);
foreach (string value in values)
{
Assert.Contains(value, headerValues);
}
}
public bool IsKnownUnserializableType(Type type, Func<Type, bool> isTypeUnserializableCallback)
{
if (isTypeUnserializableCallback != null && isTypeUnserializableCallback(type))
{
return true;
}
if (type.IsGenericType)
{
if (typeof(IEnumerable).IsAssignableFrom(type))
{
if (type.GetMethod("Add") == null)
{
return true;
}
}
// Generic type -- recursively analyze generic arguments
return IsKnownUnserializableType(type.GetGenericArguments()[0], isTypeUnserializableCallback);
}
if (type.HasElementType && IsKnownUnserializableType(type.GetElementType(), isTypeUnserializableCallback))
{
return true;
}
return false;
}
public bool IsKnownUnserializable(Type type, object obj, Func<Type, bool> isTypeUnserializableCallback)
{
if (IsKnownUnserializableType(type, isTypeUnserializableCallback))
{
return true;
}
return obj != null && IsKnownUnserializableType(obj.GetType(), isTypeUnserializableCallback);
}
public bool IsKnownUnserializable(Type type, object obj)
{
return IsKnownUnserializable(type, obj, null);
}
public bool CanRoundTrip(Type type)
{
if (typeof(TimeSpan).IsAssignableFrom(type))
{
return false;
}
if (typeof(DateTimeOffset).IsAssignableFrom(type))
{
return false;
}
if (type.IsGenericType)
{
foreach (Type genericParameterType in type.GetGenericArguments())
{
if (!CanRoundTrip(genericParameterType))
{
return false;
}
}
}
if (type.HasElementType)
{
return CanRoundTrip(type.GetElementType());
}
return true;
}
private static void HandleDateHeader(string[] expectedDateHeaderValues, string[] actualDateHeaderValues)
{
Assert.Equal(expectedDateHeaderValues.Length, actualDateHeaderValues.Length);
for (int i = 0; i < expectedDateHeaderValues.Length; i++)
{
DateTime expectedDateTime = DateTime.Parse(expectedDateHeaderValues[i]);
DateTime actualDateTime = DateTime.Parse(actualDateHeaderValues[i]);
Assert.Equal(expectedDateTime.Year, actualDateTime.Year);
Assert.Equal(expectedDateTime.Month, actualDateTime.Month);
Assert.Equal(expectedDateTime.Day, actualDateTime.Day);
int hourDifference = Math.Abs(actualDateTime.Hour - expectedDateTime.Hour);
Assert.True(hourDifference <= 1);
int minuteDifference = Math.Abs(actualDateTime.Minute - expectedDateTime.Minute);
Assert.True(minuteDifference <= 1);
}
}
private static string CleanContentString(string content)
{
Assert.Null(content);
string cleanedContent = null;
// remove any port numbers from Uri's
cleanedContent = Regex.Replace(content, ":\\d+", "");
return cleanedContent;
}
}
}

View File

@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Net.Http.Headers;
using Xunit;
namespace Microsoft.TestCommon
{
public class MediaTypeAssert
{
private static readonly MediaTypeAssert singleton = new MediaTypeAssert();
public static MediaTypeAssert Singleton { get { return singleton; } }
public void AreEqual(MediaTypeHeaderValue expected, MediaTypeHeaderValue actual, string errorMessage)
{
if (expected != null || actual != null)
{
Assert.NotNull(expected);
Assert.Equal(0, new MediaTypeHeaderValueComparer().Compare(expected, actual));
}
}
public void AreEqual(MediaTypeHeaderValue expected, string actual, string errorMessage)
{
if (expected != null || !String.IsNullOrEmpty(actual))
{
MediaTypeHeaderValue actualMediaType = new MediaTypeHeaderValue(actual);
Assert.NotNull(expected);
Assert.Equal(0, new MediaTypeHeaderValueComparer().Compare(expected, actualMediaType));
}
}
public void AreEqual(string expected, string actual, string errorMessage)
{
if (!String.IsNullOrEmpty(expected) || !String.IsNullOrEmpty(actual))
{
Assert.NotNull(expected);
MediaTypeHeaderValue expectedMediaType = new MediaTypeHeaderValue(expected);
MediaTypeHeaderValue actualMediaType = new MediaTypeHeaderValue(actual);
Assert.Equal(0, new MediaTypeHeaderValueComparer().Compare(expectedMediaType, actualMediaType));
}
}
public void AreEqual(string expected, MediaTypeHeaderValue actual, string errorMessage)
{
if (!String.IsNullOrEmpty(expected) || actual != null)
{
Assert.NotNull(expected);
MediaTypeHeaderValue expectedMediaType = new MediaTypeHeaderValue(expected); ;
Assert.Equal(0, new MediaTypeHeaderValueComparer().Compare(expectedMediaType, actual));
}
}
}
}

View File

@@ -0,0 +1,90 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Net.Http.Headers;
namespace Microsoft.TestCommon
{
public class MediaTypeHeaderValueComparer : IComparer<MediaTypeHeaderValue>
{
private static readonly MediaTypeHeaderValueComparer mediaTypeComparer = new MediaTypeHeaderValueComparer();
public MediaTypeHeaderValueComparer()
{
}
public static MediaTypeHeaderValueComparer Comparer
{
get
{
return mediaTypeComparer;
}
}
public int Compare(MediaTypeHeaderValue mediaType1, MediaTypeHeaderValue mediaType2)
{
ParsedMediaTypeHeaderValue parsedMediaType1 = new ParsedMediaTypeHeaderValue(mediaType1);
ParsedMediaTypeHeaderValue parsedMediaType2 = new ParsedMediaTypeHeaderValue(mediaType2);
int returnValue = CompareBasedOnQualityFactor(parsedMediaType1, parsedMediaType2);
if (returnValue == 0)
{
if (!String.Equals(parsedMediaType1.Type, parsedMediaType2.Type, StringComparison.OrdinalIgnoreCase))
{
if (parsedMediaType1.IsAllMediaRange)
{
return 1;
}
else if (parsedMediaType2.IsAllMediaRange)
{
return -1;
}
}
else if (!String.Equals(parsedMediaType1.SubType, parsedMediaType2.SubType, StringComparison.OrdinalIgnoreCase))
{
if (parsedMediaType1.IsSubTypeMediaRange)
{
return 1;
}
else if (parsedMediaType2.IsSubTypeMediaRange)
{
return -1;
}
}
else
{
if (!parsedMediaType1.HasNonQualityFactorParameter)
{
if (parsedMediaType2.HasNonQualityFactorParameter)
{
return 1;
}
}
else if (!parsedMediaType2.HasNonQualityFactorParameter)
{
return -1;
}
}
}
return returnValue;
}
private static int CompareBasedOnQualityFactor(ParsedMediaTypeHeaderValue parsedMediaType1, ParsedMediaTypeHeaderValue parsedMediaType2)
{
double qualityDifference = parsedMediaType1.QualityFactor - parsedMediaType2.QualityFactor;
if (qualityDifference < 0)
{
return 1;
}
else if (qualityDifference > 0)
{
return -1;
}
return 0;
}
}
}

View File

@@ -0,0 +1,111 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Net.Http.Headers;
namespace Microsoft.TestCommon
{
internal class ParsedMediaTypeHeaderValue
{
private const string MediaRangeAsterisk = "*";
private const char MediaTypeSubTypeDelimiter = '/';
private const string QualityFactorParameterName = "q";
private const double DefaultQualityFactor = 1.0;
private MediaTypeHeaderValue mediaType;
private string type;
private string subType;
private bool? hasNonQualityFactorParameter;
private double? qualityFactor;
public ParsedMediaTypeHeaderValue(MediaTypeHeaderValue mediaType)
{
this.mediaType = mediaType;
string[] splitMediaType = mediaType.MediaType.Split(MediaTypeSubTypeDelimiter);
this.type = splitMediaType[0];
this.subType = splitMediaType[1];
}
public string Type
{
get
{
return this.type;
}
}
public string SubType
{
get
{
return this.subType;
}
}
public bool IsAllMediaRange
{
get
{
return this.IsSubTypeMediaRange && String.Equals(MediaRangeAsterisk, this.Type, StringComparison.Ordinal);
}
}
public bool IsSubTypeMediaRange
{
get
{
return String.Equals(MediaRangeAsterisk, this.SubType, StringComparison.Ordinal);
}
}
public bool HasNonQualityFactorParameter
{
get
{
if (!this.hasNonQualityFactorParameter.HasValue)
{
this.hasNonQualityFactorParameter = false;
foreach (NameValueHeaderValue param in this.mediaType.Parameters)
{
if (!String.Equals(QualityFactorParameterName, param.Name, StringComparison.Ordinal))
{
this.hasNonQualityFactorParameter = true;
}
}
}
return this.hasNonQualityFactorParameter.Value;
}
}
public string CharSet
{
get
{
return this.mediaType.CharSet;
}
}
public double QualityFactor
{
get
{
if (!this.qualityFactor.HasValue)
{
MediaTypeWithQualityHeaderValue mediaTypeWithQuality = this.mediaType as MediaTypeWithQualityHeaderValue;
if (mediaTypeWithQuality != null)
{
this.qualityFactor = mediaTypeWithQuality.Quality;
}
if (!this.qualityFactor.HasValue)
{
this.qualityFactor = DefaultQualityFactor;
}
}
return this.qualityFactor.Value;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More