Imported Upstream version 5.8.0.22

Former-commit-id: df344e34b07851d296efb3e6604c8db42b6f7aa3
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-10-19 20:04:20 +00:00
parent 5f4a27cc8a
commit 7d05485754
5020 changed files with 114082 additions and 186061 deletions

View File

@@ -2,8 +2,15 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Composition.Runtime.Tests", "tests\System.Composition.Runtime.Tests.csproj", "{52BE9F68-69EC-44AA-806E-11EFB57D9B4B}"
ProjectSection(ProjectDependencies) = postProject
{2711DFD2-8541-4628-BC53-EB784A14CDCF} = {2711DFD2-8541-4628-BC53-EB784A14CDCF}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Composition.Runtime", "src\System.Composition.Runtime.csproj", "{2711DFD2-8541-4628-BC53-EB784A14CDCF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{1A2F9F4A-A032-433E-B914-ADD5992BB178}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E107E9C1-E893-4E87-987E-04EF0DCEAEFD}"
EndProject
Global
@@ -12,6 +19,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{52BE9F68-69EC-44AA-806E-11EFB57D9B4B}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
{52BE9F68-69EC-44AA-806E-11EFB57D9B4B}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
{52BE9F68-69EC-44AA-806E-11EFB57D9B4B}.Release|Any CPU.ActiveCfg = netstandard-Release|Any CPU
{52BE9F68-69EC-44AA-806E-11EFB57D9B4B}.Release|Any CPU.Build.0 = netstandard-Release|Any CPU
{2711DFD2-8541-4628-BC53-EB784A14CDCF}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
{2711DFD2-8541-4628-BC53-EB784A14CDCF}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
{2711DFD2-8541-4628-BC53-EB784A14CDCF}.Release|Any CPU.ActiveCfg = netstandard-Release|Any CPU
@@ -21,6 +32,7 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{52BE9F68-69EC-44AA-806E-11EFB57D9B4B} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
{2711DFD2-8541-4628-BC53-EB784A14CDCF} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD}
EndGlobalSection
EndGlobal

View File

@@ -1,91 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.17626
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace System.Composition.Properties {
using System;
using System.Reflection;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Composition.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to No export was found for the contract &apos;{0}&apos;..
/// </summary>
internal static string CompositionContext_NoExportFoundForContract {
get {
return ResourceManager.GetString("CompositionContext_NoExportFoundForContract", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Composition failed..
/// </summary>
internal static string CompositionFailedDefaultExceptionMessage {
get {
return ResourceManager.GetString("CompositionFailedDefaultExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to , .
/// </summary>
internal static string Formatter_ListSeparatorWithSpace {
get {
return ResourceManager.GetString("Formatter_ListSeparatorWithSpace", resourceCulture);
}
}
}
}

View File

@@ -67,4 +67,4 @@
<data name="Formatter_ListSeparatorWithSpace" xml:space="preserve">
<value>, </value>
</data>
</root>
</root>

View File

@@ -12,17 +12,6 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard1.0-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard1.0-Release|AnyCPU'" />
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="System\Composition\CompositionContext.cs" />
<Compile Include="System\Composition\ExportFactoryOfT.cs" />
<Compile Include="System\Composition\ExportFactoryOfTTMetadata.cs" />

View File

@@ -149,7 +149,7 @@ namespace System.Composition
object export;
if (!TryGetExport(contract, out export))
throw new CompositionFailedException(
string.Format(Properties.Resources.CompositionContext_NoExportFoundForContract, contract));
string.Format(SR.CompositionContext_NoExportFoundForContract, contract));
return export;
}

View File

@@ -18,12 +18,7 @@ namespace System.Composition
/// <param name="exportCreator">Action invoked upon calls to the Create() method.</param>
public ExportFactory(Func<Tuple<T, Action>> exportCreator)
{
if (exportCreator == null)
{
throw new ArgumentNullException(nameof(exportCreator));
}
_exportLifetimeContextCreator = exportCreator;
_exportLifetimeContextCreator = exportCreator ?? throw new ArgumentNullException(nameof(exportCreator));
}
/// <summary>

View File

@@ -11,8 +11,6 @@ namespace System.Composition
/// <typeparam name="TMetadata">The metadata required from the export.</typeparam>
public class ExportFactory<T, TMetadata> : ExportFactory<T>
{
private readonly TMetadata _metadata;
/// <summary>
/// Construct an ExportFactory.
/// </summary>
@@ -21,16 +19,13 @@ namespace System.Composition
public ExportFactory(Func<Tuple<T, Action>> exportCreator, TMetadata metadata)
: base(exportCreator)
{
_metadata = metadata;
Metadata = metadata;
}
/// <summary>
/// The metadata associated with the export.
/// </summary>
public TMetadata Metadata
{
get { return _metadata; }
}
public TMetadata Metadata { get; }
}
}

View File

@@ -11,7 +11,6 @@ namespace System.Composition
/// <typeparam name="T"></typeparam>
public sealed class Export<T> : IDisposable
{
private readonly T _value;
private readonly Action _disposeAction;
/// <summary>
@@ -21,31 +20,19 @@ namespace System.Composition
/// <param name="disposeAction">An action that releases resources associated with the export.</param>
public Export(T value, Action disposeAction)
{
_value = value;
Value = value;
_disposeAction = disposeAction;
}
/// <summary>
/// The exported value.
/// </summary>
public T Value
{
get
{
return _value;
}
}
public T Value { get; }
/// <summary>
/// Release the parts associated with the exported value.
/// </summary>
public void Dispose()
{
if (_disposeAction != null)
{
_disposeAction.Invoke();
}
}
public void Dispose() => _disposeAction?.Invoke();
}
}

View File

@@ -15,7 +15,7 @@ namespace System.Composition.Hosting
/// Construct a <see cref="CompositionFailedException"/> with the default message.
/// </summary>
public CompositionFailedException()
: base(Properties.Resources.CompositionFailedDefaultExceptionMessage)
: base(SR.CompositionFailedDefaultExceptionMessage)
{ }
/// <summary>

View File

@@ -46,7 +46,7 @@ namespace System.Composition.Hosting.Core
public CompositionContract(Type contractType, string contractName, IDictionary<string, object> metadataConstraints)
{
if (contractType == null) throw new ArgumentNullException(nameof(contractType));
if (metadataConstraints != null && metadataConstraints.Count == 0) throw new ArgumentOutOfRangeException(nameof(metadataConstraints));
if (metadataConstraints?.Count == 0) throw new ArgumentOutOfRangeException(nameof(metadataConstraints));
_contractType = contractType;
_contractName = contractName;
@@ -56,18 +56,18 @@ namespace System.Composition.Hosting.Core
/// <summary>
/// The type shared between the exporter and importer.
/// </summary>
public Type ContractType { get { return _contractType; } }
public Type ContractType => _contractType;
/// <summary>
/// A name that discriminates this contract from others with the same type.
/// </summary>
public string ContractName { get { return _contractName; } }
public string ContractName => _contractName;
/// <summary>
/// Constraints applied to the contract. Instead of using this collection
/// directly it is advisable to use the <see cref="TryUnwrapMetadataConstraint"/> method.
/// </summary>
public IEnumerable<KeyValuePair<string, object>> MetadataConstraints { get { return _metadataConstraints; } }
public IEnumerable<KeyValuePair<string, object>> MetadataConstraints => _metadataConstraints;
/// <summary>
/// Determines equality between two contracts.
@@ -110,7 +110,7 @@ namespace System.Composition.Hosting.Core
if (_metadataConstraints != null)
result += string.Format(" {{ {0} }}",
string.Join(Properties.Resources.Formatter_ListSeparatorWithSpace,
string.Join(SR.Formatter_ListSeparatorWithSpace,
_metadataConstraints.Select(kv => string.Format("{0} = {1}", kv.Key, Formatters.Format(kv.Value)))));
return result;
@@ -149,8 +149,7 @@ namespace System.Composition.Hosting.Core
if (_metadataConstraints == null)
return false;
object value;
if (!_metadataConstraints.TryGetValue(constraintName, out value))
if (!_metadataConstraints.TryGetValue(constraintName, out object value))
return false;
if (!(value is T))
@@ -182,10 +181,9 @@ namespace System.Composition.Hosting.Core
if (first.Count != second.Count)
return false;
foreach (var firstItem in first)
foreach (KeyValuePair<string, object> firstItem in first)
{
object secondValue;
if (!second.TryGetValue(firstItem.Key, out secondValue))
if (!second.TryGetValue(firstItem.Key, out object secondValue))
return false;
if (firstItem.Value == null && secondValue != null ||
@@ -195,8 +193,7 @@ namespace System.Composition.Hosting.Core
}
else
{
var firstEnumerable = firstItem.Value as IEnumerable;
if (firstEnumerable != null && !(firstEnumerable is string))
if (firstItem.Value is IEnumerable firstEnumerable && !(firstEnumerable is string))
{
var secondEnumerable = secondValue as IEnumerable;
if (secondEnumerable == null || !Enumerable.SequenceEqual(firstEnumerable.Cast<object>(), secondEnumerable.Cast<object>()))
@@ -215,20 +212,18 @@ namespace System.Composition.Hosting.Core
private static int ConstraintHashCode(IDictionary<string, object> metadata)
{
var result = -1;
foreach (var kv in metadata)
foreach (KeyValuePair<string, object> kv in metadata)
{
result ^= kv.Key.GetHashCode();
if (kv.Value != null)
{
var sval = kv.Value as string;
if (sval != null)
if (kv.Value is string sval)
{
result ^= sval.GetHashCode();
}
else
{
var enumerableValue = kv.Value as IEnumerable;
if (enumerableValue != null)
if (kv.Value is IEnumerable enumerableValue)
{
foreach (var ev in enumerableValue)
if (ev != null)

View File

@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace System.Composition.Runtime.Util
@@ -31,11 +33,11 @@ namespace System.Composition.Runtime.Util
private static string FormatClosedGeneric(Type closedGenericType)
{
if (closedGenericType == null) throw new ArgumentNullException(nameof(closedGenericType));
if (!closedGenericType.IsConstructedGenericType) throw new ArgumentException();
Debug.Assert(closedGenericType != null);
Debug.Assert(closedGenericType.IsConstructedGenericType);
var name = closedGenericType.Name.Substring(0, closedGenericType.Name.IndexOf("`"));
var args = closedGenericType.GenericTypeArguments.Select(t => Format(t));
return string.Format("{0}<{1}>", name, string.Join(Properties.Resources.Formatter_ListSeparatorWithSpace, args));
IEnumerable<string> args = closedGenericType.GenericTypeArguments.Select(t => Format(t));
return string.Format("{0}<{1}>", name, string.Join(SR.Formatter_ListSeparatorWithSpace, args));
}
}
}

View File

@@ -0,0 +1,141 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Composition.Hosting;
using System.Composition.Hosting.Core;
using Xunit;
namespace System.Composition.Tests
{
public class CompositionContextTests
{
[Theory]
[InlineData(true, null)]
[InlineData(false, null)]
[InlineData(true, "contractName")]
[InlineData(false, "contractName")]
public void GetExport_Invoke_ReturnsExpected(bool success, string contractName)
{
var context = new SubContext(contract =>
{
Assert.Equal(typeof(int), contract.ContractType);
Assert.Equal(contractName, contract.ContractName);
Assert.Null(contract.MetadataConstraints);
return (success, 10);
});
if (success)
{
if (contractName == null)
{
Assert.Equal(10, context.GetExport<int>());
Assert.Equal(10, context.GetExport(typeof(int)));
Assert.True(context.TryGetExport(out int export1));
Assert.Equal(10, export1);
Assert.True(context.TryGetExport(typeof(int), out object export2));
Assert.Equal(10, export2);
}
else
{
Assert.Equal(10, context.GetExport<int>(contractName));
Assert.Equal(10, context.GetExport(typeof(int), contractName));
Assert.True(context.TryGetExport(contractName, out int export1));
Assert.Equal(10, export1);
Assert.True(context.TryGetExport(typeof(int), contractName, out object export2));
Assert.Equal(10, export2);
}
}
else
{
if (contractName == null)
{
Assert.Throws<CompositionFailedException>(() => context.GetExport<int>());
Assert.Throws<CompositionFailedException>(() => context.GetExport(typeof(int)));
Assert.False(context.TryGetExport(out int export1));
Assert.Equal(0, export1);
// Failure leaks through.
Assert.False(context.TryGetExport(typeof(int), out object export2));
Assert.Equal(10, export2);
}
else
{
Assert.Throws<CompositionFailedException>(() => context.GetExport<int>(contractName));
Assert.Throws<CompositionFailedException>(() => context.GetExport(typeof(int), contractName));
Assert.False(context.TryGetExport(contractName, out int export1));
Assert.Equal(0, export1);
// Failure leaks through.
Assert.False(context.TryGetExport(typeof(int), contractName, out object export2));
Assert.Equal(10, export2);
}
}
}
[Theory]
[InlineData(true, null)]
[InlineData(false, null)]
[InlineData(true, "contractName")]
[InlineData(false, "contractName")]
public void GetExports_Invoke_ReturnsExpected(bool success, string contractName)
{
var context = new SubContext(contract =>
{
Assert.Equal(typeof(object[]), contract.ContractType);
Assert.Equal(contractName, contract.ContractName);
Assert.Equal(new Dictionary<string, object> { { "IsImportMany", true } }, contract.MetadataConstraints);
return (success, new object[] { 10 });
});
if (success)
{
if (contractName == null)
{
Assert.Equal(new object[] { 10 }, context.GetExports<object>());
Assert.Equal(new object[] { 10 }, context.GetExports(typeof(object)));
}
else
{
Assert.Equal(new object[] { 10 }, context.GetExports<object>(contractName));
Assert.Equal(new object[] { 10 }, context.GetExports(typeof(object), contractName));
}
}
else
{
if (contractName == null)
{
Assert.Throws<CompositionFailedException>(() => context.GetExports<object>());
Assert.Throws<CompositionFailedException>(() => context.GetExports(typeof(object)));
}
else
{
Assert.Throws<CompositionFailedException>(() => context.GetExports<object>(contractName));
Assert.Throws<CompositionFailedException>(() => context.GetExports(typeof(object), contractName));
}
}
}
public class SubContext : CompositionContext
{
public Func<CompositionContract, (bool, object)> Handler { get; }
public SubContext(Func<CompositionContract, (bool, object)> handler) => Handler = handler;
public override bool TryGetExport(CompositionContract contract, out object export)
{
(bool result, object exportResult) = Handler(contract);
export = exportResult;
return result;
}
}
}
}

View File

@@ -0,0 +1,326 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using Xunit;
namespace System.Composition.Hosting.Core.Tests
{
public class CompositionContractTests
{
[Theory]
[InlineData(typeof(int))]
public void Ctor_ContractType(Type contractType)
{
var contract = new CompositionContract(contractType);
Assert.Equal(contractType, contract.ContractType);
Assert.Null(contract.ContractName);
Assert.Null(contract.MetadataConstraints);
}
[Theory]
[InlineData(typeof(int), null)]
[InlineData(typeof(object), "contractName")]
public void Ctor_ContractType(Type contractType, string contractName)
{
var contract = new CompositionContract(contractType, contractName);
Assert.Equal(contractType, contract.ContractType);
Assert.Equal(contractName, contract.ContractName);
Assert.Null(contract.MetadataConstraints);
}
public static IEnumerable<object[]> Ctor_ContractType_ContractName_MetadataConstraints_TestData()
{
yield return new object[] { typeof(int), null, null };
yield return new object[] { typeof(object), "contractName", new Dictionary<string, object> { { "key", "value" } } };
}
[Theory]
[MemberData(nameof(Ctor_ContractType_ContractName_MetadataConstraints_TestData))]
public void Ctor_ContractType_MetadataConstraints(Type contractType, string contractName, IDictionary<string, object> metadataConstraints)
{
var contract = new CompositionContract(contractType, contractName, metadataConstraints);
Assert.Equal(contractType, contract.ContractType);
Assert.Equal(contractName, contract.ContractName);
Assert.Equal(metadataConstraints, contract.MetadataConstraints);
}
[Fact]
public void Ctor_NullContractType_ThrowsArgumentNullException()
{
AssertExtensions.Throws<ArgumentNullException>("contractType", () => new CompositionContract(null));
AssertExtensions.Throws<ArgumentNullException>("contractType", () => new CompositionContract(null, "contractName"));
AssertExtensions.Throws<ArgumentNullException>("contractType", () => new CompositionContract(null, "contractName", new Dictionary<string, object>()));
}
[Fact]
public void Ctor_EmptyMetadataConstraints_ThrowsArgumentOutOfRangeException()
{
AssertExtensions.Throws<ArgumentOutOfRangeException>("metadataConstraints", () => new CompositionContract(typeof(string), "contractName", new Dictionary<string, object>()));
}
public static IEnumerable<object[]> Equals_TestData()
{
yield return new object[] { new CompositionContract(typeof(int)), new CompositionContract(typeof(int)), true };
yield return new object[] { new CompositionContract(typeof(int)), new CompositionContract(typeof(string)), false };
yield return new object[] { new CompositionContract(typeof(int)), new CompositionContract(typeof(int), "contractName"), false };
yield return new object[] { new CompositionContract(typeof(int)), new CompositionContract(typeof(int), null, new Dictionary<string, object> { { "key", "value" } }), false };
yield return new object[] { new CompositionContract(typeof(int), "contractName"), new CompositionContract(typeof(int), "contractName"), true };
yield return new object[] { new CompositionContract(typeof(int), "contractName"), new CompositionContract(typeof(int), "ContractName"), false };
yield return new object[] { new CompositionContract(typeof(int), "contractName"), new CompositionContract(typeof(int)), false };
yield return new object[] { new CompositionContract(typeof(int)), new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }), false };
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }),
true
};
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", 1 } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", 1 } }),
true
};
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", new string[] { "1", null } } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", new object[] { "1", null } } }),
true
};
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", new string[] { "1", null } } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", new object[] { "1", new object() } } }),
false
};
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" }, { "key2", "value2" } }),
false
};
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" }, { "key2", "value2" } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }),
false
};
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key2", "value" } }),
false
};
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value2" } }),
false
};
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", new string[0] } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", new string[1] } }),
false
};
yield return new object[]
{
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", new string[0] } }),
new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }),
false
};
yield return new object[] { new CompositionContract(typeof(int)), new object(), false };
yield return new object[] { new CompositionContract(typeof(int)), null, false };
}
[Theory]
[MemberData(nameof(Equals_TestData))]
public void Equals_Object_ReturnsExpected(CompositionContract contract, object other, bool expected)
{
Assert.Equal(expected, contract.Equals(other));
Assert.Equal(contract.GetHashCode(), contract.GetHashCode());
}
[Fact]
public void Equals_NullValueInDictionaryNotInOther_ReturnsFalse()
{
// These tests can't be in MemberData as an ArgumentNullException is thrown in the ToString method, which is invoked by xunit.
Equals_Object_ReturnsExpected(new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", null } }), new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }), false);
Equals_Object_ReturnsExpected(new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", "value" } }), new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", null } }), false);
Equals_Object_ReturnsExpected(new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", new object[0] } }), new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", null } }), false);
}
[Fact]
public void Equals_NullValueInDictionaryAndOther_ThrowsNullReferenceException()
{
var contract = new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", null } });
var other = new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", null } });
Assert.Throws<NullReferenceException>(() => contract.Equals(other));
}
[Fact]
public void ChangeType_ValidType_Success()
{
var dictionary = new Dictionary<string, object> { { "key", "value" } };
var contract = new CompositionContract(typeof(int), "contractName", dictionary);
CompositionContract newContract = contract.ChangeType(typeof(string));
Assert.Equal(typeof(int), contract.ContractType);
Assert.Equal(typeof(string), newContract.ContractType);
Assert.Equal("contractName", newContract.ContractName);
Assert.Same(dictionary, newContract.MetadataConstraints);
}
[Fact]
public void ChangeType_NullNewContractType_ThrowsArgumentNullException()
{
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("newContractType", () => contract.ChangeType(null));
}
[Fact]
public void TryUnwrapMetadataConstraint_NullConstraints_ReturnsFalse()
{
var contract = new CompositionContract(typeof(int));
Assert.False(contract.TryUnwrapMetadataConstraint("constraintName", out int constraintValue, out CompositionContract remainingContract));
Assert.Equal(0, constraintValue);
Assert.Null(remainingContract);
}
[Fact]
public void TryUnwrapMetadataConstraint_NoSuchConstraintName_ReturnsFalse()
{
var contract = new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "constraint", 1 } });
Assert.False(contract.TryUnwrapMetadataConstraint("constraintName", out int constraintValue, out CompositionContract remainingContract));
Assert.Equal(0, constraintValue);
Assert.Null(remainingContract);
}
[Fact]
public void TryUnwrapMetadataConstraint_IncorrectConstraintNameType_ReturnsFalse()
{
var contract = new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "constraintName", "value" } });
Assert.False(contract.TryUnwrapMetadataConstraint("constraintName", out int constraintValue, out CompositionContract remainingContract));
Assert.Equal(0, constraintValue);
Assert.Null(remainingContract);
}
[Fact]
public void TryUnwrapMetadataConstraint_UnwrapAllConstraints_ReturnsTrue()
{
var originalContract = new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "constraintName1", 1 }, { "constraintName2", 2 } });
Assert.True(originalContract.TryUnwrapMetadataConstraint("constraintName1", out int constraintValue1, out CompositionContract remainingContract1));
Assert.Equal(1, constraintValue1);
Assert.Equal(originalContract.ContractType, remainingContract1.ContractType);
Assert.Equal(originalContract.ContractName, remainingContract1.ContractName);
Assert.Equal(new Dictionary<string, object> { { "constraintName2", 2 } }, remainingContract1.MetadataConstraints);
Assert.NotEqual(originalContract.MetadataConstraints, remainingContract1.MetadataConstraints);
Assert.True(remainingContract1.TryUnwrapMetadataConstraint("constraintName2", out int constraintValue2, out CompositionContract remainingContract2));
Assert.Equal(2, constraintValue2);
Assert.Equal(originalContract.ContractType, remainingContract2.ContractType);
Assert.Equal(originalContract.ContractName, remainingContract2.ContractName);
Assert.Null(remainingContract2.MetadataConstraints);
Assert.NotEqual(originalContract.MetadataConstraints, remainingContract2.MetadataConstraints);
}
[Fact]
public void TryUnwrapMetadataConstraint_NullContractName_ThrowsArgumentNullException()
{
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("constraintName", () => contract.TryUnwrapMetadataConstraint(null, out int unusedValue, out CompositionContract unusedContract));
}
public static IEnumerable<object[]> ToString_TestData()
{
yield return new object[] { new CompositionContract(typeof(int)), "Int32" };
yield return new object[] { new CompositionContract(typeof(int), "contractName"), "Int32 \"contractName\"" };
yield return new object[] { new CompositionContract(typeof(List<>), "contractName", new Dictionary<string, object> { { "key1", "value" }, { "key2", 2 } }), "List`1 \"contractName\" { key1 = \"value\", key2 = 2 }" };
yield return new object[] { new CompositionContract(typeof(List<string>), "contractName", new Dictionary<string, object> { { "key1", "value" }, { "key2", 2 } }), "List<String> \"contractName\" { key1 = \"value\", key2 = 2 }" };
}
[Theory]
[MemberData(nameof(ToString_TestData))]
public void ToString_Get_ReturnsExpected(CompositionContract contract, string expected)
{
Assert.Equal(expected, contract.ToString());
}
[Fact]
public void ToString_NullValueInDictionary_ThrowsArgumentNullException()
{
var contract = new CompositionContract(typeof(int), "contractName", new Dictionary<string, object> { { "key", null } });
AssertExtensions.Throws<ArgumentNullException>("value", () => contract.ToString());
}
[Fact]
public void ToString_NullTypeInGenericTypeArguments_ThrowsArgumentNullException()
{
var contract = new CompositionContract(new SubType() { GenericTypeArgumentsOverride = new Type[] { null } });
AssertExtensions.Throws<ArgumentNullException>("type", () => contract.ToString());
}
private class SubType : Type
{
public override Assembly Assembly => throw new NotImplementedException();
public override string AssemblyQualifiedName => throw new NotImplementedException();
public override Type BaseType => throw new NotImplementedException();
public override string FullName => throw new NotImplementedException();
public override Guid GUID => throw new NotImplementedException();
public override Module Module => throw new NotImplementedException();
public override string Namespace => throw new NotImplementedException();
public override Type UnderlyingSystemType => throw new NotImplementedException();
public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => throw new NotImplementedException();
public override object[] GetCustomAttributes(bool inherit) => throw new NotImplementedException();
public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotImplementedException();
public override Type GetElementType() => throw new NotImplementedException();
public override EventInfo GetEvent(string name, BindingFlags bindingAttr) => throw new NotImplementedException();
public override EventInfo[] GetEvents(BindingFlags bindingAttr) => throw new NotImplementedException();
public override FieldInfo GetField(string name, BindingFlags bindingAttr) => throw new NotImplementedException();
public override FieldInfo[] GetFields(BindingFlags bindingAttr) => throw new NotImplementedException();
public override Type GetInterface(string name, bool ignoreCase) => throw new NotImplementedException();
public override Type[] GetInterfaces() => throw new NotImplementedException();
public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => throw new NotImplementedException();
public override MethodInfo[] GetMethods(BindingFlags bindingAttr) => throw new NotImplementedException();
public override Type GetNestedType(string name, BindingFlags bindingAttr) => throw new NotImplementedException();
public override Type[] GetNestedTypes(BindingFlags bindingAttr) => throw new NotImplementedException();
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => throw new NotImplementedException();
public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) => throw new NotImplementedException();
public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException();
protected override TypeAttributes GetAttributeFlagsImpl() => throw new NotImplementedException();
protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) => throw new NotImplementedException();
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) => throw new NotImplementedException();
protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) => throw new NotImplementedException();
protected override bool HasElementTypeImpl() => throw new NotImplementedException();
protected override bool IsArrayImpl() => throw new NotImplementedException();
protected override bool IsByRefImpl() => throw new NotImplementedException();
protected override bool IsCOMObjectImpl() => throw new NotImplementedException();
protected override bool IsPointerImpl() => throw new NotImplementedException();
protected override bool IsPrimitiveImpl() => throw new NotImplementedException();
public override string Name => "Name`1";
public override bool IsConstructedGenericType => true;
public Type[] GenericTypeArgumentsOverride { get; set; }
public override Type[] GenericTypeArguments => GenericTypeArgumentsOverride;
}
}
}

View File

@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Xunit;
namespace System.Composition.Hosting.Tests
{
public class CompositionFailedExceptionTests
{
[Fact]
public void Ctor_Default()
{
var exception = new CompositionFailedException();
Assert.NotEmpty(exception.Message);
Assert.Null(exception.InnerException);
}
[Theory]
[InlineData("")]
[InlineData("message")]
public void Ctor_Message(string message)
{
var exception = new CompositionFailedException(message);
Assert.Equal(message, exception.Message);
Assert.Null(exception.InnerException);
}
[Theory]
[InlineData("")]
[InlineData("message")]
public void Ctor_Message_InnerException(string message)
{
var innerException = new DivideByZeroException();
var exception = new CompositionFailedException(message, innerException);
Assert.Equal(message, exception.Message);
Assert.Same(innerException, exception.InnerException);
}
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
netstandard;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,54 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Xunit;
namespace System.Composition.Tests
{
public class ExportFactoryTMetadataTests
{
[Fact]
public void CreateExport_ValidCreator_ReturnsExpected()
{
var factory = new ExportFactory<int, string>(ExportCreator, "metadata");
Assert.Equal("metadata", factory.Metadata);
Assert.Equal(0, ExportCreatorCalled);
Assert.Equal(0, ExportActionCalled);
Export<int> export = factory.CreateExport();
Assert.Equal(1, export.Value);
Assert.Equal(1, ExportCreatorCalled);
Assert.Equal(0, ExportActionCalled);
export.Dispose();
Assert.Equal(1, ExportCreatorCalled);
Assert.Equal(1, ExportActionCalled);
}
[Fact]
public void CreateExport_MultipleTimes_ReturnsDifferentExports()
{
var factory = new ExportFactory<int, string>(ExportCreator, "metadata");
Export<int> export1 = factory.CreateExport();
Export<int> export2 = factory.CreateExport();
Assert.Equal(2, ExportCreatorCalled);
Assert.NotSame(export1, export2);
}
[Fact]
public void Ctor_NullExport_ThrowsArgumentNullException()
{
AssertExtensions.Throws<ArgumentNullException>("exportCreator", () => new ExportFactory<int, string>(null, "metadata"));
}
private int ExportCreatorCalled { get; set; }
private int ExportActionCalled { get; set; }
private Tuple<int, Action> ExportCreator()
{
ExportCreatorCalled++;
return Tuple.Create<int, Action>(1, () => ExportActionCalled++);
}
}
}

View File

@@ -0,0 +1,53 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Xunit;
namespace System.Composition.Tests
{
public class ExportFactoryTests
{
[Fact]
public void CreateExport_ValidCreator_ReturnsExpected()
{
var factory = new ExportFactory<int>(ExportCreator);
Assert.Equal(0, ExportCreatorCalled);
Assert.Equal(0, ExportActionCalled);
Export<int> export = factory.CreateExport();
Assert.Equal(1, export.Value);
Assert.Equal(1, ExportCreatorCalled);
Assert.Equal(0, ExportActionCalled);
export.Dispose();
Assert.Equal(1, ExportCreatorCalled);
Assert.Equal(1, ExportActionCalled);
}
[Fact]
public void CreateExport_MultipleTimes_ReturnsDifferentExports()
{
var factory = new ExportFactory<int>(ExportCreator);
Export<int> export1 = factory.CreateExport();
Export<int> export2 = factory.CreateExport();
Assert.Equal(2, ExportCreatorCalled);
Assert.NotSame(export1, export2);
}
[Fact]
public void Ctor_NullExport_ThrowsArgumentNullException()
{
AssertExtensions.Throws<ArgumentNullException>("exportCreator", () => new ExportFactory<int>(null));
}
private int ExportCreatorCalled { get; set; }
private int ExportActionCalled { get; set; }
private Tuple<int, Action> ExportCreator()
{
ExportCreatorCalled++;
return Tuple.Create<int, Action>(1, () => ExportActionCalled++);
}
}
}

View File

@@ -0,0 +1,43 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Composition;
using Xunit;
namespace System.Compostition.Tests
{
public class ExportTests
{
[Fact]
public void Ctor_Value_Action()
{
int exportActionCalled = 0;
var export = new Export<int>(1, () => exportActionCalled++);
Assert.Equal(1, export.Value);
Assert.Equal(0, exportActionCalled);
}
[Fact]
public void Dispose_MultipleTimes_InvokesDisposeAction()
{
int exportActionCalled = 0;
Export<int> export = new Export<int>(1, () => exportActionCalled++);
Assert.Equal(0, exportActionCalled);
export.Dispose();
Assert.Equal(1, exportActionCalled);
export.Dispose();
Assert.Equal(2, exportActionCalled);
}
[Fact]
public void Dispose_NullAction_Nop()
{
Export<int> export = new Export<int>(1, null);
export.Dispose();
export.Dispose();
}
}
}

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<ProjectGuid>{52BE9F68-69EC-44AA-806E-11EFB57D9B4B}</ProjectGuid>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="CompositionFailedExceptionTests.cs" />
<Compile Include="CompositionContextTests.cs" />
<Compile Include="CompositionContractTests.cs" />
<Compile Include="ExportFactoryTMetadataTests.cs" />
<Compile Include="ExportFactoryTests.cs" />
<Compile Include="ExportTests.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>