Merge remote-tracking branch 'origin/release/2.2' into feature/master-routing-api-review-p1

This commit is contained in:
James Newton-King 2018-08-02 13:54:13 +12:00
commit 2f7ec2ada2
No known key found for this signature in database
GPG Key ID: 0A66B2F456BF5526
140 changed files with 502 additions and 390 deletions

View File

@ -29,11 +29,11 @@ namespace Benchmarks
.UseKestrel();
var scenario = config["scenarios"]?.ToLower();
if (scenario == "plaintextdispatcher" || scenario == "plaintextglobalrouting")
if (scenario == "plaintextdispatcher" || scenario == "plaintextendpointrouting")
{
webHostBuilder.UseStartup<StartupUsingGlobalRouting>();
webHostBuilder.UseStartup<StartupUsingEndpointRouting>();
// for testing
webHostBuilder.UseSetting("Startup", nameof(StartupUsingGlobalRouting));
webHostBuilder.UseSetting("Startup", nameof(StartupUsingEndpointRouting));
}
else if (scenario == "plaintextrouting" || scenario == "plaintextrouter")
{
@ -44,7 +44,7 @@ namespace Benchmarks
else
{
throw new InvalidOperationException(
$"Invalid scenario '{scenario}'. Allowed scenarios are PlaintextGlobalRouting and PlaintextRouter");
$"Invalid scenario '{scenario}'. Allowed scenarios are PlaintextEndpointRouting and PlaintextRouter");
}
return webHostBuilder;

View File

@ -2,15 +2,15 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Internal;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection;
namespace Benchmarks
{
public class StartupUsingGlobalRouting
public class StartupUsingEndpointRouting
{
private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!");
@ -41,9 +41,9 @@ namespace Benchmarks
});
}
public void Configure(IApplicationBuilder app)
public void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app)
{
app.UseGlobalRouting();
app.UseEndpointRouting();
app.UseEndpoint();
}

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// An optimized jump table that trades a small amount of additional memory for
// hash-table like performance.

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class CustomHashTableJumpTable : JumpTable
{

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class DictionaryLookupJumpTable : JumpTable
{

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public abstract class FastPathTokenizerBenchmarkBase
{

View File

@ -4,7 +4,7 @@
using System;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public class FastPathTokenizerEmptyBenchmark : FastPathTokenizerBenchmarkBase
{

View File

@ -4,7 +4,7 @@
using System;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public class FastPathTokenizerLargeBenchmark : FastPathTokenizerBenchmarkBase
{

View File

@ -4,7 +4,7 @@
using System;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public class FastPathTokenizerPlaintextBenchmark : FastPathTokenizerBenchmarkBase
{

View File

@ -4,7 +4,7 @@
using System;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public class FastPathTokenizerSmallBenchmark : FastPathTokenizerBenchmarkBase
{

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public class JumpTableMultipleEntryBenchmark
{

View File

@ -4,7 +4,7 @@
using System;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public class JumpTableSingleEntryBenchmark
{

View File

@ -3,7 +3,7 @@
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public class JumpTableZeroEntryBenchmark
{

View File

@ -5,7 +5,7 @@ using System;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public class MatcheFindCandidateSetSingleEntryBenchmark : MatcherBenchmarkBase
{

View File

@ -4,7 +4,7 @@
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// Generated from https://github.com/Azure/azure-rest-api-specs
public partial class MatcherAzureBenchmark : MatcherBenchmarkBase

View File

@ -4,7 +4,7 @@
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// This code was generated by the Swaggatherer
public partial class MatcherAzureBenchmark : MatcherBenchmarkBase

View File

@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Routing.Metadata;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public abstract class MatcherBenchmarkBase
{

View File

@ -4,7 +4,7 @@
using System;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// Generated from https://github.com/Azure/azure-rest-api-specs
public partial class MatcherFindCandidateSetAzureBenchmark : MatcherBenchmarkBase

View File

@ -4,7 +4,7 @@
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// This code was generated by the Swaggatherer
public partial class MatcherFindCandidateSetAzureBenchmark : MatcherBenchmarkBase

View File

@ -5,7 +5,7 @@ using System;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// Generated from https://github.com/APIs-guru/openapi-directory
// Use https://editor2.swagger.io/ to convert from yaml to json-

View File

@ -4,7 +4,7 @@
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// This code was generated by the Swaggatherer
public partial class MatcherFindCandidateSetGithubBenchmark : MatcherBenchmarkBase

View File

@ -5,7 +5,7 @@ using System;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public class MatcherFindCandidateSetSmallEntryCountBenchmark : MatcherBenchmarkBase
{

View File

@ -4,7 +4,7 @@
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// Generated from https://github.com/APIs-guru/openapi-directory
// Use https://editor2.swagger.io/ to convert from yaml to json-

View File

@ -4,7 +4,7 @@
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// This code was generated by the Swaggatherer
public partial class MatcherGithubBenchmark : MatcherBenchmarkBase

View File

@ -5,7 +5,7 @@ using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// Just like TechEmpower Plaintext
public partial class MatcherSingleEntryBenchmark : MatcherBenchmarkBase

View File

@ -5,7 +5,7 @@ using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// A test-only matcher implementation - used as a baseline for simpler
// perf tests. The idea with this matcher is that we can cheat on the requirements

View File

@ -4,7 +4,7 @@
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class TrivialMatcherBuilder : MatcherBuilder
{

View File

@ -18,23 +18,23 @@
for perf comparisons.
-->
<ItemGroup>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\BarebonesMatcher.cs">
<Link>Matchers\BarebonesMatcher.cs</Link>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matching\BarebonesMatcher.cs">
<Link>Matching\BarebonesMatcher.cs</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\BarebonesMatcherBuilder.cs">
<Link>Matchers\BarebonesMatcherBuilder.cs</Link>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matching\BarebonesMatcherBuilder.cs">
<Link>Matching\BarebonesMatcherBuilder.cs</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\RouteMatcher.cs">
<Link>Matchers\RouteMatcher.cs</Link>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matching\RouteMatcher.cs">
<Link>Matching\RouteMatcher.cs</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\RouteMatcherBuilder.cs">
<Link>Matchers\RouteMatcherBuilder.cs</Link>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matching\RouteMatcherBuilder.cs">
<Link>Matching\RouteMatcherBuilder.cs</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\TreeRouterMatcher.cs">
<Link>Matchers\TreeRouterMatcher.cs</Link>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matching\TreeRouterMatcher.cs">
<Link>Matching\TreeRouterMatcher.cs</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\TreeRouterMatcherBuilder.cs">
<Link>Matchers\TreeRouterMatcherBuilder.cs</Link>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matching\TreeRouterMatcherBuilder.cs">
<Link>Matching\TreeRouterMatcherBuilder.cs</Link>
</Compile>
</ItemGroup>

View File

@ -39,7 +39,7 @@ namespace Swaggatherer
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{{
// This code was generated by the Swaggatherer
public partial class GeneratedBenchmark : MatcherBenchmarkBase

View File

@ -3,7 +3,7 @@
using System;
using System.Globalization;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.Extensions.Logging;
namespace RoutingSample.Web

View File

@ -9,8 +9,8 @@ namespace RoutingSample.Web
{
public class Program
{
public static readonly string GlobalRoutingScenario = "globalrouting";
public static readonly string RouterScenario = "router";
public const string EndpointRoutingScenario = "endpointrouting";
public const string RouterScenario = "router";
public static void Main(string[] args)
{
@ -25,7 +25,7 @@ namespace RoutingSample.Web
if (args.Length == 0)
{
Console.WriteLine("Choose a sample to run:");
Console.WriteLine($"1. {GlobalRoutingScenario}");
Console.WriteLine($"1. {EndpointRoutingScenario}");
Console.WriteLine($"2. {RouterScenario}");
Console.WriteLine();
@ -40,18 +40,18 @@ namespace RoutingSample.Web
switch (scenario)
{
case "1":
case "globalrouting":
startupType = typeof(UseGlobalRoutingStartup);
case EndpointRoutingScenario:
startupType = typeof(UseEndpointRoutingStartup);
break;
case "2":
case "router":
case RouterScenario:
startupType = typeof(UseRouterStartup);
break;
default:
Console.WriteLine($"unknown scenario {scenario}");
Console.WriteLine($"usage: dotnet run -- ({GlobalRoutingScenario}|{RouterScenario})");
Console.WriteLine($"usage: dotnet run -- ({EndpointRoutingScenario}|{RouterScenario})");
throw new InvalidOperationException();
}

View File

@ -3,18 +3,18 @@
using System;
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Internal;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection;
namespace RoutingSample.Web
{
public class UseGlobalRoutingStartup
public class UseEndpointRoutingStartup
{
private static readonly byte[] _homePayload = Encoding.UTF8.GetBytes("Global Routing sample endpoints:" + Environment.NewLine + "/plaintext");
private static readonly byte[] _homePayload = Encoding.UTF8.GetBytes("Endpoint Routing sample endpoints:" + Environment.NewLine + "/plaintext");
private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!");
public void ConfigureServices(IServiceCollection services)
@ -86,9 +86,9 @@ namespace RoutingSample.Web
});
}
public void Configure(IApplicationBuilder app)
public void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app)
{
app.UseGlobalRouting();
app.UseEndpointRouting();
// Imagine some more stuff here...

View File

@ -8,7 +8,7 @@ using System.Linq;
namespace Microsoft.AspNetCore.Routing
{
public class EndpointMetadataCollection : IReadOnlyList<object>
public sealed class EndpointMetadataCollection : IReadOnlyList<object>
{
public static readonly EndpointMetadataCollection Empty = new EndpointMetadataCollection(Array.Empty<object>());
@ -24,6 +24,11 @@ namespace Microsoft.AspNetCore.Routing
_items = items.ToArray();
}
public EndpointMetadataCollection(params object[] items)
: this((IEnumerable<object>)items)
{
}
public object this[int index] => _items[index];
public int Count => _items.Length;

View File

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Builder
{
// TODO: Remove once MVC is updated
public static class EndpointRoutingApplicationBuilderExtensions
{
public static IApplicationBuilder UseGlobalRouting(this IApplicationBuilder builder)
{
return Internal.EndpointRoutingApplicationBuilderExtensions.UseEndpointRouting(builder);
}
public static IApplicationBuilder UseEndpoint(this IApplicationBuilder builder)
{
return Internal.EndpointRoutingApplicationBuilderExtensions.UseEndpoint(builder);
}
}
}

View File

@ -7,14 +7,14 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Metadata;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Routing
{
[DebuggerDisplay("{DebuggerDisplayString,nq}")]
public class CompositeEndpointDataSource : EndpointDataSource
public sealed class CompositeEndpointDataSource : EndpointDataSource
{
private readonly EndpointDataSource[] _dataSources;
private readonly object _lock;

View File

@ -8,9 +8,14 @@ using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Routing
{
public class DefaultEndpointDataSource : EndpointDataSource
public sealed class DefaultEndpointDataSource : EndpointDataSource
{
private readonly List<Endpoint> _endpoints;
private readonly List<Endpoint> _endpoints;
public DefaultEndpointDataSource(params Endpoint[] endpoints)
: this((IEnumerable<Endpoint>) endpoints)
{
}
public DefaultEndpointDataSource(IEnumerable<Endpoint> endpoints)
{

View File

@ -6,7 +6,7 @@ using System.Linq;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Template;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ObjectPool;

View File

@ -3,10 +3,8 @@
using System;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Constraints;
using Microsoft.AspNetCore.Routing.EndpointFinders;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Tree;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
@ -70,7 +68,7 @@ namespace Microsoft.Extensions.DependencyInjection
// Link generation related services
services.TryAddSingleton<IEndpointFinder<string>, NameBasedEndpointFinder>();
services.TryAddSingleton<IEndpointFinder<RouteValuesBasedEndpointFinderContext>, RouteValuesBasedEndpointFinder>();
services.TryAddSingleton<IEndpointFinder<RouteValuesAddress>, RouteValuesBasedEndpointFinder>();
services.TryAddSingleton<LinkGenerator, DefaultLinkGenerator>();
//

View File

@ -34,8 +34,8 @@ namespace Microsoft.AspNetCore.Routing
var feature = httpContext.Features.Get<IEndpointFeature>();
if (feature == null)
{
var message = $"Unable to execute an endpoint because the {nameof(GlobalRoutingMiddleware)} was not run for this request. " +
$"Ensure {nameof(GlobalRoutingMiddleware)} is added to the request execution pipeline before {nameof(EndpointMiddleware)} in application startup code.";
var message = $"Unable to execute an endpoint because the {nameof(EndpointRoutingMiddleware)} was not run for this request. " +
$"Ensure {nameof(EndpointRoutingMiddleware)} is added to the request execution pipeline before {nameof(EndpointMiddleware)} in application startup code.";
throw new InvalidOperationException(message);
}

View File

@ -5,13 +5,13 @@ using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Routing
{
internal sealed class GlobalRoutingMiddleware
internal sealed class EndpointRoutingMiddleware
{
private readonly MatcherFactory _matcherFactory;
private readonly ILogger _logger;
@ -20,10 +20,10 @@ namespace Microsoft.AspNetCore.Routing
private Task<Matcher> _initializationTask;
public GlobalRoutingMiddleware(
public EndpointRoutingMiddleware(
MatcherFactory matcherFactory,
CompositeEndpointDataSource endpointDataSource,
ILogger<GlobalRoutingMiddleware> logger,
ILogger<EndpointRoutingMiddleware> logger,
RequestDelegate next)
{
if (matcherFactory == null)

View File

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing
{
public interface INameMetadata

View File

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing
{
public interface IRouteNameMetadata

View File

@ -2,33 +2,38 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Builder
namespace Microsoft.AspNetCore.Internal
{
public static class GlobalRoutingApplicationBuilderExtensions
public static class EndpointRoutingApplicationBuilderExtensions
{
// TODO: Remove once MVC is updated
private const string GlobalRoutingRegisteredKey = "__GlobalRoutingMiddlewareRegistered";
public static IApplicationBuilder UseGlobalRouting(this IApplicationBuilder builder)
private const string EndpointRoutingRegisteredKey = "__EndpointRoutingMiddlewareRegistered";
public static IApplicationBuilder UseEndpointRouting(this IApplicationBuilder builder)
{
VerifyRoutingIsRegistered(builder);
builder.Properties[EndpointRoutingRegisteredKey] = true;
builder.Properties[GlobalRoutingRegisteredKey] = true;
return builder.UseMiddleware<GlobalRoutingMiddleware>();
return builder.UseMiddleware<EndpointRoutingMiddleware>();
}
public static IApplicationBuilder UseEndpoint(this IApplicationBuilder builder)
{
VerifyRoutingIsRegistered(builder);
if (!builder.Properties.TryGetValue(GlobalRoutingRegisteredKey, out _))
if (!builder.Properties.TryGetValue(EndpointRoutingRegisteredKey, out _))
{
var message = $"{nameof(GlobalRoutingMiddleware)} must be added to the request execution pipeline before {nameof(EndpointMiddleware)}. " +
$"Please add {nameof(GlobalRoutingMiddleware)} by calling '{nameof(IApplicationBuilder)}.{nameof(UseGlobalRouting)}' inside the call to 'Configure(...)' in the application startup code.";
var message = $"{nameof(EndpointRoutingMiddleware)} must be added to the request execution pipeline before {nameof(EndpointMiddleware)}. " +
$"Please add {nameof(EndpointRoutingMiddleware)} by calling '{nameof(IApplicationBuilder)}.{nameof(UseEndpointRouting)}' inside the call to 'Configure(...)' in the application startup code.";
throw new InvalidOperationException(message);
}
@ -38,7 +43,7 @@ namespace Microsoft.AspNetCore.Builder
private static void VerifyRoutingIsRegistered(IApplicationBuilder app)
{
// Verify if AddRouting was done before calling UseGlobalRouting/UseEndpoint
// Verify if AddRouting was done before calling UseEndpointRouting/UseEndpoint
// We use the RoutingMarkerService to make sure if all the services were added.
if (app.ApplicationServices.GetService(typeof(RoutingMarkerService)) == null)
{

View File

@ -4,7 +4,7 @@
using System;
using System.Runtime.Serialization;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
/// <summary>
/// An exception which indicates multiple matches in endpoint selection.

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Routing.Patterns;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal readonly struct Candidate
{

View File

@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public sealed class CandidateSet
{

View File

@ -1,17 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public struct CandidateState
{
// Provided for testability
public CandidateState(MatcherEndpoint endpoint)
: this(endpoint, score: 0)
{
}
public CandidateState(MatcherEndpoint endpoint, int score)
internal CandidateState(MatcherEndpoint endpoint, int score)
{
Endpoint = endpoint;
Score = score;

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class DataSourceDependentMatcher : Matcher
{

View File

@ -7,7 +7,7 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class DefaultEndpointSelector : EndpointSelector
{

View File

@ -5,7 +5,7 @@ using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class DefaultMatchProcessorFactory : MatchProcessorFactory
{

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Patterns;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal sealed class DfaMatcher : Matcher
{

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Routing.Patterns;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class DfaMatcherBuilder : MatcherBuilder
{

View File

@ -4,7 +4,7 @@
using System;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class DfaMatcherFactory : MatcherFactory
{

View File

@ -7,7 +7,7 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// Intermediate data structure used to build the DFA. Not used at runtime.
[DebuggerDisplay("{DebuggerToString(),nq}")]

View File

@ -3,7 +3,7 @@
using System.Diagnostics;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
[DebuggerDisplay("{DebuggerToString(),nq}")]
internal readonly struct DfaState

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class DictionaryJumpTable : JumpTable
{

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public abstract class EndpointMetadataComparer<TMetadata> : IComparer<Endpoint> where TMetadata : class
{

View File

@ -4,7 +4,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public abstract class EndpointSelector
{

View File

@ -3,7 +3,7 @@
using System;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// Low level implementation of our path tokenization algorithm. Alternative
// to PathTokenizer.

View File

@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public sealed class HttpMethodMatcherPolicy : MatcherPolicy, IEndpointComparerPolicy, INodeBuilderPolicy
{

View File

@ -3,7 +3,7 @@
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public interface IEndpointComparerPolicy
{

View File

@ -3,7 +3,7 @@
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public interface IEndpointSelectorPolicy
{

View File

@ -3,7 +3,7 @@
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public interface INodeBuilderPolicy
{

View File

@ -3,7 +3,7 @@
using System.Diagnostics;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
[DebuggerDisplay("{DebuggerToString(),nq}")]
internal abstract class JumpTable

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class JumpTableBuilder
{

View File

@ -5,7 +5,7 @@ using System;
using System.Linq;
using System.Text;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class LinearSearchJumpTable : JumpTable
{

View File

@ -3,7 +3,7 @@
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public abstract class MatchProcessor
{

View File

@ -3,7 +3,7 @@
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public abstract class MatchProcessorBase : MatchProcessor
{

View File

@ -5,7 +5,7 @@ using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Routing.Patterns;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal abstract class MatchProcessorFactory
{

View File

@ -4,11 +4,11 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
/// <summary>
/// An interface for components that can select an <see cref="Endpoint"/> given the current request, as part
/// of the execution of <see cref="GlobalRoutingMiddleware"/>.
/// of the execution of <see cref="EndpointRoutingMiddleware"/>.
/// </summary>
internal abstract class Matcher
{

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal abstract class MatcherBuilder
{

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Patterns;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public sealed class MatcherEndpoint : Endpoint
{

View File

@ -4,7 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
// Use to sort and group MatcherEndpoints.
//

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal abstract class MatcherFactory
{

View File

@ -3,7 +3,7 @@
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class OptionalMatchProcessor : MatchProcessor
{

View File

@ -3,7 +3,7 @@
using System;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal readonly struct PathSegment : IEquatable<PathSegment>
{

View File

@ -3,7 +3,7 @@
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public abstract class PolicyJumpTable
{

View File

@ -3,7 +3,7 @@
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class PolicyJumpTableBuilder
{

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public readonly struct PolicyJumpTableEdge
{

View File

@ -3,7 +3,7 @@
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
public readonly struct PolicyNodeEdge
{

View File

@ -4,7 +4,7 @@
using System;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class RouteConstraintMatchProcessor : MatchProcessor
{

View File

@ -3,7 +3,7 @@
using System;
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class SingleEntryJumpTable : JumpTable
{

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing.Matchers
namespace Microsoft.AspNetCore.Routing.Matching
{
internal class ZeroEntryJumpTable : JumpTable
{

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Routing

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
namespace Microsoft.AspNetCore.Routing.Patterns
{
@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Routing.Patterns
public IRouteConstraint Constraint { get; }
/// <summary>
/// Gets a pre-existing <see cref="Matchers.MatchProcessor"/> that was used to construct this reference.
/// Gets a pre-existing <see cref="Matching.MatchProcessor"/> that was used to construct this reference.
/// </summary>
public MatchProcessor MatchProcessor { get; }

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Routing.Constraints;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
namespace Microsoft.AspNetCore.Routing.Patterns
{

View File

@ -11,7 +11,7 @@ using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Routing
{
public class RoutePatternMatcher
internal class RoutePatternMatcher
{
private const string SeparatorString = "/";
private const char SeparatorChar = '/';

View File

@ -8,7 +8,7 @@ using System.Text;
namespace Microsoft.AspNetCore.Routing.Patterns
{
[DebuggerDisplay("{DebuggerToString()}")]
public class RoutePatternParameterPart : RoutePatternPart
public sealed class RoutePatternParameterPart : RoutePatternPart
{
internal RoutePatternParameterPart(
string parameterName,

View File

@ -1,9 +1,9 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing.EndpointFinders
namespace Microsoft.AspNetCore.Routing
{
public class RouteValuesBasedEndpointFinderContext
public class RouteValuesAddress
{
public string RouteName { get; set; }

View File

@ -4,16 +4,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Routing.EndpointFinders;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Template;
using Microsoft.AspNetCore.Routing.Tree;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Routing
{
internal class RouteValuesBasedEndpointFinder : IEndpointFinder<RouteValuesBasedEndpointFinderContext>
internal class RouteValuesBasedEndpointFinder : IEndpointFinder<RouteValuesAddress>
{
private readonly CompositeEndpointDataSource _endpointDataSource;
private readonly ObjectPool<UriBuildingContext> _objectPool;
@ -36,16 +35,16 @@ namespace Microsoft.AspNetCore.Routing
HandleChange);
}
public IEnumerable<Endpoint> FindEndpoints(RouteValuesBasedEndpointFinderContext context)
public IEnumerable<Endpoint> FindEndpoints(RouteValuesAddress address)
{
IEnumerable<OutboundMatchResult> matchResults = null;
if (string.IsNullOrEmpty(context.RouteName))
if (string.IsNullOrEmpty(address.RouteName))
{
matchResults = _allMatchesLinkGenerationTree.GetMatches(
context.ExplicitValues,
context.AmbientValues);
address.ExplicitValues,
address.AmbientValues);
}
else if (_namedMatchResults.TryGetValue(context.RouteName, out var namedMatchResults))
else if (_namedMatchResults.TryGetValue(address.RouteName, out var namedMatchResults))
{
matchResults = namedMatchResults;
}

View File

@ -52,8 +52,5 @@ namespace Microsoft.AspNetCore.Routing.Tree
/// Gets or sets the <see cref="RouteTemplate"/>.
/// </summary>
public RouteTemplate RouteTemplate { get; set; }
// REVIEW: temporary change to enable reusing the tree router
public object Tag { get; set; }
}
}

View File

@ -0,0 +1,48 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;
namespace Microsoft.AspNetCore.Routing
{
public class EndpointMetadataCollectionTests
{
[Fact]
public void Constructor_Enumeration_ContainsValues()
{
// Arrange & Act
var metadata = new EndpointMetadataCollection(new List<object>
{
1,
2,
3,
});
// Assert
Assert.Equal(3, metadata.Count);
Assert.Collection(metadata,
value => Assert.Equal(1, value),
value => Assert.Equal(2, value),
value => Assert.Equal(3, value));
}
[Fact]
public void Constructor_ParamsArray_ContainsValues()
{
// Arrange & Act
var metadata = new EndpointMetadataCollection(1, 2, 3);
// Assert
Assert.Equal(3, metadata.Count);
Assert.Collection(metadata,
value => Assert.Equal(1, value),
value => Assert.Equal(2, value),
value => Assert.Equal(3, value));
}
}
}

View File

@ -11,20 +11,20 @@ using Xunit;
namespace Microsoft.AspNetCore.Routing.FunctionalTests
{
public class GlobalRoutingBenchmarkTest : IDisposable
public class EndpointRoutingBenchmarkTest : IDisposable
{
private readonly HttpClient _client;
private readonly TestServer _testServer;
public GlobalRoutingBenchmarkTest()
public EndpointRoutingBenchmarkTest()
{
// This switch and value are set by benchmark server when running the app for profiling.
var args = new[] { "--scenarios", "PlaintextGlobalRouting" };
var args = new[] { "--scenarios", "PlaintextEndpointRouting" };
var webHostBuilder = Benchmarks.Program.GetWebHostBuilder(args);
// Make sure we are using the right startup
var startupName = webHostBuilder.GetSetting("Startup");
Assert.Equal(nameof(Benchmarks.StartupUsingGlobalRouting), startupName);
Assert.Equal(nameof(Benchmarks.StartupUsingEndpointRouting), startupName);
_testServer = new TestServer(webHostBuilder);
_client = _testServer.CreateClient();

View File

@ -11,14 +11,14 @@ using Xunit;
namespace Microsoft.AspNetCore.Routing.FunctionalTests
{
public class GlobalRoutingSampleTest : IDisposable
public class EndpointRoutingSampleTest : IDisposable
{
private readonly HttpClient _client;
private readonly TestServer _testServer;
public GlobalRoutingSampleTest()
public EndpointRoutingSampleTest()
{
var webHostBuilder = Program.GetWebHostBuilder(new[] { Program.GlobalRoutingScenario, });
var webHostBuilder = Program.GetWebHostBuilder(new[] { Program.EndpointRoutingScenario, });
_testServer = new TestServer(webHostBuilder);
_client = _testServer.CreateClient();
_client.BaseAddress = new Uri("http://localhost");
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Routing.FunctionalTests
{
// Arrange
var expectedContentType = "text/plain";
var expectedContent = "Global Routing sample endpoints:" + Environment.NewLine + "/plaintext";
var expectedContent = "Endpoint Routing sample endpoints:" + Environment.NewLine + "/plaintext";
// Act
var response = await _client.GetAsync("/");

View File

@ -5,6 +5,7 @@ using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Internal;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Moq;
@ -12,16 +13,16 @@ using Xunit;
namespace Microsoft.AspNetCore.Builder
{
public class GlobalRoutingBuilderExtensionsTest
public class EndpointRoutingBuilderExtensionsTest
{
[Fact]
public void UseGlobalRouting_ServicesNotRegistered_Throws()
public void UseEndpointRouting_ServicesNotRegistered_Throws()
{
// Arrange
var app = new ApplicationBuilder(Mock.Of<IServiceProvider>());
// Act
var ex = Assert.Throws<InvalidOperationException>(() => app.UseGlobalRouting());
var ex = Assert.Throws<InvalidOperationException>(() => app.UseEndpointRouting());
// Assert
Assert.Equal(
@ -49,14 +50,14 @@ namespace Microsoft.AspNetCore.Builder
}
[Fact]
public async Task UseGlobalRouting_ServicesRegistered_SetsFeature()
public async Task UseEndpointRouting_ServicesRegistered_SetsFeature()
{
// Arrange
var services = CreateServices();
var app = new ApplicationBuilder(services);
app.UseGlobalRouting();
app.UseEndpointRouting();
var appFunc = app.Build();
var httpContext = new DefaultHttpContext();
@ -81,21 +82,21 @@ namespace Microsoft.AspNetCore.Builder
// Assert
Assert.Equal(
"GlobalRoutingMiddleware must be added to the request execution pipeline before EndpointMiddleware. " +
"Please add GlobalRoutingMiddleware by calling 'IApplicationBuilder.UseGlobalRouting' " +
"EndpointRoutingMiddleware must be added to the request execution pipeline before EndpointMiddleware. " +
"Please add EndpointRoutingMiddleware by calling 'IApplicationBuilder.UseEndpointRouting' " +
"inside the call to 'Configure(...)' in the application startup code.",
ex.Message);
}
[Fact]
public async Task UseEndpoint_ServicesRegisteredAndGlobalRoutingRegistered_SetsFeature()
public async Task UseEndpoint_ServicesRegisteredAndEndpointRoutingRegistered_SetsFeature()
{
// Arrange
var services = CreateServices();
var app = new ApplicationBuilder(services);
app.UseGlobalRouting();
app.UseEndpointRouting();
app.UseEndpoint();
var appFunc = app.Build();

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.AspNetCore.Routing.TestObjects;
using Microsoft.Extensions.Primitives;

View File

@ -0,0 +1,45 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Routing.TestObjects;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;
namespace Microsoft.AspNetCore.Routing
{
public class DefaultEndpointDataSourceTests
{
[Fact]
public void Constructor_Params_EndpointsInitialized()
{
// Arrange & Act
var dataSource = new DefaultEndpointDataSource(
new TestEndpoint(EndpointMetadataCollection.Empty, "1"),
new TestEndpoint(EndpointMetadataCollection.Empty, "2")
);
// Assert
Assert.Collection(dataSource.Endpoints,
endpoint => Assert.Equal("1", endpoint.DisplayName),
endpoint => Assert.Equal("2", endpoint.DisplayName));
}
[Fact]
public void Constructor_Enumerable_EndpointsInitialized()
{
// Arrange & Act
var dataSource = new DefaultEndpointDataSource(new List<Endpoint>
{
new TestEndpoint(EndpointMetadataCollection.Empty, "1"),
new TestEndpoint(EndpointMetadataCollection.Empty, "2")
});
// Assert
Assert.Collection(dataSource.Endpoints,
endpoint => Assert.Equal("1", endpoint.DisplayName),
endpoint => Assert.Equal("2", endpoint.DisplayName));
}
}
}

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