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.Hosting.Tests", "tests\System.Composition.Hosting.Tests.csproj", "{52BE9F68-69EC-44AA-806E-11EFB57D9B4B}"
ProjectSection(ProjectDependencies) = postProject
{2B8FECC6-34A1-48FE-BA75-99572D2D6DB2} = {2B8FECC6-34A1-48FE-BA75-99572D2D6DB2}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Composition.Hosting", "src\System.Composition.Hosting.csproj", "{2B8FECC6-34A1-48FE-BA75-99572D2D6DB2}"
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
{2B8FECC6-34A1-48FE-BA75-99572D2D6DB2}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
{2B8FECC6-34A1-48FE-BA75-99572D2D6DB2}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
{2B8FECC6-34A1-48FE-BA75-99572D2D6DB2}.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}
{2B8FECC6-34A1-48FE-BA75-99572D2D6DB2} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD}
EndGlobalSection
EndGlobal

View File

@@ -3,10 +3,8 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Composition;
using System.Composition.Hosting;
using System.Diagnostics;
using System.Composition.Hosting.Properties;
namespace Microsoft.Internal
{
@@ -14,7 +12,7 @@ namespace Microsoft.Internal
{
private static Exception LogException(Exception e)
{
Debug.WriteLine(Resources.Diagnostic_ThrowingException, e.ToString());
Debug.WriteLine(SR.Diagnostic_ThrowingException, e.ToString());
return e;
}
@@ -27,7 +25,7 @@ namespace Microsoft.Internal
public static CompositionFailedException CardinalityMismatch_TooManyExports(string exportKey)
{
var e = new CompositionFailedException(string.Format(Resources.CardinalityMismatch_TooManyExports, exportKey));
var e = new CompositionFailedException(SR.Format(SR.CardinalityMismatch_TooManyExports, exportKey));
LogException(e);
return e;
}
@@ -41,7 +39,7 @@ namespace Microsoft.Internal
internal static Exception NotImplemented_MetadataCycles()
{
var e = new NotImplementedException(Resources.NotImplemented_MetadataCycles);
var e = new NotImplementedException(SR.NotImplemented_MetadataCycles);
LogException(e);
return e;
}

View File

@@ -1,235 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace System.Composition.Hosting.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("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 &quot;Only one export for the contract &apos;{0}&apos; is allowed, multiple implementations were found.&quot;.
/// </summary>
internal static string CardinalityMismatch_TooManyExports {
get {
return ResourceManager.GetString("CardinalityMismatch_TooManyExports", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The component (unknown) cannot be created outside the {0} sharing boundary..
/// </summary>
internal static string Component_NotCreatableOutsideSharingBoundary {
get {
return ResourceManager.GetString("Component_NotCreatableOutsideSharingBoundary", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sharing lock is required.
/// </summary>
internal static string CompositionOperation_SharingLockRequired {
get {
return ResourceManager.GetString("CompositionOperation_SharingLockRequired", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No export was found for the contract &apos;{0}&apos;.
/// </summary>
internal static string Dependency_ExportNotFound {
get {
return ResourceManager.GetString("Dependency_ExportNotFound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &apos;{0}&apos;.
/// </summary>
internal static string Dependency_QuoteParameter {
get {
return ResourceManager.GetString("Dependency_QuoteParameter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Only one export for the contract &apos;{0}&apos; is allowed, but the following parts: {1} export it..
/// </summary>
internal static string Dependency_TooManyExports {
get {
return ResourceManager.GetString("Dependency_TooManyExports", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &apos;{0}&apos; on contract &apos;{1}&apos; supplied by {2}.
/// </summary>
internal static string Dependency_ToStringFormat {
get {
return ResourceManager.GetString("Dependency_ToStringFormat", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Exception Thrown: {0}\r\n.
/// </summary>
internal static string Diagnostic_ThrowingException {
get {
return ResourceManager.GetString("Diagnostic_ThrowingException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to -&gt; required by initial request for contract &apos;{0}&apos;.
/// </summary>
internal static string ExportDescriptor_DependencyErrorContract {
get {
return ResourceManager.GetString("ExportDescriptor_DependencyErrorContract", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to -&gt; required by import &apos;{0}&apos; of part &apos;{1}&apos;.
/// </summary>
internal static string ExportDescriptor_DependencyErrorLine {
get {
return ResourceManager.GetString("ExportDescriptor_DependencyErrorLine", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} supplied by {1}.
/// </summary>
internal static string ExportDescriptor_ToStringFormat {
get {
return ResourceManager.GetString("ExportDescriptor_ToStringFormat", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Detected an unsupported cycle for part &apos;{0}&apos;. To construct a valid cycle, at least one part in the cycle must be shared, and at least one import in the cycle must be non-prerequisite (e.g. a property)..
/// </summary>
internal static string ExportDescriptor_UnsupportedCycle {
get {
return ResourceManager.GetString("ExportDescriptor_UnsupportedCycle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Export descriptor fulfillment function returned null..
/// </summary>
internal static string ExportDescriptorNull {
get {
return ResourceManager.GetString("ExportDescriptorNull", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to , .
/// </summary>
internal static string Formatter_ListSeparatorWithSpace {
get {
return ResourceManager.GetString("Formatter_ListSeparatorWithSpace", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;none&gt;.
/// </summary>
internal static string Formatter_None {
get {
return ResourceManager.GetString("Formatter_None", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Metadata View Provider.
/// </summary>
internal static string Keyword_MetadataViewProvider {
get {
return ResourceManager.GetString("Keyword_MetadataViewProvider", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The type &apos;{0}&apos; cannot be used as a metadata view. A metadata view must be a concrete class with a parameterless or dictionary constructor..
/// </summary>
internal static string MetadataViewProvider_InvalidViewImplementation {
get {
return ResourceManager.GetString("MetadataViewProvider_InvalidViewImplementation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Export metadata for &apos;{0}&apos; is missing and no default value was supplied..
/// </summary>
internal static string MetadataViewProvider_MissingMetadata {
get {
return ResourceManager.GetString("MetadataViewProvider_MissingMetadata", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Metadata value circularity not possible, use lazy initialization..
/// </summary>
internal static string NotImplemented_MetadataCycles {
get {
return ResourceManager.GetString("NotImplemented_MetadataCycles", resourceCulture);
}
}
}
}

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />

View File

@@ -37,11 +37,6 @@
<Link>Microsoft\Internal\Requires.cs</Link>
</Compile>
<Compile Include="Microsoft\Internal\ThrowHelper.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="System\Composition\Hosting\CompositionHost.cs" />
<Compile Include="System\Composition\Hosting\Core\CompositeActivator.cs" />
<Compile Include="System\Composition\Hosting\Core\CompositionDependency.cs" />
@@ -76,12 +71,6 @@
<LastGenOutput>CommonStrings.Designer.cs</LastGenOutput>
<CustomToolNamespace>Microsoft.Internal</CustomToolNamespace>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
<CustomToolNamespace>System.Composition.Hosting.Properties</CustomToolNamespace>
</EmbeddedResource>
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard1.0'">
<Reference Include="System.Collections" />

View File

@@ -133,7 +133,7 @@ namespace System.Composition.Hosting.Core
if (IsError)
return Site.ToString();
return string.Format(Properties.Resources.Dependency_ToStringFormat, Site, Target.Contract, Target.Origin);
return SR.Format(SR.Dependency_ToStringFormat, Site, Target.Contract, Target.Origin);
}
internal bool IsError { get { return _target == null; } }
@@ -144,12 +144,12 @@ namespace System.Composition.Hosting.Core
if (_oversuppliedTargets != null)
{
var list = Formatters.ReadableList(_oversuppliedTargets.Select(t => string.Format(Properties.Resources.Dependency_QuoteParameter, t.Origin)));
message.AppendFormat(Properties.Resources.Dependency_TooManyExports, Contract, list);
var list = Formatters.ReadableList(_oversuppliedTargets.Select(t => SR.Format(SR.Dependency_QuoteParameter, t.Origin)));
message.AppendFormat(SR.Dependency_TooManyExports, Contract, list);
}
else
{
message.AppendFormat(Properties.Resources.Dependency_ExportNotFound, Contract);
message.AppendFormat(SR.Dependency_ExportNotFound, Contract);
}
}
}

View File

@@ -41,7 +41,10 @@ namespace System.Composition.Hosting.Core
private object Activate(LifetimeContext context, CompositionOperation operation)
{
Assumes.IsTrue(_exportDescriptor.IsValueCreated, "Activation in progress before all descriptors fully initialized.");
if (!_exportDescriptor.IsValueCreated)
{
throw ThrowHelper.NotImplemented_MetadataCycles();
}
Debug.WriteLine("[System.Composition] Activating via cycle-breaking proxy.");
return _exportDescriptor.Value.Activator(context, operation);

View File

@@ -83,9 +83,9 @@ namespace System.Composition.Hosting.Core
_creating = true;
try
{
var reply = _descriptor.Value;
Assumes.IsTrue(reply != null, "Export descriptor fulfillment function returned null.");
return reply;
ExportDescriptor relay = _descriptor.Value;
Requires.NotNull(relay, "descriptor");
return relay;
}
finally
{
@@ -99,7 +99,7 @@ namespace System.Composition.Hosting.Core
/// <returns>A description of the promise.</returns>
public override string ToString()
{
return string.Format(Properties.Resources.ExportDescriptor_ToStringFormat, Contract, Origin);
return SR.Format(SR.ExportDescriptor_ToStringFormat, Contract, Origin);
}
}
}

View File

@@ -93,7 +93,7 @@ namespace System.Composition.Hosting.Core
if (step.Target.Equals(dependency.Target))
{
var message = new StringBuilder();
message.AppendFormat(Properties.Resources.ExportDescriptor_UnsupportedCycle, dependency.Target.Origin);
message.AppendFormat(SR.ExportDescriptor_UnsupportedCycle, dependency.Target.Origin);
message.AppendLine();
message.Append(DescribeCompositionStack(dependency, checking));
throw ThrowHelper.CompositionException(message.ToString());
@@ -117,12 +117,12 @@ namespace System.Composition.Hosting.Core
foreach (var step in dependencies)
{
result.AppendFormat(Properties.Resources.ExportDescriptor_DependencyErrorLine, import.Site, step.Target.Origin);
result.AppendFormat(SR.ExportDescriptor_DependencyErrorLine, import.Site, step.Target.Origin);
result.AppendLine();
import = step;
}
result.AppendFormat(Properties.Resources.ExportDescriptor_DependencyErrorContract, import.Contract);
result.AppendFormat(SR.ExportDescriptor_DependencyErrorContract, import.Contract);
return result;
}

View File

@@ -92,7 +92,7 @@ namespace System.Composition.Hosting.Core
// To generate acceptable error messages here we're going to need to pass in a description
// of the component, or otherwise find a way to get one.
throw ThrowHelper.CompositionException(string.Format(Properties.Resources.Component_NotCreatableOutsideSharingBoundary, sharingBoundary));
throw ThrowHelper.CompositionException(SR.Format(SR.Component_NotCreatableOutsideSharingBoundary, sharingBoundary));
}
/// <summary>

View File

@@ -19,8 +19,7 @@ namespace System.Composition.Hosting.Providers.ExportFactory
public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(CompositionContract contract, DependencyAccessor definitionAccessor)
{
if (!contract.ContractType.GetTypeInfo().IsGenericType ||
contract.ContractType.GetGenericTypeDefinition() != typeof(ExportFactory<,>))
if (!contract.ContractType.IsConstructedGenericType || contract.ContractType.GetGenericTypeDefinition() != typeof(ExportFactory<,>))
return NoExportDescriptors;
var ga = contract.ContractType.GenericTypeArguments;

View File

@@ -23,7 +23,7 @@ namespace System.Composition.Hosting.Providers.Metadata
return m => (TMetadata)m;
if (!typeof(TMetadata).GetTypeInfo().IsClass)
throw new CompositionFailedException(string.Format(Properties.Resources.MetadataViewProvider_InvalidViewImplementation, typeof(TMetadata).Name));
throw new CompositionFailedException(SR.Format(SR.MetadataViewProvider_InvalidViewImplementation, typeof(TMetadata).Name));
var ti = typeof(TMetadata).GetTypeInfo();
var dictionaryConstructor = ti.DeclaredConstructors.SingleOrDefault(ci =>
@@ -71,7 +71,7 @@ namespace System.Composition.Hosting.Providers.Metadata
.Compile();
}
throw new CompositionFailedException(string.Format(Properties.Resources.MetadataViewProvider_InvalidViewImplementation, typeof(TMetadata).Name));
throw new CompositionFailedException(SR.Format(SR.MetadataViewProvider_InvalidViewImplementation, typeof(TMetadata).Name));
}
private static TValue GetMetadataValue<TValue>(IDictionary<string, object> metadata, string name, DefaultValueAttribute defaultValue)
@@ -84,7 +84,7 @@ namespace System.Composition.Hosting.Providers.Metadata
return (TValue)defaultValue.Value;
// This could be significantly improved by describing the target metadata property.
var message = string.Format(Properties.Resources.MetadataViewProvider_MissingMetadata, name);
var message = SR.Format(SR.MetadataViewProvider_MissingMetadata, name);
throw ThrowHelper.CompositionException(message);
}
}

View File

@@ -14,8 +14,8 @@ namespace System.Composition.Hosting.Util
{
Assumes.NotNull(items);
string reply = string.Join(Properties.Resources.Formatter_ListSeparatorWithSpace, items.OrderBy(t => t));
return !string.IsNullOrEmpty(reply) ? reply : Properties.Resources.Formatter_None;
string reply = string.Join(SR.Formatter_ListSeparatorWithSpace, items.OrderBy(t => t));
return !string.IsNullOrEmpty(reply) ? reply : SR.Formatter_None;
}
public static string Format(Type type)

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,23 @@
<?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="System\Composition\Hosting\Core\CompositionDependencyTests.cs" />
<Compile Include="System\Composition\Hosting\Core\CompositionHostTests.cs" />
<Compile Include="System\Composition\Hosting\Core\DependencyAccessorTests.cs" />
<Compile Include="System\Composition\Hosting\Core\ExportDescriptorPromiseTests.cs" />
<Compile Include="System\Composition\Hosting\Core\CompositionOperationTests.cs" />
<Compile Include="System\Composition\Hosting\Core\ExportDescriptorProviderTests.cs" />
<Compile Include="System\Composition\Hosting\Core\LifetimeContextTests.cs" />
<Compile Include="System\Composition\Hosting\Core\ExportDescriptorTests.cs" />
<Compile Include="$(CommonTestPath)\System\PlatformDetection.cs">
<Link>Common\System\PlatformDetection.cs</Link>
</Compile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

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.Linq;
using Xunit;
namespace System.Composition.Hosting.Core.Tests
{
public class CompositionDependencyTests
{
[Fact]
public void Missing_Invoke_ReturnsExpected()
{
var contract = new CompositionContract(typeof(int));
CompositionDependency dependency = CompositionDependency.Missing(contract, "Site");
Assert.Same(contract, dependency.Contract);
Assert.Equal("Site", dependency.Site);
Assert.Null(dependency.Target);
Assert.False(dependency.IsPrerequisite);
Assert.Equal("Site", dependency.ToString());
}
[Fact]
public void Missing_NullContract_ThrowsArgumentNullException()
{
AssertExtensions.Throws<ArgumentNullException>("contract", () => CompositionDependency.Missing(null, new object()));
}
[Fact]
public void Missing_NullSite_ThrowsArgumentNullException()
{
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("site", () => CompositionDependency.Missing(contract, null));
}
[Fact]
public void Satisfied_Invoke_ReturnsExpected()
{
var contract = new CompositionContract(typeof(int));
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", false, () => Enumerable.Empty<CompositionDependency>(), dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
CompositionDependency dependency = CompositionDependency.Satisfied(contract, target, true, "Site");
Assert.Same(contract, dependency.Contract);
Assert.Equal("Site", dependency.Site);
Assert.Same(target, dependency.Target);
Assert.True(dependency.IsPrerequisite);
Assert.Equal("'Site' on contract 'Int32' supplied by Origin", dependency.ToString());
}
[Fact]
public void Satisfied_NullContract_ThrowsArgumentNullException()
{
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
AssertExtensions.Throws<ArgumentNullException>("contract", () => CompositionDependency.Satisfied(null, target, false , new object()));
}
[Fact]
public void Satisfied_NullTarget_ThrowsArgumentNullException()
{
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("target", () => CompositionDependency.Satisfied(contract, null, false, new object()));
}
[Fact]
public void Satisfied_NullSite_ThrowsArgumentNullException()
{
var contract = new CompositionContract(typeof(int));
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
AssertExtensions.Throws<ArgumentNullException>("site", () => CompositionDependency.Satisfied(contract, target, false, null));
}
public static IEnumerable<object[]> Oversupplied_TestData()
{
yield return new object[] { Enumerable.Empty<ExportDescriptorPromise>() };
yield return new object[] { new ExportDescriptorPromise[] { null } };
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", false, () => Enumerable.Empty<CompositionDependency>(), dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
yield return new object[] { new ExportDescriptorPromise[] { target } };
}
[Theory]
[MemberData(nameof(Oversupplied_TestData))]
public void Oversupplied_Invoke_ReturnsExpected(IEnumerable<ExportDescriptorPromise> targets)
{
var contract = new CompositionContract(typeof(int));
CompositionDependency dependency = CompositionDependency.Oversupplied(contract, targets, "Site");
Assert.Same(contract, dependency.Contract);
Assert.Equal("Site", dependency.Site);
Assert.Null(dependency.Target);
Assert.False(dependency.IsPrerequisite);
Assert.Equal("Site", dependency.ToString());
}
[Fact]
public void Oversupplied_NullContract_ThrowsArgumentNullException()
{
AssertExtensions.Throws<ArgumentNullException>("contract", () => CompositionDependency.Oversupplied(null, Enumerable.Empty<ExportDescriptorPromise>(), new object()));
}
[Fact]
public void Oversupplied_NullTargets_ThrowsArgumentNullException()
{
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("targets", () => CompositionDependency.Oversupplied(contract, null, new object()));
}
[Fact]
public void Oversupplied_NullSite_ThrowsArgumentNullException()
{
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("site", () => CompositionDependency.Oversupplied(contract, Enumerable.Empty<ExportDescriptorPromise>(), null));
}
private static object Activator(LifetimeContext context, CompositionOperation operation) => null;
}
}

View File

@@ -0,0 +1,266 @@
// 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.Linq;
using Xunit;
namespace System.Composition.Hosting.Core.Tests
{
public class CompositionHostTests
{
[Fact]
public void GetExport_CompositionContextContract_ReturnsExpected()
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[0]))
{
Assert.True(host.TryGetExport(new CompositionContract(typeof(CompositionContext)), out object export));
Assert.IsType<LifetimeContext>(export);
}
}
[Fact]
public void GetExport_MultipleDependencies_ReturnsExpected()
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new MultipleDependency()))
{
Assert.True(host.TryGetExport(new CompositionContract(typeof(int)), out object export));
Assert.Equal("hi", export);
}
}
public class MultipleDependency : ExportDescriptorProvider
{
public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(CompositionContract contract, DependencyAccessor descriptorAccessor)
{
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin1", true, () =>
{
var dependencyTarget = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin2", true, () => Enumerable.Empty<CompositionDependency>(), dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
return new CompositionDependency[]
{
CompositionDependency.Satisfied(contract, dependencyTarget, true, "Site")
};
}, dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
return new ExportDescriptorPromise[] { target };
}
}
[Theory]
[InlineData(typeof(int), new Type[] { typeof(int) })]
[InlineData(typeof(IList<>), new Type[] { typeof(IList<>) })]
[InlineData(typeof(ICollection<>), new Type[] { typeof(ICollection<>) })]
[InlineData(typeof(IEnumerable<>), new Type[] { typeof(IEnumerable<>) })]
[InlineData(typeof(IList<string>), new Type[] { typeof(IList<string>) })]
[InlineData(typeof(ICollection<string>), new Type[] { typeof(ICollection<string>) })]
[InlineData(typeof(IEnumerable<string>), new Type[] { typeof(IEnumerable<string>) })]
[InlineData(typeof(string[]), new Type[] { typeof(string[]) })]
[InlineData(typeof(Lazy<>), new Type[] { typeof(Lazy<>) })]
[InlineData(typeof(Lazy<int>), new Type[] { typeof(int), typeof(Lazy<int>) })]
[InlineData(typeof(Lazy<,>), new Type[] { typeof(Lazy<,>) })]
[InlineData(typeof(Lazy<int, IDictionary<string, object>>), new Type[] { typeof(int), typeof(Lazy<int, IDictionary<string, object>>) })]
[InlineData(typeof(Lazy<int, Dictionary<string, object>>), new Type[] { typeof(int), typeof(Lazy<int, Dictionary<string, object>>) })]
[InlineData(typeof(Lazy<int, ParameterlessConstructor>), new Type[] { typeof(int), typeof(Lazy<int, ParameterlessConstructor>) })]
[InlineData(typeof(ExportFactory<>), new Type[] { typeof(ExportFactory<>) })]
[InlineData(typeof(ExportFactory<int>), new Type[] { typeof(int), typeof(ExportFactory<int>) })]
[InlineData(typeof(ExportFactory<,>), new Type[] { typeof(ExportFactory<,>) })]
[InlineData(typeof(ExportFactory<int, IDictionary<string, object>>), new Type[] { typeof(int), typeof(ExportFactory<int, IDictionary<string, object>>) })]
public void GetExport_LazyOrExportFactoryContractType_ReturnsExpected(Type type, Type[] expectedContractTypes)
{
var tracker = new TrackingProvider();
using (CompositionHost host = CompositionHost.CreateCompositionHost(tracker))
{
Assert.False(host.TryGetExport(type, out object export));
Assert.Equal(expectedContractTypes, tracker.Contracts.Select(c => c.ContractType));
}
}
[Theory]
[InlineData(typeof(string[]), new Type[] { typeof(string[]), typeof(string) })]
[InlineData(typeof(IList<string>), new Type[] { typeof(IList<string>), typeof(string) })]
[InlineData(typeof(ICollection<string>), new Type[] { typeof(ICollection<string>), typeof(string) })]
[InlineData(typeof(IEnumerable<string>), new Type[] { typeof(IEnumerable<string>), typeof(string) })]
public void GetExport_ImoportManyWithMetadataConstraints_ReturnsExpected(Type contractType, Type[] expectedTypes)
{
var tracker = new TrackingProvider();
using (CompositionHost host = CompositionHost.CreateCompositionHost(tracker))
{
var contract = new CompositionContract(contractType, "contractName", new Dictionary<string, object> { { "IsImportMany", true } });
Assert.True(host.TryGetExport(contract, out object export));
Assert.Empty(Assert.IsAssignableFrom<Array>(export));
Assert.Equal(expectedTypes, tracker.Contracts.Select(c => c.ContractType));
}
}
[Theory]
[InlineData(typeof(ExportFactory<int>), null, new Type[] { typeof(int), typeof(ExportFactory<int>) })]
[InlineData(typeof(ExportFactory<int>), new string[] { "1", "2", "3" }, new Type[] { typeof(int), typeof(ExportFactory<int>) })]
[InlineData(typeof(ExportFactory<int, ParameterlessConstructor>), null, new Type[] { typeof(int), typeof(ExportFactory<int, ParameterlessConstructor>) })]
[InlineData(typeof(ExportFactory<int, ParameterlessConstructor>), new string[] { "1", "2", "3" }, new Type[] { typeof(int), typeof(ExportFactory<int, ParameterlessConstructor>) })]
public void GetExport_ExportFactoryContractWithMetadataConstraints_ReturnsExpected(Type contractType, string[] sharingBoundaryNames, Type[] expectedTypes)
{
var tracker = new TrackingProvider();
using (CompositionHost host = CompositionHost.CreateCompositionHost(tracker))
{
var contract = new CompositionContract(contractType, "contractName", new Dictionary<string, object> { { "SharingBoundaryNames", sharingBoundaryNames } });
Assert.False(host.TryGetExport(contract, out object export));
Assert.Equal(expectedTypes, tracker.Contracts.Select(c => c.ContractType));
}
}
private class TrackingProvider : ExportDescriptorProvider
{
public List<CompositionContract> Contracts { get; } = new List<CompositionContract>();
public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(CompositionContract contract, DependencyAccessor descriptorAccessor)
{
Contracts.Add(contract);
return new ExportDescriptorPromise[0];
}
}
[Theory]
[InlineData(typeof(Lazy<int, int>))]
[InlineData(typeof(Lazy<int, IDictionary<string, string>>))]
[InlineData(typeof(Lazy<int, PrivateConstructor>))]
[InlineData(typeof(Lazy<int, NoParameterlessConstructor>))]
public void GetExport_InvalidMetadata_ThrowsComposititionFailedException(Type type)
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[0]))
{
Assert.Throws<CompositionFailedException>(() => host.TryGetExport(type, out object _));
}
}
[Fact]
public void GetExport_AbstractMetadata_ThrowsInvalidOperationException()
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[0]))
{
Assert.Throws<InvalidOperationException>(() => host.TryGetExport(typeof(Lazy<int, AbstractConstructor>), out object _));
}
}
[Fact]
public void GetExport_NullProviderInProviders_ThrowsNullReferenceException()
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[] { null }))
{
Assert.Throws<NullReferenceException>(() => host.GetExport<int>());
}
}
[Fact]
public void TryGetExport_NullContract_ThrowsArgumentNullException()
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[0]))
{
AssertExtensions.Throws<ArgumentNullException>("key", () => host.TryGetExport((CompositionContract)null, out object export));
}
}
[Fact]
public void GetExport_MultipleReturns_ThrowsCompositionFailedException()
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new MultiplePromises()))
{
Assert.Throws<CompositionFailedException>(() => host.TryGetExport(new CompositionContract(typeof(int)), out object export));
}
}
public class MultiplePromises : ExportDescriptorProvider
{
public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(CompositionContract contract, DependencyAccessor descriptorAccessor)
{
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
return new ExportDescriptorPromise[] { target, target };
}
}
[Fact]
public void GetExport_FailedDependency_ThrowsCompositionFailedException()
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new FailedDependency()))
{
Assert.Throws<CompositionFailedException>(() => host.TryGetExport(new CompositionContract(typeof(int)), out object export));
}
}
public class FailedDependency : ExportDescriptorProvider
{
public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(CompositionContract contract, DependencyAccessor descriptorAccessor)
{
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () =>
{
return new CompositionDependency[]
{
CompositionDependency.Missing(contract, "site")
};
}, dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
return new ExportDescriptorPromise[] { target };
}
}
[Fact]
public void CreateCompositionHost_NullProvider_ThrowsArgumentNullException()
{
AssertExtensions.Throws<ArgumentNullException>("providers", () => CompositionHost.CreateCompositionHost(null));
AssertExtensions.Throws<ArgumentNullException>("providers", () => CompositionHost.CreateCompositionHost((IEnumerable<ExportDescriptorProvider>)null));
}
[Fact]
public void Dispose_MultipleTimes_Success()
{
CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[0]);
host.Dispose();
host.Dispose();
}
private static object Activator(LifetimeContext context, CompositionOperation operation) => "hi";
private class ParameterlessConstructor
{
public ParameterlessConstructor() { }
public int PublicProperty { get; set; }
public static int PublicStaticProperty { get; set; }
public int GetOnlyProperty { get; }
public int SetOnlyProperty { set { } }
private int PrivateProperty { get; set; }
}
private class PrivateConstructor
{
private PrivateConstructor() { }
}
private class NoParameterlessConstructor
{
public NoParameterlessConstructor(int x) { }
}
private abstract class AbstractConstructor
{
public AbstractConstructor() { }
}
}
}

View File

@@ -0,0 +1,101 @@
// 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 Xunit;
namespace System.Composition.Hosting.Core.Tests
{
public class CompositionOperationTests
{
[Fact]
public void Run_ValidContextAndAction_ReturnsExpected()
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[0]))
{
Assert.True(host.TryGetExport(new CompositionContract(typeof(CompositionContext)), out object export));
LifetimeContext context = Assert.IsType<LifetimeContext>(export);
var results = new List<string>();
void NonPrequisiteAction1() => results.Add("NonPrequisiteAction1");
void NonPrequisiteAction2() => results.Add("NonPrequisiteAction2");
void PostCompositionAction1() => results.Add("PostCompositionAction1");
void PostCompositionAction2() => results.Add("PostCompositionAction2");
object Activator(LifetimeContext activatorContext, CompositionOperation activatorOperation)
{
Assert.Same(context, activatorContext);
activatorOperation.AddNonPrerequisiteAction(NonPrequisiteAction1);
activatorOperation.AddNonPrerequisiteAction(NonPrequisiteAction2);
activatorOperation.AddPostCompositionAction(PostCompositionAction1);
activatorOperation.AddPostCompositionAction(PostCompositionAction2);
return "Hi";
}
Assert.Equal("Hi", CompositionOperation.Run(context, Activator));
Assert.Equal(new string[] { "NonPrequisiteAction1", "NonPrequisiteAction2", "PostCompositionAction1", "PostCompositionAction2" }, results);
}
}
[Fact]
public void Run_NullOutmostContext_ThrowsArgumentNullException()
{
AssertExtensions.Throws<ArgumentNullException>("outermostLifetimeContext", () => CompositionOperation.Run(null, Activator));
}
[Fact]
public void Run_NullActivator_ThrowsArgumentNullException()
{
using (CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[0]))
{
Assert.True(host.TryGetExport(new CompositionContract(typeof(CompositionContext)), out object export));
LifetimeContext context = Assert.IsType<LifetimeContext>(export);
AssertExtensions.Throws<ArgumentNullException>("compositionRootActivator", () => CompositionOperation.Run(context, null));
}
}
[Fact]
public void AddNonPrequisiteAction_NullAction_ThrowsArgumentNullException()
{
object Activator(LifetimeContext context, CompositionOperation operation)
{
AssertExtensions.Throws<ArgumentNullException>("action", () => operation.AddNonPrerequisiteAction(null));
return null;
}
using (CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[0]))
{
Assert.True(host.TryGetExport(new CompositionContract(typeof(CompositionContext)), out object export));
LifetimeContext context = Assert.IsType<LifetimeContext>(export);
CompositionOperation.Run(context, Activator);
}
}
[Fact]
public void AddPostCompositionAction_NullAction_ThrowsArgumentNullException()
{
object Activator(LifetimeContext context, CompositionOperation operation)
{
AssertExtensions.Throws<ArgumentNullException>("action", () => operation.AddPostCompositionAction(null));
return null;
}
using (CompositionHost host = CompositionHost.CreateCompositionHost(new ExportDescriptorProvider[0]))
{
Assert.True(host.TryGetExport(new CompositionContract(typeof(CompositionContext)), out object export));
LifetimeContext context = Assert.IsType<LifetimeContext>(export);
CompositionOperation.Run(context, Activator);
}
}
private static object Activator(LifetimeContext context, CompositionOperation operation) => null;
}
}

View File

@@ -0,0 +1,153 @@
// 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;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace System.Composition.Hosting.Core.Tests
{
public class DependencyAccessorTests
{
[Fact]
public void ResolveDependencies_PromisesReturnsEmpty_ReturnsEmpty()
{
var accessor = new SubAccessor { Result = new ExportDescriptorPromise[0] };
var contract = new CompositionContract(typeof(int));
Assert.Empty(accessor.ResolveDependencies("Site", contract, true));
Assert.Same(contract, accessor.Contract);
}
[Fact]
public void ResolveDependencies_PromisesReturnsNonEmpty_ReturnsExpected()
{
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", false, () => Enumerable.Empty<CompositionDependency>(), dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
var accessor = new SubAccessor { Result = new ExportDescriptorPromise[] { target } };
var contract = new CompositionContract(typeof(int));
CompositionDependency dependency = Assert.Single(accessor.ResolveDependencies("Site", contract, true));
Assert.Same(contract, accessor.Contract);
Assert.Same(contract, dependency.Contract);
Assert.Equal("Site", dependency.Site);
Assert.True(dependency.IsPrerequisite);
Assert.Same(target, dependency.Target);
}
[Fact]
public void ResolveDependencies_PromisesReturnsNull_ThrowsArgumentNullException()
{
var accessor = new SubAccessor();
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("source", () => accessor.ResolveDependencies("Site", contract, true));
Assert.Same(contract, accessor.Contract);
}
[Fact]
public void ResolveDependencies_PromisesReturnsNullObjectInArray_ThrowsArgumentNullException()
{
var accessor = new SubAccessor { Result = new ExportDescriptorPromise[] { null } };
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("target", () => accessor.ResolveDependencies("Site", contract, true));
Assert.Same(contract, accessor.Contract);
}
[Fact]
public void ResolveRequiredDependency_PromisesReturnsEmpty_ReturnsMissing()
{
var accessor = new SubAccessor { Result = new ExportDescriptorPromise[0] };
var contract = new CompositionContract(typeof(int));
CompositionDependency dependency = accessor.ResolveRequiredDependency("Site", contract, true);
Assert.Same(contract, accessor.Contract);
Assert.Same(contract, dependency.Contract);
Assert.Equal("Site", dependency.Site);
Assert.False(dependency.IsPrerequisite);
Assert.Null(dependency.Target);
}
[Fact]
public void ResolveRequiredDependency_PromisesReturnsOneTarget_ReturnsStatisfied()
{
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", false, () => Enumerable.Empty<CompositionDependency>(), dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
var accessor = new SubAccessor { Result = new ExportDescriptorPromise[] { target } };
var contract = new CompositionContract(typeof(int));
CompositionDependency dependency = accessor.ResolveRequiredDependency("Site", contract, true);
Assert.Same(contract, accessor.Contract);
Assert.Same(contract, dependency.Contract);
Assert.Equal("Site", dependency.Site);
Assert.True(dependency.IsPrerequisite);
Assert.Same(target, dependency.Target);
}
[Fact]
public void ResolveRequiredDependency_PromisesReturnsMultipleTargets_ReturnsStatisfied()
{
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var target = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", false, () => Enumerable.Empty<CompositionDependency>(), dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
var accessor = new SubAccessor { Result = new ExportDescriptorPromise[] { target, target } };
var contract = new CompositionContract(typeof(int));
CompositionDependency dependency = accessor.ResolveRequiredDependency("Site", contract, true);
Assert.Same(contract, accessor.Contract);
Assert.Same(contract, dependency.Contract);
Assert.Equal("Site", dependency.Site);
Assert.False(dependency.IsPrerequisite);
Assert.Null(dependency.Target);
}
[Fact]
public void ResolveRequiredDependency_PromisesReturnsNull_ThrowsArgumentNullException()
{
var accessor = new SubAccessor();
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("source", () => accessor.ResolveRequiredDependency("Site", contract, true));
Assert.Same(contract, accessor.Contract);
}
[Fact]
public void ResolveRequiredDependency_PromisesReturnsNullObjectInArray_ThrowsArgumentNullException()
{
var accessor = new SubAccessor { Result = new ExportDescriptorPromise[] { null } };
var contract = new CompositionContract(typeof(int));
AssertExtensions.Throws<ArgumentNullException>("target", () => accessor.ResolveRequiredDependency("Site", contract, true));
Assert.Same(contract, accessor.Contract);
}
private class SubAccessor : DependencyAccessor
{
public CompositionContract Contract { get; set; }
public IEnumerable<ExportDescriptorPromise> Result { get; set; }
protected override IEnumerable<ExportDescriptorPromise> GetPromises(CompositionContract exportKey)
{
Contract = exportKey;
return Result;
}
}
private static object Activator(LifetimeContext context, CompositionOperation operation) => "hi";
}
}

View File

@@ -0,0 +1,267 @@
// 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;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace System.Composition.Hosting.Core.Tests
{
public class ExportDescriptorPromiseTests
{
public static IEnumerable<object[]> Ctor_Depedencies()
{
yield return new object[] { null, null, false, Enumerable.Empty<CompositionDependency>() };
yield return new object[] { new CompositionContract(typeof(int)), "Origin", true, Enumerable.Empty<CompositionDependency>() };
}
[Theory]
[MemberData(nameof(Ctor_Depedencies))]
public void Ctor_Dependencies(CompositionContract contract, string origin, bool isShared, IEnumerable<CompositionDependency> dependencies)
{
int calledDependencies = 0;
int calledGetDescriptor = 0;
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var promise = new ExportDescriptorPromise(contract, origin, isShared, () =>
{
calledDependencies++;
return dependencies;
}, getDependencies =>
{
Assert.Equal(dependencies, getDependencies);
calledGetDescriptor++;
return descriptor;
});
Assert.Same(contract, promise.Contract);
Assert.Same(origin, promise.Origin);
Assert.Equal(isShared, promise.IsShared);
// The Dependencies parameter should only be invoked once.
Assert.Equal(0, calledDependencies);
Assert.Equal(0, calledGetDescriptor);
Assert.Equal(dependencies, promise.Dependencies);
Assert.Equal(1, calledDependencies);
Assert.Equal(0, calledGetDescriptor);
Assert.Same(promise.Dependencies, promise.Dependencies);
Assert.Equal(1, calledDependencies);
Assert.Equal(0, calledGetDescriptor);
// The GetDescriptor parameter should only be invoked once.
ExportDescriptor actualDescriptor = promise.GetDescriptor();
Assert.Same(descriptor, actualDescriptor);
Assert.Equal(1, calledDependencies);
Assert.Equal(1, calledGetDescriptor);
Assert.Same(actualDescriptor, promise.GetDescriptor());
Assert.Equal(1, calledDependencies);
Assert.Equal(1, calledGetDescriptor);
}
[Fact]
public void Dependencies_GetWhenNull_ThrowsNullReferenceException()
{
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, null, dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
Assert.Throws<NullReferenceException>(() => promise.Dependencies);
}
[Fact]
public void Dependencies_GetWhenReturnsNull_ThrowsArgumentNullException()
{
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => null, depdendencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
AssertExtensions.Throws<ArgumentNullException>("source", () => promise.Dependencies);
}
[Fact]
public void GetDescriptor_GetWhenNull_ThrowsNullReferenceException()
{
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, null, dependencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
Assert.Throws<NullReferenceException>(() => promise.GetDescriptor());
}
[Fact]
public void GetDescriptor_GetWhenReturnsNull_ThrowsArgumentNullException()
{
var descriptor = ExportDescriptor.Create(Activator, new Dictionary<string, object>());
var promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), depdendencies =>
{
return null;
});
AssertExtensions.Throws<ArgumentNullException>("descriptor", () => promise.GetDescriptor());
}
[Fact]
public void GetDescriptor_CycleMetadataNotCompleted_MethodsThrowNotImplementedException()
{
ExportDescriptorPromise promise = null;
promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), depdendencies =>
{
ExportDescriptor cycleDescriptor = promise.GetDescriptor();
IDictionary<string, object> metadata = cycleDescriptor.Metadata;
Assert.Throws<NotImplementedException>(() => metadata.Add("key", "value"));
Assert.Throws<NotImplementedException>(() => metadata.Clear());
Assert.Throws<NotImplementedException>(() => metadata.Add(default(KeyValuePair<string, object>)));
Assert.Throws<NotImplementedException>(() => metadata.CopyTo(null, 0));
Assert.Throws<NotImplementedException>(() => metadata.Contains(default(KeyValuePair<string, object>)));
Assert.Throws<NotImplementedException>(() => metadata.ContainsKey("key"));
Assert.Throws<NotImplementedException>(() => metadata.Count);
Assert.Throws<NotImplementedException>(() => metadata.IsReadOnly);
Assert.Throws<NotImplementedException>(() => metadata.GetEnumerator());
Assert.Throws<NotImplementedException>(() => ((IEnumerable)metadata).GetEnumerator());
Assert.Throws<NotImplementedException>(() => metadata.Keys);
Assert.Throws<NotImplementedException>(() => metadata.Remove("key"));
Assert.Throws<NotImplementedException>(() => metadata.Remove(default(KeyValuePair<string, object>)));
Assert.Throws<NotImplementedException>(() => metadata.TryGetValue("key", out object _));
Assert.Throws<NotImplementedException>(() => metadata.Values);
Assert.Throws<NotImplementedException>(() => metadata["key"]);
Assert.Throws<NotImplementedException>(() => metadata["key"] = "value");
return ExportDescriptor.Create(Activator, new Dictionary<string, object> { { "key", "value" } });
});
// Invoke the GetDescriptor method to start the test.
Assert.NotNull(promise.GetDescriptor());
}
[Fact]
public void GetDescriptor_CycleMetadataCompleted_MethodsReturnExpected()
{
ExportDescriptorPromise promise = null;
IDictionary<string, object> metadata = null;
promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), depdendencies =>
{
ExportDescriptor cycleDescriptor = promise.GetDescriptor();
metadata = cycleDescriptor.Metadata;
return ExportDescriptor.Create(Activator, new Dictionary<string, object> { { "key", "value" } });
});
// Invoke the GetDescriptor method to start the test.
Assert.NotNull(promise.GetDescriptor());
// Make sure all the IDictionary methods complete successfully.
Assert.Equal("value", metadata["key"]);
Assert.True(metadata.Contains(new KeyValuePair<string, object>("key", "value")));
Assert.True(metadata.ContainsKey("key"));
Assert.False(metadata.IsReadOnly);
metadata["key"] = "value2";
Assert.True(metadata.TryGetValue("key", out object value));
Assert.Equal("value2", value);
metadata.Add("key2", "value");
Assert.Equal(2, metadata.Count);
metadata.Remove("key2");
Assert.Equal(1, metadata.Count);
metadata.Add(new KeyValuePair<string, object>("key2", "value"));
Assert.Equal(2, metadata.Count);
metadata.Remove(new KeyValuePair<string, object>("key2", "value"));
Assert.Equal(1, metadata.Count);
Assert.Equal(1, metadata.Keys.Count);
Assert.Equal(1, metadata.Values.Count);
var array = new KeyValuePair<string, object>[2];
metadata.CopyTo(array, 1);
Assert.Equal(new KeyValuePair<string, object>[] { default(KeyValuePair<string, object>), new KeyValuePair<string, object>("key", "value2") }, array);
IEnumerator enumerator = metadata.GetEnumerator();
Assert.True(enumerator.MoveNext());
Assert.Equal(new KeyValuePair<string, object>("key", "value2"), enumerator.Current);
enumerator = ((IEnumerable)metadata).GetEnumerator();
Assert.True(enumerator.MoveNext());
Assert.Equal(new KeyValuePair<string, object>("key", "value2"), enumerator.Current);
metadata.Clear();
Assert.Equal(0, metadata.Count);
}
[Fact]
public void GetDescriptor_CycleActivatorNotCompleted_ThrowsNotImplementedException()
{
ExportDescriptorPromise promise = null;
promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), depdendencies =>
{
ExportDescriptor cycleDescriptor = promise.GetDescriptor();
CompositeActivator activator = cycleDescriptor.Activator;
Assert.Throws<NotImplementedException>(() => activator(null, null));
return ExportDescriptor.Create(Activator, new Dictionary<string, object> { { "key", "value" } });
});
// Invoke the GetDescriptor method to start the test.
Assert.NotNull(promise.GetDescriptor());
}
[Fact]
public void GetDescriptor_CycleActivatorCompleted_Success()
{
ExportDescriptorPromise promise = null;
CompositeActivator activator = null;
promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), depdendencies =>
{
ExportDescriptor cycleDescriptor = promise.GetDescriptor();
activator = cycleDescriptor.Activator;
return ExportDescriptor.Create(Activator, new Dictionary<string, object> { { "key", "value" } });
});
ExportDescriptor descriptor = promise.GetDescriptor();
Assert.Equal("hi", descriptor.Activator(null, null));
Assert.Equal("hi", activator(null, null));
}
[Fact]
public void GetDescriptor_CycleMetadataBroken_HasExpectedProperties()
{
ExportDescriptorPromise promise = null;
ExportDescriptor cycleDescriptor = null;
promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), depdendencies =>
{
cycleDescriptor = promise.GetDescriptor();
return ExportDescriptor.Create(Activator, new Dictionary<string, object> { { "key", "value" } });
});
ExportDescriptor descriptor = promise.GetDescriptor();
Assert.Same(descriptor.Activator, cycleDescriptor.Activator);
Assert.Same(descriptor.Metadata, cycleDescriptor.Metadata);
}
[Fact]
public void ToString_Invoke_ReturnsExpected()
{
var promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty<CompositionDependency>(), depdendencies =>
{
return ExportDescriptor.Create(Activator, new Dictionary<string, object>());
});
Assert.Equal("Int32 supplied by Origin", promise.ToString());
}
private static object Activator(LifetimeContext context, CompositionOperation operation) => "hi";
}
}

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