From a6dce7b33c0217392ec374a3b9cd7b759a434654 Mon Sep 17 00:00:00 2001
From: Artak <34246760+mkArtakMSFT@users.noreply.github.com>
Date: Thu, 23 May 2019 10:26:07 -0700
Subject: [PATCH 01/95] Updating minimum required VS version to 16.2 (#10458)
* Updating minimum required VS version to 16.2
---
.../Blazor/BlazorExtension/src/source.extension.vsixmanifest | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Components/Blazor/BlazorExtension/src/source.extension.vsixmanifest b/src/Components/Blazor/BlazorExtension/src/source.extension.vsixmanifest
index 85c5c76f40..64d36b9b99 100644
--- a/src/Components/Blazor/BlazorExtension/src/source.extension.vsixmanifest
+++ b/src/Components/Blazor/BlazorExtension/src/source.extension.vsixmanifest
@@ -12,7 +12,7 @@
Content\WebConfiguration.png
-
+
From 2948c81aea2e5a947dc80fe4a62fa7150a9c6f94 Mon Sep 17 00:00:00 2001
From: Ryan Nowak
Date: Thu, 23 May 2019 10:39:53 -0700
Subject: [PATCH 02/95] Fix RendererSyncContext.Post() (#10451)
* Fix RendererSyncContext.Post()
Fixes: #9683 - SignalR connection breaks on large DOM
The root cause here is a misbehaving sync context. It's not legal for a
Post() implementation to run a callback synchronously. We want that
behavior for most of the functionality Blazor calls directly, but Post()
should always go async or else various threading primitives are broken.
* Fix incorrect tests
These tests have the assumption that setting the result of a TCS will
execution continuations synchronously. This was a bug in our
SyncContext, and these tests needed updating to be more resiliant.
* Remove a delegate allocation
---
.../RendererSynchronizationContext.cs | 94 ++++++++++++-------
.../Components/test/Auth/AuthorizeViewTest.cs | 28 +++++-
.../Components/test/ComponentBaseTest.cs | 19 +++-
.../Components/test/RendererTest.cs | 41 +++++++-
... => RendererSynchronizationContextTest.cs} | 36 +++++--
.../test/Circuits/RemoteRendererTest.cs | 21 ++++-
src/Components/Shared/test/TestRenderer.cs | 7 ++
7 files changed, 196 insertions(+), 50 deletions(-)
rename src/Components/Components/test/Rendering/{RendererSynchronizationContextTests.cs => RendererSynchronizationContextTest.cs} (95%)
diff --git a/src/Components/Components/src/Rendering/RendererSynchronizationContext.cs b/src/Components/Components/src/Rendering/RendererSynchronizationContext.cs
index 9a235b791f..4a97329fe1 100644
--- a/src/Components/Components/src/Rendering/RendererSynchronizationContext.cs
+++ b/src/Components/Components/src/Rendering/RendererSynchronizationContext.cs
@@ -39,12 +39,13 @@ namespace Microsoft.AspNetCore.Components.Rendering
public Task Invoke(Action action)
{
- var completion = new TaskCompletionSource();
- Post(_ =>
+ var completion = new RendererSynchronizationTaskCompletionSource(action);
+ ExecuteSynchronouslyIfPossible((state) =>
{
+ var completion = (RendererSynchronizationTaskCompletionSource)state;
try
{
- action();
+ completion.Callback();
completion.SetResult(null);
}
catch (OperationCanceledException)
@@ -55,19 +56,20 @@ namespace Microsoft.AspNetCore.Components.Rendering
{
completion.SetException(exception);
}
- }, null);
+ }, completion);
return completion.Task;
}
public Task InvokeAsync(Func asyncAction)
{
- var completion = new TaskCompletionSource();
- Post(async (_) =>
+ var completion = new RendererSynchronizationTaskCompletionSource, object>(asyncAction);
+ ExecuteSynchronouslyIfPossible(async (state) =>
{
+ var completion = (RendererSynchronizationTaskCompletionSource, object>)state;
try
{
- await asyncAction();
+ await completion.Callback();
completion.SetResult(null);
}
catch (OperationCanceledException)
@@ -78,19 +80,20 @@ namespace Microsoft.AspNetCore.Components.Rendering
{
completion.SetException(exception);
}
- }, null);
+ }, completion);
return completion.Task;
}
public Task Invoke(Func function)
{
- var completion = new TaskCompletionSource();
- Post(_ =>
+ var completion = new RendererSynchronizationTaskCompletionSource, TResult>(function);
+ ExecuteSynchronouslyIfPossible((state) =>
{
+ var completion = (RendererSynchronizationTaskCompletionSource, TResult>)state;
try
{
- var result = function();
+ var result = completion.Callback();
completion.SetResult(result);
}
catch (OperationCanceledException)
@@ -101,19 +104,20 @@ namespace Microsoft.AspNetCore.Components.Rendering
{
completion.SetException(exception);
}
- }, null);
+ }, completion);
return completion.Task;
}
public Task InvokeAsync(Func> asyncFunction)
{
- var completion = new TaskCompletionSource();
- Post(async (_) =>
+ var completion = new RendererSynchronizationTaskCompletionSource>, TResult>(asyncFunction);
+ ExecuteSynchronouslyIfPossible(async (state) =>
{
+ var completion = (RendererSynchronizationTaskCompletionSource>, TResult>)state;
try
{
- var result = await asyncFunction();
+ var result = await completion.Callback();
completion.SetResult(result);
}
catch (OperationCanceledException)
@@ -124,30 +128,20 @@ namespace Microsoft.AspNetCore.Components.Rendering
{
completion.SetException(exception);
}
- }, null);
+ }, completion);
return completion.Task;
}
// asynchronously runs the callback
+ //
+ // NOTE: this must always run async. It's not legal here to execute the work item synchronously.
public override void Post(SendOrPostCallback d, object state)
{
- TaskCompletionSource completion;
lock (_state.Lock)
{
- if (!_state.Task.IsCompleted)
- {
- _state.Task = Enqueue(_state.Task, d, state);
- return;
- }
-
- // We can execute this synchronously because nothing is currently running
- // or queued.
- completion = new TaskCompletionSource();
- _state.Task = completion.Task;
+ _state.Task = Enqueue(_state.Task, d, state, forceAsync: true);
}
-
- ExecuteSynchronously(completion, d, state);
}
// synchronously runs the callback
@@ -177,10 +171,33 @@ namespace Microsoft.AspNetCore.Components.Rendering
return new RendererSynchronizationContext(_state);
}
- private Task Enqueue(Task antecedant, SendOrPostCallback d, object state)
+ // Similar to Post, but it can runs the work item synchronously if the context is not busy.
+ //
+ // This is the main code path used by components, we want to be able to run async work but only dispatch
+ // if necessary.
+ private void ExecuteSynchronouslyIfPossible(SendOrPostCallback d, object state)
{
- // If we get here is means that a callback is being queued while something is currently executing
- // in this context. Let's instead add it to the queue and yield.
+ TaskCompletionSource completion;
+ lock (_state.Lock)
+ {
+ if (!_state.Task.IsCompleted)
+ {
+ _state.Task = Enqueue(_state.Task, d, state);
+ return;
+ }
+
+ // We can execute this synchronously because nothing is currently running
+ // or queued.
+ completion = new TaskCompletionSource();
+ _state.Task = completion.Task;
+ }
+
+ ExecuteSynchronously(completion, d, state);
+ }
+
+ private Task Enqueue(Task antecedant, SendOrPostCallback d, object state, bool forceAsync = false)
+ {
+ // If we get here is means that a callback is being explicitly queued. Let's instead add it to the queue and yield.
//
// We use our own queue here to maintain the execution order of the callbacks scheduled here. Also
// we need a queue rather than just scheduling an item in the thread pool - those items would immediately
@@ -194,13 +211,14 @@ namespace Microsoft.AspNetCore.Components.Rendering
executionContext = ExecutionContext.Capture();
}
+ var flags = forceAsync ? TaskContinuationOptions.RunContinuationsAsynchronously : TaskContinuationOptions.None;
return antecedant.ContinueWith(BackgroundWorkThunk, new WorkItem()
{
SynchronizationContext = this,
ExecutionContext = executionContext,
Callback = d,
State = state,
- }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
+ }, CancellationToken.None, flags, TaskScheduler.Current);
}
private void ExecuteSynchronously(
@@ -280,5 +298,15 @@ namespace Microsoft.AspNetCore.Components.Rendering
public SendOrPostCallback Callback;
public object State;
}
+
+ private class RendererSynchronizationTaskCompletionSource : TaskCompletionSource
+ {
+ public RendererSynchronizationTaskCompletionSource(TCallback callback)
+ {
+ Callback = callback;
+ }
+
+ public TCallback Callback { get; }
+ }
}
}
diff --git a/src/Components/Components/test/Auth/AuthorizeViewTest.cs b/src/Components/Components/test/Auth/AuthorizeViewTest.cs
index 3039cca28e..5617c3b32d 100644
--- a/src/Components/Components/test/Auth/AuthorizeViewTest.cs
+++ b/src/Components/Components/test/Auth/AuthorizeViewTest.cs
@@ -2,9 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers;
@@ -14,6 +16,10 @@ namespace Microsoft.AspNetCore.Components
{
public class AuthorizeViewTest
{
+ // Nothing should exceed the timeout in a successful run of the the tests, this is just here to catch
+ // failures.
+ private static readonly TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10);
+
[Fact]
public void RendersNothingIfNotAuthorized()
{
@@ -180,7 +186,11 @@ namespace Microsoft.AspNetCore.Components
public void RendersNothingUntilAuthorizationCompleted()
{
// Arrange
- var renderer = new TestRenderer();
+ var @event = new ManualResetEventSlim();
+ var renderer = new TestRenderer()
+ {
+ OnUpdateDisplayComplete = () => { @event.Set(); },
+ };
var rootComponent = WrapInAuthorizeView(
notAuthorizedContent: builder => builder.AddContent(0, "You are not authorized"));
var authTcs = new TaskCompletionSource();
@@ -195,7 +205,12 @@ namespace Microsoft.AspNetCore.Components
Assert.Empty(diff1.Edits);
// Act/Assert 2: Auth process completes asynchronously
+ @event.Reset();
authTcs.SetResult(new AuthenticationState(new ClaimsPrincipal()));
+
+ // We need to wait here because the continuations of SetResult will be scheduled to run asynchronously.
+ @event.Wait(Timeout);
+
Assert.Equal(2, renderer.Batches.Count);
var batch2 = renderer.Batches[1];
var diff2 = batch2.DiffsByComponentId[authorizeViewComponentId].Single();
@@ -212,7 +227,11 @@ namespace Microsoft.AspNetCore.Components
public void RendersAuthorizingContentUntilAuthorizationCompleted()
{
// Arrange
- var renderer = new TestRenderer();
+ var @event = new ManualResetEventSlim();
+ var renderer = new TestRenderer()
+ {
+ OnUpdateDisplayComplete = () => { @event.Set(); },
+ };
var rootComponent = WrapInAuthorizeView(
authorizingContent: builder => builder.AddContent(0, "Auth pending..."),
authorizedContent: context => builder => builder.AddContent(0, $"Hello, {context.User.Identity.Name}!"));
@@ -234,7 +253,12 @@ namespace Microsoft.AspNetCore.Components
});
// Act/Assert 2: Auth process completes asynchronously
+ @event.Reset();
authTcs.SetResult(CreateAuthenticationState("Monsieur").Result);
+
+ // We need to wait here because the continuations of SetResult will be scheduled to run asynchronously.
+ @event.Wait(Timeout);
+
Assert.Equal(2, renderer.Batches.Count);
var batch2 = renderer.Batches[1];
var diff2 = batch2.DiffsByComponentId[authorizeViewComponentId].Single();
diff --git a/src/Components/Components/test/ComponentBaseTest.cs b/src/Components/Components/test/ComponentBaseTest.cs
index 15c2ae98c2..ba9c17f46b 100644
--- a/src/Components/Components/test/ComponentBaseTest.cs
+++ b/src/Components/Components/test/ComponentBaseTest.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.RenderTree;
@@ -12,6 +13,10 @@ namespace Microsoft.AspNetCore.Components.Test
{
public class ComponentBaseTest
{
+ // Nothing should exceed the timeout in a successful run of the the tests, this is just here to catch
+ // failures.
+ private static readonly TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10);
+
[Fact]
public void RunsOnInitWhenRendered()
{
@@ -178,7 +183,12 @@ namespace Microsoft.AspNetCore.Components.Test
public async Task RendersAfterParametersSetAndInitAsyncTasksAreCompleted()
{
// Arrange
- var renderer = new TestRenderer();
+ var @event = new ManualResetEventSlim();
+
+ var renderer = new TestRenderer()
+ {
+ OnUpdateDisplayComplete = () => { @event.Set(); },
+ };
var component = new TestComponent();
component.Counter = 1;
@@ -197,10 +207,16 @@ namespace Microsoft.AspNetCore.Components.Test
// A rendering should have happened after the synchronous execution of Init
Assert.Single(renderer.Batches);
+ @event.Reset();
+
// Completes task started by OnInitAsync
component.Counter = 2;
initTask.SetResult(true);
+ // We need to wait here, because the continuation from SetResult needs to be scheduled.
+ @event.Wait(Timeout);
+ @event.Reset();
+
// Component should be rendered once, after set parameters
Assert.Equal(2, renderer.Batches.Count);
@@ -209,6 +225,7 @@ namespace Microsoft.AspNetCore.Components.Test
parametersSetTask.SetResult(false);
await renderTask;
+ Assert.True(@event.IsSet);
// Component should be rendered again
// after the async part of onparameterssetasync completes
diff --git a/src/Components/Components/test/RendererTest.cs b/src/Components/Components/test/RendererTest.cs
index be4994a83b..8c8d9b1d49 100644
--- a/src/Components/Components/test/RendererTest.cs
+++ b/src/Components/Components/test/RendererTest.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading;
@@ -19,6 +20,10 @@ namespace Microsoft.AspNetCore.Components.Test
{
public class RendererTest
{
+ // Nothing should exceed the timeout in a successful run of the the tests, this is just here to catch
+ // failures.
+ private static readonly TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10);
+
private const string EventActionsName = nameof(NestedAsyncComponent.EventActions);
private const string WhatToRenderName = nameof(NestedAsyncComponent.WhatToRender);
private const string LogName = nameof(NestedAsyncComponent.Log);
@@ -2458,13 +2463,17 @@ namespace Microsoft.AspNetCore.Components.Test
public void CallsAfterRenderAfterTheUIHasFinishedUpdatingAsynchronously()
{
// Arrange
+ var @event = new ManualResetEventSlim();
var tcs = new TaskCompletionSource();
var afterRenderTcs = new TaskCompletionSource();
var onAfterRenderCallCountLog = new List();
- var component = new AsyncAfterRenderComponent(afterRenderTcs.Task);
+ var component = new AsyncAfterRenderComponent(afterRenderTcs.Task)
+ {
+ OnAfterRenderComplete = () => @event.Set(),
+ };
var renderer = new AsyncUpdateTestRenderer()
{
- OnUpdateDisplayAsync = _ => tcs.Task
+ OnUpdateDisplayAsync = _ => tcs.Task,
};
renderer.AssignRootComponentId(component);
@@ -2473,6 +2482,9 @@ namespace Microsoft.AspNetCore.Components.Test
tcs.SetResult(null);
afterRenderTcs.SetResult(null);
+ // We need to wait here because the completions from SetResult will be scheduled.
+ @event.Wait(Timeout);
+
// Assert
Assert.True(component.Called);
}
@@ -2481,9 +2493,13 @@ namespace Microsoft.AspNetCore.Components.Test
public void CallsAfterRenderAfterTheUIHasFinishedUpdatingSynchronously()
{
// Arrange
+ var @event = new ManualResetEventSlim();
var afterRenderTcs = new TaskCompletionSource();
var onAfterRenderCallCountLog = new List();
- var component = new AsyncAfterRenderComponent(afterRenderTcs.Task);
+ var component = new AsyncAfterRenderComponent(afterRenderTcs.Task)
+ {
+ OnAfterRenderComplete = () => @event.Set(),
+ };
var renderer = new AsyncUpdateTestRenderer()
{
OnUpdateDisplayAsync = _ => Task.CompletedTask
@@ -2494,6 +2510,9 @@ namespace Microsoft.AspNetCore.Components.Test
component.TriggerRender();
afterRenderTcs.SetResult(null);
+ // We need to wait here because the completions from SetResult will be scheduled.
+ @event.Wait(Timeout);
+
// Assert
Assert.True(component.Called);
}
@@ -2798,7 +2817,12 @@ namespace Microsoft.AspNetCore.Components.Test
// code paths are special cased for the first render because of prerendering.
// Arrange
- var renderer = new TestRenderer { ShouldHandleExceptions = true };
+ var @event = new ManualResetEventSlim();
+ var renderer = new TestRenderer()
+ {
+ ShouldHandleExceptions = true,
+ OnExceptionHandled = () => { @event.Set(); },
+ };
var taskToAwait = Task.CompletedTask;
var component = new TestComponent(builder =>
{
@@ -2815,8 +2839,13 @@ namespace Microsoft.AspNetCore.Components.Test
// Act
var exception = new InvalidOperationException();
+
+ @event.Reset();
asyncExceptionTcs.SetException(exception);
+ // We need to wait here because the continuations of SetException will be scheduled to run asynchronously.
+ @event.Wait(Timeout);
+
// Assert
Assert.Same(exception, Assert.Single(renderer.HandledExceptions).GetBaseException());
}
@@ -3829,10 +3858,14 @@ namespace Microsoft.AspNetCore.Components.Test
public bool Called { get; private set; }
+ public Action OnAfterRenderComplete { get; set; }
+
public async Task OnAfterRenderAsync()
{
await _task;
Called = true;
+
+ OnAfterRenderComplete?.Invoke();
}
protected override void BuildRenderTree(RenderTreeBuilder builder)
diff --git a/src/Components/Components/test/Rendering/RendererSynchronizationContextTests.cs b/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs
similarity index 95%
rename from src/Components/Components/test/Rendering/RendererSynchronizationContextTests.cs
rename to src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs
index 153f362b0c..5be5050983 100644
--- a/src/Components/Components/test/Rendering/RendererSynchronizationContextTests.cs
+++ b/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs
@@ -1,8 +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.
+
using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
-using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
@@ -16,34 +17,51 @@ namespace Microsoft.AspNetCore.Components.Rendering
public TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10);
[Fact]
- public void Post_CanRunSynchronously_WhenNotBusy()
+ public void Post_RunsAsynchronously_WhenNotBusy()
{
// Arrange
var context = new RendererSynchronizationContext();
var thread = Thread.CurrentThread;
Thread capturedThread = null;
+ var e = new ManualResetEventSlim();
+
// Act
context.Post((_) =>
{
capturedThread = Thread.CurrentThread;
+
+ e.Set();
}, null);
// Assert
- Assert.Same(thread, capturedThread);
+ Assert.True(e.Wait(Timeout), "timeout");
+ Assert.NotSame(thread, capturedThread);
}
[Fact]
- public void Post_CanRunSynchronously_WhenNotBusy_Exception()
+ public void Post_RunsAynchronously_WhenNotBusy_Exception()
{
// Arrange
var context = new RendererSynchronizationContext();
- // Act & Assert
- Assert.Throws(() => context.Post((_) =>
+ Exception exception = null;
+ context.UnhandledException += (sender, e) =>
+ {
+ exception = (InvalidTimeZoneException)e.ExceptionObject;
+ };
+
+ // Act
+ context.Post((_) =>
{
throw new InvalidTimeZoneException();
- }, null));
+ }, null);
+
+ // Assert
+ //
+ // Use another item to 'push through' the throwing one
+ context.Send((_) => { }, null);
+ Assert.NotNull(exception);
}
[Fact]
@@ -573,7 +591,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
Thread capturedThread = null;
// Act
- var task = context.Invoke(() =>
+ var task = context.InvokeAsync(() =>
{
capturedThread = Thread.CurrentThread;
return Task.CompletedTask;
diff --git a/src/Components/Server/test/Circuits/RemoteRendererTest.cs b/src/Components/Server/test/Circuits/RemoteRendererTest.cs
index 428e173a26..630fd75c7e 100644
--- a/src/Components/Server/test/Circuits/RemoteRendererTest.cs
+++ b/src/Components/Server/test/Circuits/RemoteRendererTest.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Text.Encodings.Web;
using System.Threading;
using System.Threading.Tasks;
@@ -19,6 +20,10 @@ namespace Microsoft.AspNetCore.Components.Browser.Rendering
{
public class RemoteRendererTest : HtmlRendererTestBase
{
+ // Nothing should exceed the timeout in a successful run of the the tests, this is just here to catch
+ // failures.
+ private static readonly TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10);
+
protected override HtmlRenderer GetHtmlRenderer(IServiceProvider serviceProvider)
{
return GetRemoteRenderer(serviceProvider, new CircuitClientProxy());
@@ -50,6 +55,7 @@ namespace Microsoft.AspNetCore.Components.Browser.Rendering
public async Task ProcessBufferedRenderBatches_WritesRenders()
{
// Arrange
+ var @event = new ManualResetEventSlim();
var serviceProvider = new ServiceCollection().BuildServiceProvider();
var renderIds = new List();
@@ -78,8 +84,13 @@ namespace Microsoft.AspNetCore.Components.Browser.Rendering
var componentId = renderer.AssignRootComponentId(component);
component.TriggerRender();
renderer.OnRenderCompleted(2, null);
+
+ @event.Reset();
firstBatchTCS.SetResult(null);
+ // Waiting is required here because the continuations of SetResult will not execute synchronously.
+ @event.Wait(Timeout);
+
circuitClient.SetDisconnected();
component.TriggerRender();
component.TriggerRender();
@@ -261,7 +272,7 @@ namespace Microsoft.AspNetCore.Components.Browser.Rendering
NullLogger.Instance);
}
- private class TestComponent : IComponent
+ private class TestComponent : IComponent, IHandleAfterRender
{
private RenderHandle _renderHandle;
private RenderFragment _renderFragment = (builder) =>
@@ -280,11 +291,19 @@ namespace Microsoft.AspNetCore.Components.Browser.Rendering
_renderFragment = renderFragment;
}
+ public Action OnAfterRenderComplete { get; set; }
+
public void Configure(RenderHandle renderHandle)
{
_renderHandle = renderHandle;
}
+ public Task OnAfterRenderAsync()
+ {
+ OnAfterRenderComplete?.Invoke();
+ return Task.CompletedTask;
+ }
+
public Task SetParametersAsync(ParameterCollection parameters)
{
TriggerRender();
diff --git a/src/Components/Shared/test/TestRenderer.cs b/src/Components/Shared/test/TestRenderer.cs
index 8b0cecd4f9..f2a99ccdd4 100644
--- a/src/Components/Shared/test/TestRenderer.cs
+++ b/src/Components/Shared/test/TestRenderer.cs
@@ -25,8 +25,12 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers
{
}
+ public Action OnExceptionHandled { get; set; }
+
public Action OnUpdateDisplay { get; set; }
+ public Action OnUpdateDisplayComplete { get; set; }
+
public List Batches { get; }
= new List();
@@ -81,6 +85,7 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers
}
HandledExceptions.Add(exception);
+ OnExceptionHandled?.Invoke();
}
protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
@@ -102,6 +107,8 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers
// This renderer updates the UI synchronously, like the WebAssembly one.
// To test async UI updates, subclass TestRenderer and override UpdateDisplayAsync.
+
+ OnUpdateDisplayComplete?.Invoke();
return Task.CompletedTask;
}
}
From c05244cda928c94c25dc17bc9f8c6211106ded9a Mon Sep 17 00:00:00 2001
From: BrennanConroy
Date: Thu, 23 May 2019 14:46:32 -0700
Subject: [PATCH 03/95] More docker resiliency for tests (#10425)
---
src/SignalR/server/StackExchangeRedis/test/Docker.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/SignalR/server/StackExchangeRedis/test/Docker.cs b/src/SignalR/server/StackExchangeRedis/test/Docker.cs
index c5f613461e..cdcbe9bfcc 100644
--- a/src/SignalR/server/StackExchangeRedis/test/Docker.cs
+++ b/src/SignalR/server/StackExchangeRedis/test/Docker.cs
@@ -81,6 +81,9 @@ namespace Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests
{
logger.LogError(ex, "Error starting redis docker container, retrying.");
Thread.Sleep(1000);
+
+ // Call stop just in case the container somehow started after the timeout so our retry logic doesn't fail
+ RunProcessAndWait(_path, $"stop {_dockerContainerName}", "docker stop", logger, TimeSpan.FromSeconds(15), out var _);
Run();
}
@@ -90,7 +93,7 @@ namespace Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests
// use static name 'redisTestContainer' so if the container doesn't get removed we don't keep adding more
// use redis base docker image
// 30 second timeout to allow redis image to be downloaded, should be a rare occurrence, only happening when a new version is released
- RunProcessAndThrowIfFailed(_path, $"run --rm -p 6379:6379 --name {_dockerContainerName} -d redis", "redis", logger, TimeSpan.FromSeconds(30));
+ RunProcessAndThrowIfFailed(_path, $"run --rm -p 6379:6379 --name {_dockerContainerName} -d redis", "redis", logger, TimeSpan.FromMinutes(1));
}
}
From e01d713909e4905643b33c4f7fb261bb90e80b3d Mon Sep 17 00:00:00 2001
From: Nate McMaster
Date: Thu, 23 May 2019 15:35:49 -0700
Subject: [PATCH 04/95] Use Microsoft.Net.Compilers.Toolset (#10415)
---
Directory.Build.props | 10 +-
build/sources.props | 1 +
eng/Version.Details.xml | 12 +-
eng/Versions.props | 6 +-
eng/common/PublishToPackageFeed.proj | 1 +
eng/common/build.ps1 | 4 +
eng/common/build.sh | 5 +
eng/common/cross/arm64/sources.list.buster | 11 ++
eng/common/cross/arm64/sources.list.stretch | 12 ++
eng/common/cross/build-rootfs.sh | 17 ++-
eng/common/darc-init.ps1 | 11 +-
eng/common/darc-init.sh | 15 ++-
eng/common/dotnet-install.ps1 | 11 +-
eng/common/templates/steps/send-to-helix.yml | 3 +
eng/common/tools.ps1 | 6 +-
eng/common/tools.sh | 115 +++++++++++++++++--
global.json | 4 +-
17 files changed, 212 insertions(+), 32 deletions(-)
create mode 100644 eng/common/cross/arm64/sources.list.buster
create mode 100644 eng/common/cross/arm64/sources.list.stretch
diff --git a/Directory.Build.props b/Directory.Build.props
index 8b002c635e..8a8ef6d27d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,6 +1,15 @@
+
+
+
+
+
Microsoft ASP.NET Core
@@ -121,7 +130,6 @@
$(MSBuildProjectName)-ref
-
diff --git a/build/sources.props b/build/sources.props
index 26d8be6677..b561688d1f 100644
--- a/build/sources.props
+++ b/build/sources.props
@@ -14,6 +14,7 @@
https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json;
https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json;
https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json;
+ https://dotnet.myget.org/F/roslyn/api/v3/index.json;
https://grpc.jfrog.io/grpc/api/nuget/v3/grpc-nuget-dev;
https://api.nuget.org/v3/index.json;
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index fc32cbe01a..11b8454994 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -384,13 +384,17 @@
https://github.com/aspnet/Extensions
8dfb4ece7ca9a6dea14264dafc38a0c953874559
-
+
https://github.com/dotnet/arcade
- e913fb3b02d4089a91ff91c041c5f6e7c29038b0
+ 86e674361bdcefecbd8199ab62d0b1a6cb25703d
-
+
https://github.com/dotnet/arcade
- e913fb3b02d4089a91ff91c041c5f6e7c29038b0
+ 86e674361bdcefecbd8199ab62d0b1a6cb25703d
+
+
+ https://github.com/dotnet/arcade
+ 86e674361bdcefecbd8199ab62d0b1a6cb25703d
https://github.com/aspnet/Extensions
diff --git a/eng/Versions.props b/eng/Versions.props
index 10a317d441..108f3ea38a 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -5,6 +5,10 @@
-->
+
+
+ true
+
- 1.0.0-beta.19270.1
+ 1.0.0-beta.19272.13
3.0.0-preview6-27714-15
3.0.0-preview6-27714-15
diff --git a/eng/common/PublishToPackageFeed.proj b/eng/common/PublishToPackageFeed.proj
index e17f72644e..9120b2d212 100644
--- a/eng/common/PublishToPackageFeed.proj
+++ b/eng/common/PublishToPackageFeed.proj
@@ -53,6 +53,7 @@
https://dotnetfeed.blob.core.windows.net/dotnet-toolset/index.json
https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json
https://dotnetfeed.blob.core.windows.net/nuget-nugetclient/index.json
+ https://dotnetfeed.blob.core.windows.net/aspnet-entityframework6/index.json
Build configuration: 'Debug' or 'Release' (short: -c)"
+ Write-Host " -platform Platform configuration: 'x86', 'x64' or any valid Platform value to pass to msbuild"
Write-Host " -verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)"
Write-Host " -binaryLog Output binary log (short: -bl)"
Write-Host " -help Print help and exit"
@@ -77,6 +79,7 @@ function Build {
InitializeCustomToolset
$bl = if ($binaryLog) { "/bl:" + (Join-Path $LogDir "Build.binlog") } else { "" }
+ $platformArg = if ($platform) { "/p:Platform=$platform" } else { "" }
if ($projects) {
# Re-assign properties to a new variable because PowerShell doesn't let us append properties directly for unclear reasons.
@@ -88,6 +91,7 @@ function Build {
MSBuild $toolsetBuildProj `
$bl `
+ $platformArg `
/p:Configuration=$configuration `
/p:RepoRoot=$RepoRoot `
/p:Restore=$restore `
diff --git a/eng/common/build.sh b/eng/common/build.sh
index ce846d888d..6236fc4d38 100755
--- a/eng/common/build.sh
+++ b/eng/common/build.sh
@@ -66,6 +66,7 @@ ci=false
warn_as_error=true
node_reuse=true
binary_log=false
+pipelines_log=false
projects=''
configuration='Debug'
@@ -92,6 +93,9 @@ while [[ $# > 0 ]]; do
-binarylog|-bl)
binary_log=true
;;
+ -pipelineslog|-pl)
+ pipelines_log=true
+ ;;
-restore|-r)
restore=true
;;
@@ -146,6 +150,7 @@ while [[ $# > 0 ]]; do
done
if [[ "$ci" == true ]]; then
+ pipelines_log=true
binary_log=true
node_reuse=false
fi
diff --git a/eng/common/cross/arm64/sources.list.buster b/eng/common/cross/arm64/sources.list.buster
new file mode 100644
index 0000000000..7194ac64a9
--- /dev/null
+++ b/eng/common/cross/arm64/sources.list.buster
@@ -0,0 +1,11 @@
+deb http://deb.debian.org/debian buster main
+deb-src http://deb.debian.org/debian buster main
+
+deb http://deb.debian.org/debian-security/ buster/updates main
+deb-src http://deb.debian.org/debian-security/ buster/updates main
+
+deb http://deb.debian.org/debian buster-updates main
+deb-src http://deb.debian.org/debian buster-updates main
+
+deb http://deb.debian.org/debian buster-backports main contrib non-free
+deb-src http://deb.debian.org/debian buster-backports main contrib non-free
diff --git a/eng/common/cross/arm64/sources.list.stretch b/eng/common/cross/arm64/sources.list.stretch
new file mode 100644
index 0000000000..0e12157743
--- /dev/null
+++ b/eng/common/cross/arm64/sources.list.stretch
@@ -0,0 +1,12 @@
+deb http://deb.debian.org/debian stretch main
+deb-src http://deb.debian.org/debian stretch main
+
+deb http://deb.debian.org/debian-security/ stretch/updates main
+deb-src http://deb.debian.org/debian-security/ stretch/updates main
+
+deb http://deb.debian.org/debian stretch-updates main
+deb-src http://deb.debian.org/debian stretch-updates main
+
+deb http://deb.debian.org/debian stretch-backports main contrib non-free
+deb-src http://deb.debian.org/debian stretch-backports main contrib non-free
+
diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh
index 83ec39195c..34d3d2ba1f 100755
--- a/eng/common/cross/build-rootfs.sh
+++ b/eng/common/cross/build-rootfs.sh
@@ -2,7 +2,7 @@
usage()
{
- echo "Usage: $0 [BuildArch] [LinuxCodeName] [lldbx.y] [--skipunmount] --rootfs ]"
+ echo "Usage: $0 [BuildArch] [LinuxCodeName] [lldbx.y] [--skipunmount] --rootfsdir ]"
echo "BuildArch can be: arm(default), armel, arm64, x86"
echo "LinuxCodeName - optional, Code name for Linux, can be: trusty, xenial(default), zesty, bionic, alpine. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen."
echo "lldbx.y - optional, LLDB version, can be: lldb3.9(default), lldb4.0, lldb5.0, lldb6.0 no-lldb. Ignored for alpine"
@@ -113,12 +113,12 @@ while :; do
__LinuxCodeName=trusty
fi
;;
- xenial) # Ubunry 16.04
+ xenial) # Ubuntu 16.04
if [ "$__LinuxCodeName" != "jessie" ]; then
__LinuxCodeName=xenial
fi
;;
- zesty) # Ununtu 17.04
+ zesty) # Ubuntu 17.04
if [ "$__LinuxCodeName" != "jessie" ]; then
__LinuxCodeName=zesty
fi
@@ -132,7 +132,16 @@ while :; do
__LinuxCodeName=jessie
__UbuntuRepo="http://ftp.debian.org/debian/"
;;
- # TBD Stretch -> Debian 9, Buster -> Debian 10
+ stretch) # Debian 9
+ __LinuxCodeName=stretch
+ __UbuntuRepo="http://ftp.debian.org/debian/"
+ __LLDB_Package="liblldb-6.0-dev"
+ ;;
+ buster) # Debian 10
+ __LinuxCodeName=buster
+ __UbuntuRepo="http://ftp.debian.org/debian/"
+ __LLDB_Package="liblldb-6.0-dev"
+ ;;
tizen)
if [ "$__BuildArch" != "armel" ]; then
echo "Tizen is available only for armel."
diff --git a/eng/common/darc-init.ps1 b/eng/common/darc-init.ps1
index 81ffd16779..dea7cdd903 100644
--- a/eng/common/darc-init.ps1
+++ b/eng/common/darc-init.ps1
@@ -1,5 +1,6 @@
param (
- $darcVersion = $null
+ $darcVersion = $null,
+ $versionEndpoint = "https://maestro-prod.westus2.cloudapp.azure.com/api/assets/darc-version?api-version=2019-01-16"
)
$verbosity = "m"
@@ -16,13 +17,13 @@ function InstallDarcCli ($darcVersion) {
Invoke-Expression "& `"$dotnet`" tool uninstall $darcCliPackageName -g"
}
- # Until we can anonymously query the BAR API for the latest arcade-services
- # build applied to the PROD channel, this is hardcoded.
+ # If the user didn't explicitly specify the darc version,
+ # query the Maestro API for the correct version of darc to install.
if (-not $darcVersion) {
- $darcVersion = '1.1.0-beta.19205.4'
+ $darcVersion = $(Invoke-WebRequest -Uri $versionEndpoint -UseBasicParsing).Content
}
- $arcadeServicesSource = 'https://dotnetfeed.blob.core.windows.net/dotnet-arcade/index.json'
+ $arcadeServicesSource = 'https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json'
Write-Host "Installing Darc CLI version $darcVersion..."
Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed."
diff --git a/eng/common/darc-init.sh b/eng/common/darc-init.sh
index bd7eb46398..abdd0bc05a 100755
--- a/eng/common/darc-init.sh
+++ b/eng/common/darc-init.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
source="${BASH_SOURCE[0]}"
-darcVersion="1.1.0-beta.19205.4"
+darcVersion=''
+versionEndpoint="https://maestro-prod.westus2.cloudapp.azure.com/api/assets/darc-version?api-version=2019-01-16"
while [[ $# > 0 ]]; do
opt="$(echo "$1" | awk '{print tolower($0)}')"
@@ -10,6 +11,10 @@ while [[ $# > 0 ]]; do
darcVersion=$2
shift
;;
+ --versionendpoint)
+ versionEndpoint=$2
+ shift
+ ;;
*)
echo "Invalid argument: $1"
usage
@@ -33,6 +38,10 @@ verbosity=m
. "$scriptroot/tools.sh"
+if [ -z "$darcVersion" ]; then
+ darcVersion=$(curl -X GET "$versionEndpoint" -H "accept: text/plain")
+fi
+
function InstallDarcCli {
local darc_cli_package_name="microsoft.dotnet.darc"
@@ -45,9 +54,9 @@ function InstallDarcCli {
echo $($dotnet_root/dotnet tool uninstall $darc_cli_package_name -g)
fi
- local arcadeServicesSource="https://dotnetfeed.blob.core.windows.net/dotnet-arcade/index.json"
+ local arcadeServicesSource="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json"
- echo "Installing Darc CLI version $toolset_version..."
+ echo "Installing Darc CLI version $darcVersion..."
echo "You may need to restart your command shell if this is the first dotnet tool you have installed."
echo $($dotnet_root/dotnet tool install $darc_cli_package_name --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity -g)
}
diff --git a/eng/common/dotnet-install.ps1 b/eng/common/dotnet-install.ps1
index 5987943fd6..0b629b8301 100644
--- a/eng/common/dotnet-install.ps1
+++ b/eng/common/dotnet-install.ps1
@@ -8,9 +8,14 @@ Param(
. $PSScriptRoot\tools.ps1
+$dotnetRoot = Join-Path $RepoRoot ".dotnet"
+
+$installdir = $dotnetRoot
try {
- $dotnetRoot = Join-Path $RepoRoot ".dotnet"
- InstallDotNet $dotnetRoot $version $architecture $runtime $true
+ if ($architecture -and $architecture.Trim() -eq "x86") {
+ $installdir = Join-Path $installdir "x86"
+ }
+ InstallDotNet $installdir $version $architecture $runtime $true
}
catch {
Write-Host $_
@@ -19,4 +24,4 @@ catch {
ExitWithExitCode 1
}
-ExitWithExitCode 0
\ No newline at end of file
+ExitWithExitCode 0
diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml
index d1ce577db5..05df886f55 100644
--- a/eng/common/templates/steps/send-to-helix.yml
+++ b/eng/common/templates/steps/send-to-helix.yml
@@ -5,6 +5,7 @@ parameters:
HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number
HelixTargetQueues: '' # required -- semicolon delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues
HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group
+ HelixConfiguration: '' # optional -- additional property attached to a job
HelixPreCommands: '' # optional -- commands to run before Helix work item execution
HelixPostCommands: '' # optional -- commands to run after Helix work item execution
WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects
@@ -35,6 +36,7 @@ steps:
HelixSource: ${{ parameters.HelixSource }}
HelixType: ${{ parameters.HelixType }}
HelixBuild: ${{ parameters.HelixBuild }}
+ HelixConfiguration: ${{ parameters.HelixConfiguration }}
HelixTargetQueues: ${{ parameters.HelixTargetQueues }}
HelixAccessToken: ${{ parameters.HelixAccessToken }}
HelixPreCommands: ${{ parameters.HelixPreCommands }}
@@ -64,6 +66,7 @@ steps:
HelixSource: ${{ parameters.HelixSource }}
HelixType: ${{ parameters.HelixType }}
HelixBuild: ${{ parameters.HelixBuild }}
+ HelixConfiguration: ${{ parameters.HelixConfiguration }}
HelixTargetQueues: ${{ parameters.HelixTargetQueues }}
HelixAccessToken: ${{ parameters.HelixAccessToken }}
HelixPreCommands: ${{ parameters.HelixPreCommands }}
diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1
index 9ca177b82a..9cea610a27 100644
--- a/eng/common/tools.ps1
+++ b/eng/common/tools.ps1
@@ -213,7 +213,11 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements =
if ($env:VSINSTALLDIR -ne $null) {
$msbuildCmd = Get-Command "msbuild.exe" -ErrorAction SilentlyContinue
if ($msbuildCmd -ne $null) {
- if ($msbuildCmd.Version -ge $vsMinVersion) {
+ # Workaround for https://github.com/dotnet/roslyn/issues/35793
+ # Due to this issue $msbuildCmd.Version returns 0.0.0.0 for msbuild.exe 16.2+
+ $msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split(@('-', '+'))[0])
+
+ if ($msbuildVersion -ge $vsMinVersion) {
return $global:_MSBuildExe = $msbuildCmd.Path
}
diff --git a/eng/common/tools.sh b/eng/common/tools.sh
index df3eb8bce0..34a23e9476 100755
--- a/eng/common/tools.sh
+++ b/eng/common/tools.sh
@@ -1,8 +1,20 @@
+#!/usr/bin/env bash
+
# Initialize variables if they aren't already defined.
# CI mode - set to true on CI server for PR validation build or official build.
ci=${ci:-false}
+# Set to true to use the pipelines logger which will enable Azure logging output.
+# https://github.com/Microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md
+# This flag is meant as a temporary opt-opt for the feature while validate it across
+# our consumers. It will be deleted in the future.
+if [[ "$ci" == true ]]; then
+ pipelines_log=${pipelines_log:-true}
+else
+ pipelines_log=${pipelines_log:-false}
+fi
+
# Build configuration. Common values include 'Debug' and 'Release', but the repository may use other names.
configuration=${configuration:-'Debug'}
@@ -40,6 +52,78 @@ else
use_global_nuget_cache=${use_global_nuget_cache:-true}
fi
+function EmitError {
+ if [[ "$ci" != true ]]; then
+ echo "$@" >&2
+ return
+ fi
+
+ message_type="error"
+ sourcepath=''
+ linenumber=''
+ columnnumber=''
+ error_code=''
+
+ while [[ $# -gt 0 ]]; do
+ opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')"
+ case "$opt" in
+ -type|-t)
+ message_type=$2
+ shift
+ ;;
+ -sourcepath|-s)
+ sourcepath=$2
+ shift
+ ;;
+ -linenumber|-l)
+ linenumber=$2
+ shift
+ ;;
+ -columnnumber|-col)
+ columnnumber=$2
+ shift
+ ;;
+ -code|-c)
+ error_code=$2
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+
+ shift
+ done
+
+ message='##vso[task.logissue'
+
+ message="$message type=$message_type"
+
+ if [ -n "$sourcepath" ]; then
+ message="$message;sourcepath=$sourcepath"
+ else
+ message="$message;sourcepath=${BASH_SOURCE[1]}"
+ fi
+
+ if [ -n "$linenumber" ]; then
+ message="$message;linenumber=$linenumber"
+ else
+ message="$message;linenumber=${BASH_LINENO[0]}"
+ fi
+
+ if [ -n "$columnnumber" ]; then
+ message="$message;columnnumber=$columnnumber"
+ fi
+
+ if [ -n "$error_code" ]; then
+ message="$message;code=$error_code"
+ fi
+
+ message="$message]$*"
+
+ echo "$message"
+}
+
# Resolve any symlinks in the given path.
function ResolvePath {
local path=$1
@@ -65,7 +149,7 @@ function ReadGlobalVersion {
local pattern="\"$key\" *: *\"(.*)\""
if [[ ! $line =~ $pattern ]]; then
- echo "Error: Cannot find \"$key\" in $global_json_file" >&2
+ EmitError "Error: Cannot find \"$key\" in $global_json_file"
ExitWithExitCode 1
fi
@@ -126,7 +210,7 @@ function InitializeDotNetCli {
if [[ "$install" == true ]]; then
InstallDotNetSdk "$dotnet_root" "$dotnet_sdk_version"
else
- echo "Unable to find dotnet with SDK version '$dotnet_sdk_version'" >&2
+ EmitError "Unable to find dotnet with SDK version '$dotnet_sdk_version'"
ExitWithExitCode 1
fi
fi
@@ -179,7 +263,7 @@ function InstallDotNet {
fi
bash "$install_script" --version $version --install-dir "$root" $archArg $runtimeArg $skipNonVersionedFilesArg || {
local exit_code=$?
- echo "Failed to install dotnet SDK (exit code '$exit_code')." >&2
+ EmitError "Failed to install dotnet SDK (exit code '$exit_code')."
ExitWithExitCode $exit_code
}
}
@@ -216,6 +300,7 @@ function InitializeBuildTool {
# return values
_InitializeBuildTool="$_InitializeDotNetCli/dotnet"
_InitializeBuildToolCommand="msbuild"
+ _InitializeBuildToolFramework="netcoreapp2.1"
}
function GetNuGetPackageCachePath {
@@ -264,7 +349,7 @@ function InitializeToolset {
fi
if [[ "$restore" != true ]]; then
- echo "Toolset version $toolsetVersion has not been restored." >&2
+ EmitError "Toolset version $toolsetVersion has not been restored."
ExitWithExitCode 2
fi
@@ -276,12 +361,12 @@ function InitializeToolset {
fi
echo ' ' > "$proj"
- MSBuild "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file"
+ MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file"
local toolset_build_proj=`cat "$toolset_location_file"`
if [[ ! -a "$toolset_build_proj" ]]; then
- echo "Invalid toolset path: $toolset_build_proj" >&2
+ EmitError "Invalid toolset path: $toolset_build_proj"
ExitWithExitCode 3
fi
@@ -304,14 +389,26 @@ function StopProcesses {
}
function MSBuild {
+ args=$@
+ if [[ "$pipelines_log" == true ]]; then
+ InitializeBuildTool
+ InitializeToolset
+ _toolset_dir="${_InitializeToolset%/*}"
+ _loggerPath="$_toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.Arcade.Sdk.dll"
+ args=( "${args[@]}" "-logger:$_loggerPath" )
+ fi
+ MSBuild-Core ${args[@]}
+}
+
+function MSBuild-Core {
if [[ "$ci" == true ]]; then
if [[ "$binary_log" != true ]]; then
- echo "Binary log must be enabled in CI build." >&2
+ EmitError "Binary log must be enabled in CI build."
ExitWithExitCode 1
fi
if [[ "$node_reuse" == true ]]; then
- echo "Node reuse must be disabled in CI build." >&2
+ EmitError "Node reuse must be disabled in CI build."
ExitWithExitCode 1
fi
fi
@@ -325,7 +422,7 @@ function MSBuild {
"$_InitializeBuildTool" "$_InitializeBuildToolCommand" /m /nologo /clp:Summary /v:$verbosity /nr:$node_reuse $warnaserror_switch /p:TreatWarningsAsErrors=$warn_as_error /p:ContinuousIntegrationBuild=$ci "$@" || {
local exit_code=$?
- echo "Build failed (exit code '$exit_code')." >&2
+ EmitError "Build failed (exit code '$exit_code')."
ExitWithExitCode $exit_code
}
}
diff --git a/global.json b/global.json
index 30db777b99..e4c42b3c60 100644
--- a/global.json
+++ b/global.json
@@ -3,10 +3,12 @@
"version": "3.0.100-preview5-011568"
},
"tools": {
+ "dotnet": "3.0.100-preview5-011568",
"jdk": "11.0.3"
},
"msbuild-sdks": {
"Yarn.MSBuild": "1.15.2",
- "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19270.1"
+ "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19272.13",
+ "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19272.13"
}
}
From 72433039c02abe13963945238abdfa5d1ae4d5dd Mon Sep 17 00:00:00 2001
From: "dotnet-maestro[bot]"
Date: Thu, 23 May 2019 15:40:54 -0700
Subject: [PATCH 05/95] Update dependencies and pin System.Data.SqlClient
(#10434)
---
eng/Version.Details.xml | 358 +++++++++---------
eng/Versions.props | 172 ++++-----
.../Build/test/BindRazorIntegrationTest.cs | 18 +-
.../test/RenderingRazorIntegrationTest.cs | 2 +-
.../BasicTestApp/InputEventComponent.razor | 2 +-
5 files changed, 276 insertions(+), 276 deletions(-)
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 11b8454994..0bfad6512e 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -9,21 +9,21 @@
-->
-
+
https://github.com/aspnet/AspNetCore-Tooling
- 62e33dac1d5ec88ab15d7af694c1adf29ffc4c59
+ 5bcd00877984c63293665f75bad20f522132638a
-
+
https://github.com/aspnet/AspNetCore-Tooling
- 62e33dac1d5ec88ab15d7af694c1adf29ffc4c59
+ 5bcd00877984c63293665f75bad20f522132638a
-
+
https://github.com/aspnet/AspNetCore-Tooling
- 62e33dac1d5ec88ab15d7af694c1adf29ffc4c59
+ 5bcd00877984c63293665f75bad20f522132638a
-
+
https://github.com/aspnet/AspNetCore-Tooling
- 62e33dac1d5ec88ab15d7af694c1adf29ffc4c59
+ 5bcd00877984c63293665f75bad20f522132638a
https://github.com/aspnet/EntityFrameworkCore
@@ -53,336 +53,336 @@
https://github.com/aspnet/EntityFrameworkCore
08edd86216be4857b45b47bf0a9b29e98e525c05
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
-
+
+ https://github.com/dotnet/corefx
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
+
+
+ https://github.com/dotnet/corefx
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
+
+
+ https://github.com/dotnet/corefx
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
+
+
https://github.com/dotnet/corefx
a28176b5ec68b6da1472934fe9493790d1665cae
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
- https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
-
-
- https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
-
-
- https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
-
-
+
https://github.com/dotnet/core-setup
- 73226d6f119c757813f47b0dc021e8700d525f71
+ c3145b06ba5151d5eafcf177a2e380f7acb61189
-
+
https://github.com/dotnet/core-setup
- 73226d6f119c757813f47b0dc021e8700d525f71
+ c3145b06ba5151d5eafcf177a2e380f7acb61189
-
+
https://github.com/dotnet/corefx
- a28176b5ec68b6da1472934fe9493790d1665cae
+ ef1a5aa730098b6c3350977a991232c1ff11cfe3
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
https://github.com/dotnet/arcade
@@ -396,9 +396,9 @@
https://github.com/dotnet/arcade
86e674361bdcefecbd8199ab62d0b1a6cb25703d
-
+
https://github.com/aspnet/Extensions
- 8dfb4ece7ca9a6dea14264dafc38a0c953874559
+ da5dee978f4eece3de85b776dfcf9dcc4cf5b109
diff --git a/eng/Versions.props b/eng/Versions.props
index 108f3ea38a..78e4d044b8 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -23,92 +23,92 @@
1.0.0-beta.19272.13
- 3.0.0-preview6-27714-15
- 3.0.0-preview6-27714-15
+ 3.0.0-preview6-27720-09
+ 3.0.0-preview6-27720-09
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
4.7.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 1.7.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
- 4.6.0-preview6.19264.9
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 1.7.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
+ 4.6.0-preview6.19270.12
- 3.0.0-preview6.19264.9
+ 3.0.0-preview6.19270.12
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
- 3.0.0-preview6.19265.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
+ 3.0.0-preview6.19271.2
3.0.0-preview6.19252.4
3.0.0-preview6.19252.4
@@ -118,10 +118,10 @@
3.0.0-preview6.19252.4
3.0.0-preview6.19252.4
- 3.0.0-preview6.19270.2
- 3.0.0-preview6.19270.2
- 3.0.0-preview6.19270.2
- 3.0.0-preview6.19270.2
+ 3.0.0-preview6.19272.2
+ 3.0.0-preview6.19272.2
+ 3.0.0-preview6.19272.2
+ 3.0.0-preview6.19272.2
true
@@ -20,8 +19,7 @@
-
-
+
diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs
index 12aacce182..c0b0c49225 100644
--- a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs
+++ b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs
@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.Test;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
+using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
@@ -27,11 +28,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
_fixture = fixture;
}
- protected override bool ShouldSkipDbTests()
- {
- return TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows;
- }
-
public class TestUserDbContext : IdentityUserContext
{
public TestUserDbContext(DbContextOptions options) : base(options) { }
@@ -54,9 +50,9 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName);
- public TestUserDbContext CreateContext()
+ private TestUserDbContext CreateContext()
{
- var db = DbUtil.Create(_fixture.ConnectionString);
+ var db = DbUtil.Create(_fixture.Connection);
db.Database.EnsureCreated();
return db;
}
@@ -89,7 +85,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
{
var sqlConn = dbContext.Database.GetDbConnection();
- using (var db = new SqlConnection(sqlConn.ConnectionString))
+ using (var db = new SqliteConnection(sqlConn.ConnectionString))
{
db.Open();
Assert.True(DbUtil.VerifyColumns(db, "AspNetUsers", "Id", "UserName", "Email", "PasswordHash", "SecurityStamp",
@@ -104,7 +100,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
DbUtil.VerifyIndex(db, "AspNetUsers", "UserNameIndex", isUnique: true);
DbUtil.VerifyIndex(db, "AspNetUsers", "EmailIndex");
- DbUtil.VerifyMaxLength(db, "AspNetUsers", 256, "UserName", "Email", "NormalizeUserName", "NormalizeEmail");
+ DbUtil.VerifyMaxLength(dbContext, "AspNetUsers", 256, "UserName", "Email", "NormalizeUserName", "NormalizeEmail");
db.Close();
}
@@ -249,4 +245,4 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
Assert.Equal(2, (await manager.GetRolesAsync(userByEmail)).Count);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs
index 3c7ae781a4..d889876dcc 100644
--- a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs
+++ b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs
@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.Test;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
+using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@@ -58,11 +59,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
SetupAddIdentity(services);
}
- protected override bool ShouldSkipDbTests()
- {
- return TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows;
- }
-
public class TestDbContext : IdentityDbContext {
public TestDbContext(DbContextOptions options) : base(options) { }
}
@@ -94,11 +90,11 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName);
- public virtual TestDbContext CreateContext()
+ protected virtual TestDbContext CreateContext()
{
var services = new ServiceCollection();
SetupAddIdentity(services);
- var db = DbUtil.Create(_fixture.ConnectionString, services);
+ var db = DbUtil.Create(_fixture.Connection, services);
db.Database.EnsureCreated();
return db;
}
@@ -136,7 +132,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
{
var sqlConn = dbContext.Database.GetDbConnection();
- using (var db = new SqlConnection(sqlConn.ConnectionString))
+ using (var db = new SqliteConnection(sqlConn.ConnectionString))
{
db.Open();
Assert.True(DbUtil.VerifyColumns(db, "AspNetUsers", "Id", "UserName", "Email", "PasswordHash", "SecurityStamp",
@@ -148,8 +144,8 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
Assert.True(DbUtil.VerifyColumns(db, "AspNetUserLogins", "UserId", "ProviderKey", "LoginProvider", "ProviderDisplayName"));
Assert.True(DbUtil.VerifyColumns(db, "AspNetUserTokens", "UserId", "LoginProvider", "Name", "Value"));
- Assert.True(DbUtil.VerifyMaxLength(db, "AspNetUsers", 256, "UserName", "Email", "NormalizedUserName", "NormalizedEmail"));
- Assert.True(DbUtil.VerifyMaxLength(db, "AspNetRoles", 256, "Name", "NormalizedName"));
+ Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetUsers", 256, "UserName", "Email", "NormalizedUserName", "NormalizedEmail"));
+ Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetRoles", 256, "Name", "NormalizedName"));
DbUtil.VerifyIndex(db, "AspNetRoles", "RoleNameIndex", isUnique: true);
DbUtil.VerifyIndex(db, "AspNetUsers", "UserNameIndex", isUnique: true);
diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyCustomContextTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyCustomContextTest.cs
index 47d1e30d5c..14eb1a77ee 100644
--- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyCustomContextTest.cs
+++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyCustomContextTest.cs
@@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
services
.AddSingleton(new ConfigurationBuilder().Build())
.AddDbContext(o =>
- o.UseSqlServer(fixture.ConnectionString)
+ o.UseSqlite(fixture.Connection)
.ConfigureWarnings(b => b.Log(CoreEventId.ManyServiceProvidersCreatedWarning)))
.AddIdentityCore(o => { })
.AddEntityFrameworkStores();
diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyTest.cs
index 8f1ea38881..4fa6c005cb 100644
--- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyTest.cs
+++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyTest.cs
@@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
services
.AddSingleton(new ConfigurationBuilder().Build())
.AddDbContext(
- o => o.UseSqlServer(fixture.ConnectionString)
+ o => o.UseSqlite(fixture.Connection)
.ConfigureWarnings(b => b.Log(CoreEventId.ManyServiceProvidersCreatedWarning)))
.AddIdentityCore(o => { })
.AddEntityFrameworkStores();
diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreEncryptPersonalDataTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreEncryptPersonalDataTest.cs
index 8d8c4c5a26..bf186561ed 100644
--- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreEncryptPersonalDataTest.cs
+++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreEncryptPersonalDataTest.cs
@@ -75,10 +75,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
[Fact]
public async Task CanRotateKeysAndStillFind()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var name = Guid.NewGuid().ToString();
var user = CreateTestUser(name);
@@ -176,11 +172,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
[InlineData(false)]
public async Task CustomPersonalDataPropertiesAreProtected(bool protect)
{
- if (ShouldSkipDbTests())
- {
- return;
- }
-
using (var scratch = new ScratchDatabaseFixture())
{
var services = new ServiceCollection().AddLogging();
@@ -191,7 +182,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
.AddEntityFrameworkStores>()
.AddPersonalDataProtection();
- var dbOptions = new DbContextOptionsBuilder().UseSqlServer(scratch.ConnectionString)
+ var dbOptions = new DbContextOptionsBuilder().UseSqlite(scratch.Connection)
.UseApplicationServiceProvider(services.BuildServiceProvider())
.Options;
var dbContext = new IdentityDbContext(dbOptions);
@@ -260,11 +251,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
[Fact]
public void ProtectedPersonalDataThrowsOnNonString()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
-
using (var scratch = new ScratchDatabaseFixture())
{
var services = new ServiceCollection().AddLogging();
@@ -274,7 +260,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
})
.AddEntityFrameworkStores>()
.AddPersonalDataProtection();
- var dbOptions = new DbContextOptionsBuilder().UseSqlServer(scratch.ConnectionString)
+ var dbOptions = new DbContextOptionsBuilder().UseSqlite(scratch.Connection)
.UseApplicationServiceProvider(services.BuildServiceProvider())
.Options;
var dbContext = new IdentityDbContext(dbOptions);
diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs
index d143047a58..3618b97309 100644
--- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs
+++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs
@@ -23,9 +23,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
_fixture = fixture;
}
- protected override bool ShouldSkipDbTests()
- => TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows;
-
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions options) : base(options)
@@ -48,9 +45,9 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
}
}
- public IdentityDbContext CreateContext(bool delete = false)
+ private IdentityDbContext CreateContext(bool delete = false)
{
- var db = DbUtil.Create(_fixture.ConnectionString);
+ var db = DbUtil.Create(_fixture.Connection);
if (delete)
{
db.Database.EnsureDeleted();
@@ -64,13 +61,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
return CreateContext();
}
- public ApplicationDbContext CreateAppContext()
- {
- var db = DbUtil.Create(_fixture.ConnectionString);
- db.Database.EnsureCreated();
- return db;
- }
-
protected override void AddUserStore(IServiceCollection services, object context = null)
{
services.AddSingleton>(new UserStore((IdentityDbContext)context));
diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreWithGenericsTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreWithGenericsTest.cs
index 951e91cabf..8e07a8dc8e 100644
--- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreWithGenericsTest.cs
+++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreWithGenericsTest.cs
@@ -8,7 +8,6 @@ using System.Linq.Expressions;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.Test;
-using Microsoft.AspNetCore.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
@@ -24,9 +23,9 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
_fixture = fixture;
}
- public ContextWithGenerics CreateContext()
+ private ContextWithGenerics CreateContext()
{
- var db = DbUtil.Create(_fixture.ConnectionString);
+ var db = DbUtil.Create(_fixture.Connection);
db.Database.EnsureCreated();
return db;
}
@@ -36,11 +35,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
return CreateContext();
}
- protected override bool ShouldSkipDbTests()
- {
- return TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows;
- }
-
protected override void AddUserStore(IServiceCollection services, object context = null)
{
services.AddSingleton>(new UserStoreWithGenerics((ContextWithGenerics)context, "TestContext"));
@@ -104,10 +98,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
[Fact]
public async Task CanAddRemoveUserClaimWithIssuer()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -136,10 +126,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
[Fact]
public async Task RemoveClaimWithIssuerOnlyAffectsUser()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
var user2 = CreateTestUser();
@@ -169,10 +155,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
[Fact]
public async Task CanReplaceUserClaimWithIssuer()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -348,4 +330,4 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
}
#endregion
-}
\ No newline at end of file
+}
diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/Utilities/ScratchDatabaseFixture.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/Utilities/ScratchDatabaseFixture.cs
index 6634a81591..39aed8910b 100644
--- a/src/Identity/EntityFrameworkCore/test/EF.Test/Utilities/ScratchDatabaseFixture.cs
+++ b/src/Identity/EntityFrameworkCore/test/EF.Test/Utilities/ScratchDatabaseFixture.cs
@@ -2,28 +2,40 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test.Utilities;
-using Microsoft.EntityFrameworkCore.Internal;
+using System.Data.Common;
+using Microsoft.Data.Sqlite;
+using Microsoft.EntityFrameworkCore;
namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
{
public class ScratchDatabaseFixture : IDisposable
{
- private readonly Lazy _testStore;
+ private readonly SqliteConnection _connection;
public ScratchDatabaseFixture()
{
- _testStore = new Lazy(() => SqlServerTestStore.CreateScratch());
+ _connection = new SqliteConnection($"DataSource=D{Guid.NewGuid()}.db");
+
+ using (var context = CreateEmptyContext())
+ {
+ context.Database.EnsureDeleted();
+ context.Database.EnsureCreated();
+ }
}
- public string ConnectionString => _testStore.Value.Connection.ConnectionString;
+ private DbContext CreateEmptyContext()
+ => new DbContext(new DbContextOptionsBuilder().UseSqlite(_connection).Options);
+
+ public DbConnection Connection => _connection;
public void Dispose()
{
- if (_testStore.IsValueCreated)
+ using (var context = CreateEmptyContext())
{
- _testStore.Value.Dispose();
+ context.Database.EnsureDeleted();
}
+
+ _connection.Dispose();
}
}
}
diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/Utilities/SqlServerTestStore.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/Utilities/SqlServerTestStore.cs
deleted file mode 100644
index dab5854282..0000000000
--- a/src/Identity/EntityFrameworkCore/test/EF.Test/Utilities/SqlServerTestStore.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-// 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.Data.Common;
-using System.Data.SqlClient;
-using System.IO;
-using System.Threading;
-
-namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test.Utilities
-{
- public class SqlServerTestStore : IDisposable
- {
- public const int CommandTimeout = 90;
-
- public static string CreateConnectionString(string name)
- {
- var connStrBuilder = new SqlConnectionStringBuilder(TestEnvironment.Config["Test:SqlServer:DefaultConnectionString"])
- {
- InitialCatalog = name
- };
-
- return connStrBuilder.ConnectionString;
- }
-
- public static SqlServerTestStore CreateScratch(bool createDatabase = true)
- => new SqlServerTestStore(GetScratchDbName()).CreateTransient(createDatabase);
-
- private SqlConnection _connection;
- private readonly string _name;
- private bool _deleteDatabase;
-
- private SqlServerTestStore(string name)
- {
- _name = name;
- }
-
- private static string GetScratchDbName()
- {
- string name;
- do
- {
- name = "Scratch_" + Guid.NewGuid();
- } while (DatabaseExists(name)
- || DatabaseFilesExist(name));
-
- return name;
- }
-
- private static void WaitForExists(SqlConnection connection)
- {
- var retryCount = 0;
- while (true)
- {
- try
- {
- connection.Open();
-
- connection.Close();
-
- return;
- }
- catch (SqlException e)
- {
- if (++retryCount >= 30
- || (e.Number != 233 && e.Number != -2 && e.Number != 4060))
- {
- throw;
- }
-
- SqlConnection.ClearPool(connection);
-
- Thread.Sleep(100);
- }
- }
- }
-
- private SqlServerTestStore CreateTransient(bool createDatabase)
- {
- _connection = new SqlConnection(CreateConnectionString(_name));
-
- if (createDatabase)
- {
- using (var master = new SqlConnection(CreateConnectionString("master")))
- {
- master.Open();
- using (var command = master.CreateCommand())
- {
- command.CommandTimeout = CommandTimeout;
- command.CommandText = $"{Environment.NewLine}CREATE DATABASE [{_name}]";
-
- command.ExecuteNonQuery();
-
- WaitForExists(_connection);
- }
- }
- _connection.Open();
- }
-
- _deleteDatabase = true;
- return this;
- }
-
- private static bool DatabaseExists(string name)
- {
- using (var master = new SqlConnection(CreateConnectionString("master")))
- {
- master.Open();
-
- using (var command = master.CreateCommand())
- {
- command.CommandTimeout = CommandTimeout;
- command.CommandText = $@"SELECT COUNT(*) FROM sys.databases WHERE name = N'{name}'";
-
- return (int) command.ExecuteScalar() > 0;
- }
- }
- }
-
- private static bool DatabaseFilesExist(string name)
- {
- var userFolder = Environment.GetEnvironmentVariable("USERPROFILE") ??
- Environment.GetEnvironmentVariable("HOME");
- return userFolder != null
- && (File.Exists(Path.Combine(userFolder, name + ".mdf"))
- || File.Exists(Path.Combine(userFolder, name + "_log.ldf")));
- }
-
- private void DeleteDatabase(string name)
- {
- using (var master = new SqlConnection(CreateConnectionString("master")))
- {
- master.Open();
-
- using (var command = master.CreateCommand())
- {
- command.CommandTimeout = CommandTimeout;
- // Query will take a few seconds if (and only if) there are active connections
-
- // SET SINGLE_USER will close any open connections that would prevent the drop
- command.CommandText
- = string.Format(@"IF EXISTS (SELECT * FROM sys.databases WHERE name = N'{0}')
- BEGIN
- ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
- DROP DATABASE [{0}];
- END", name);
-
- command.ExecuteNonQuery();
- }
- }
- }
-
- public DbConnection Connection => _connection;
-
- public void Dispose()
- {
- _connection.Dispose();
-
- if (_deleteDatabase)
- {
- DeleteDatabase(_name);
- }
- }
- }
-}
diff --git a/src/Identity/Specification.Tests/src/IdentitySpecificationTestBase.cs b/src/Identity/Specification.Tests/src/IdentitySpecificationTestBase.cs
index 9d43420682..4e67e26253 100644
--- a/src/Identity/Specification.Tests/src/IdentitySpecificationTestBase.cs
+++ b/src/Identity/Specification.Tests/src/IdentitySpecificationTestBase.cs
@@ -7,7 +7,6 @@ using System.Linq;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Xunit;
@@ -129,10 +128,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanCreateRoleTest()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
var roleName = "create" + Guid.NewGuid().ToString();
var role = CreateTestRole(roleName, useRoleNamePrefixAsRoleName: true);
@@ -169,10 +164,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task BadValidatorBlocksCreateRole()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
manager.RoleValidators.Clear();
manager.RoleValidators.Add(new AlwaysBadValidator());
@@ -189,10 +180,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanChainRoleValidators()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
manager.RoleValidators.Clear();
manager.RoleValidators.Add(new AlwaysBadValidator());
@@ -211,10 +198,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task BadValidatorBlocksRoleUpdate()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
var role = CreateTestRole("poorguy");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(role));
@@ -232,10 +215,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanDeleteRole()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
var roleName = "delete" + Guid.NewGuid().ToString();
var role = CreateTestRole(roleName, useRoleNamePrefixAsRoleName: true);
@@ -253,10 +232,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanAddRemoveRoleClaim()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
var role = CreateTestRole("ClaimsAddRemove");
var roleSafe = CreateTestRole("ClaimsAdd");
@@ -296,10 +271,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanRoleFindById()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
var role = CreateTestRole("FindByIdAsync");
Assert.Null(await manager.FindByIdAsync(await manager.GetRoleIdAsync(role)));
@@ -314,10 +285,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanRoleFindByName()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
var roleName = "FindByNameAsync" + Guid.NewGuid().ToString();
var role = CreateTestRole(roleName, useRoleNamePrefixAsRoleName: true);
@@ -334,10 +301,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanUpdateRoleName()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
var roleName = "update" + Guid.NewGuid().ToString();
var role = CreateTestRole(roleName, useRoleNamePrefixAsRoleName: true);
@@ -357,10 +320,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanQueryableRoles()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
if (manager.SupportsQueryableRoles)
{
@@ -384,10 +343,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CreateRoleFailsIfExists()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateRoleManager();
var roleName = "dupeRole" + Guid.NewGuid().ToString();
var role = CreateTestRole(roleName, useRoleNamePrefixAsRoleName: true);
@@ -405,10 +360,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanAddUsersToRole()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var context = CreateTestContext();
var manager = CreateManager(context);
var roleManager = CreateRoleManager(context);
@@ -434,11 +385,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanGetRolesForUser()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
-
var context = CreateTestContext();
var userManager = CreateManager(context);
var roleManager = CreateRoleManager(context);
@@ -477,10 +423,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task RemoveUserFromRoleWithMultipleRoles()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var context = CreateTestContext();
var userManager = CreateManager(context);
var roleManager = CreateRoleManager(context);
@@ -504,10 +446,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanRemoveUsersFromRole()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var context = CreateTestContext();
var userManager = CreateManager(context);
var roleManager = CreateRoleManager(context);
@@ -538,10 +476,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task RemoveUserNotInRoleFails()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var context = CreateTestContext();
var userMgr = CreateManager(context);
var roleMgr = CreateRoleManager(context);
@@ -562,10 +496,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task AddUserToRoleFailsIfAlreadyInRole()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var context = CreateTestContext();
var userMgr = CreateManager(context);
var roleMgr = CreateRoleManager(context);
@@ -587,10 +517,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task AddUserToRolesIgnoresDuplicates()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var context = CreateTestContext();
var userMgr = CreateManager(context);
var roleMgr = CreateRoleManager(context);
@@ -611,10 +537,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanFindRoleByNameWithManager()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var roleMgr = CreateRoleManager();
var roleName = "findRoleByNameTest" + Guid.NewGuid().ToString();
var role = CreateTestRole(roleName, useRoleNamePrefixAsRoleName: true);
@@ -629,10 +551,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanFindRoleWithManager()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var roleMgr = CreateRoleManager();
var roleName = "findRoleTest" + Guid.NewGuid().ToString();
var role = CreateTestRole(roleName, useRoleNamePrefixAsRoleName: true);
@@ -647,10 +565,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanGetUsersInRole()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var context = CreateTestContext();
var manager = CreateManager(context);
var roleManager = CreateRoleManager(context);
diff --git a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs
index b5fe50375a..9b743e4cf9 100644
--- a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs
+++ b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs
@@ -7,7 +7,6 @@ using System.Linq;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.DependencyInjection;
@@ -72,12 +71,6 @@ namespace Microsoft.AspNetCore.Identity.Test
return builder;
}
- ///
- /// If true, tests that require a database will be skipped.
- ///
- ///
- protected virtual bool ShouldSkipDbTests() => false;
-
///
/// Creates the user manager used for tests.
///
@@ -184,10 +177,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task PasswordValidatorWithNoErrorsCanBlockAddPassword()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -203,10 +192,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CreateUserWillSetCreateDateOnlyIfSupported()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -220,10 +205,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanDeleteUser()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -239,10 +220,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanUpdateUserName()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var name = Guid.NewGuid().ToString();
var user = CreateTestUser(name);
@@ -262,10 +239,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CheckSetUserNameValidatesUser()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var username = "UpdateAsync" + Guid.NewGuid().ToString();
var newUsername = "New" + Guid.NewGuid().ToString();
@@ -294,10 +267,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task SetUserNameUpdatesSecurityStamp()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var username = "UpdateAsync" + Guid.NewGuid().ToString();
var newUsername = "New" + Guid.NewGuid().ToString();
@@ -316,10 +285,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ResetAuthenticatorKeyUpdatesSecurityStamp()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var username = "Create" + Guid.NewGuid().ToString();
var user = CreateTestUser(username, useNamePrefixAsUserName: true);
@@ -336,10 +301,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CheckSetEmailValidatesUser()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.Options.User.RequireUniqueEmail = true;
manager.UserValidators.Add(new UserValidator());
@@ -363,10 +324,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanUpdatePasswordUsingHasher()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser("UpdatePassword");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
@@ -387,10 +344,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanFindById()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -404,10 +357,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task UserValidatorCanBlockCreate()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
manager.UserValidators.Clear();
@@ -423,10 +372,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task UserValidatorCanBlockUpdate()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -443,10 +388,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanChainUserValidators()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.UserValidators.Clear();
var user = CreateTestUser();
@@ -467,10 +408,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[InlineData(null)]
public async Task UserValidatorBlocksShortEmailsWhenRequiresUniqueEmail(string email)
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
manager.Options.User.RequireUniqueEmail = true;
@@ -486,10 +423,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[InlineData("bogus")]
public async Task UserValidatorBlocksInvalidEmailsWhenRequiresUniqueEmail(string email)
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser("UpdateBlocked", email);
manager.Options.User.RequireUniqueEmail = true;
@@ -503,10 +436,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task PasswordValidatorCanBlockAddPassword()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -524,10 +453,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanChainPasswordValidators()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.PasswordValidators.Clear();
manager.PasswordValidators.Add(new EmptyBadValidator());
@@ -546,10 +471,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task PasswordValidatorWithNoErrorsCanBlockChangePassword()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
@@ -565,10 +486,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task PasswordValidatorWithNoErrorsCanBlockCreateUser()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
manager.PasswordValidators.Clear();
@@ -583,10 +500,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task PasswordValidatorWithNoErrorsCanBlockResetPasswordWithStaticTokenProvider()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.Tokens.PasswordResetTokenProvider = "Static";
@@ -611,10 +524,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task PasswordValidatorCanBlockChangePassword()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
@@ -632,10 +541,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task PasswordValidatorCanBlockCreateUser()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
manager.PasswordValidators.Clear();
@@ -651,10 +556,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanCreateUserNoPassword()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var username = "CreateUserTest" + Guid.NewGuid();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(CreateTestUser(username, useNamePrefixAsUserName: true)));
@@ -674,10 +575,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanCreateUserAddLogin()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
const string provider = "ZzAuth";
const string display = "display";
@@ -700,10 +597,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanCreateUserLoginAndAddPassword()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -727,10 +620,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task AddPasswordFailsIfAlreadyHave()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "Password"));
@@ -747,10 +636,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanCreateUserAddRemoveLogin()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
var result = await manager.CreateAsync(user);
@@ -782,10 +667,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanRemovePassword()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser("CanRemovePassword");
const string password = "password";
@@ -806,10 +687,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanChangePassword()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
const string password = "password";
@@ -830,10 +707,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanAddRemoveUserClaim()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -863,10 +736,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task RemoveClaimOnlyAffectsUser()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
var user2 = CreateTestUser();
@@ -900,10 +769,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanReplaceUserClaim()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -927,10 +792,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ReplaceUserClaimOnlyAffectsUser()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
var user2 = CreateTestUser();
@@ -964,10 +825,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ChangePasswordFallsIfPasswordWrong()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
@@ -983,10 +840,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task AddDupeUserNameFails()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var username = "AddDupeUserNameFails" + Guid.NewGuid();
var user = CreateTestUser(username, useNamePrefixAsUserName: true);
@@ -1002,10 +855,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task AddDupeEmailAllowedByDefault()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser(email: "yup@yup.com");
var user2 = CreateTestUser(email: "yup@yup.com");
@@ -1021,10 +870,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task AddDupeEmailFailsWhenUniqueEmailRequired()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.Options.User.RequireUniqueEmail = true;
var user = CreateTestUser(email: "FooUser@yup.com");
@@ -1040,10 +885,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task UpdateSecurityStampActuallyChanges()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1059,10 +900,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task AddDupeLoginFails()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
var login = new UserLoginInfo("Provider", "key", "display");
@@ -1082,10 +919,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanFindByEmail()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var email = "foouser@test.com";
var manager = CreateManager();
var user = CreateTestUser(email: email);
@@ -1101,11 +934,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async virtual Task CanFindUsersViaUserQuerable()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
-
var mgr = CreateManager();
if (mgr.SupportsQueryableUsers)
{
@@ -1126,10 +954,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ConfirmEmailFalseByDefaultTest()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1166,10 +990,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanResetPasswordWithStaticTokenProvider()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.Tokens.PasswordResetTokenProvider = "Static";
@@ -1195,10 +1015,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task PasswordValidatorCanBlockResetPasswordWithStaticTokenProvider()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.Tokens.PasswordResetTokenProvider = "Static";
@@ -1225,10 +1041,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ResetPasswordWithStaticTokenProviderFailsWithWrongToken()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.Tokens.PasswordResetTokenProvider = "Static";
@@ -1251,10 +1063,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanGenerateAndVerifyUserTokenWithStaticTokenProvider()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.RegisterTokenProvider("Static", new StaticTokenProvider());
var user = CreateTestUser();
@@ -1283,10 +1091,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanConfirmEmailWithStaticToken()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.Tokens.EmailConfirmationTokenProvider = "Static";
@@ -1309,10 +1113,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ConfirmEmailWithStaticTokenFailsWithWrongToken()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.Tokens.EmailConfirmationTokenProvider = "Static";
@@ -1331,10 +1131,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ConfirmTokenFailsAfterPasswordChange()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser(namePrefix: "Test");
Assert.False(await manager.IsEmailConfirmedAsync(user));
@@ -1356,10 +1152,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task SingleFailureLockout()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
mgr.Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromHours(1);
mgr.Options.Lockout.MaxFailedAccessAttempts = 0;
@@ -1382,10 +1174,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task TwoFailureLockout()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
mgr.Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromHours(1);
mgr.Options.Lockout.MaxFailedAccessAttempts = 2;
@@ -1411,10 +1199,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ResetAccessCountPreventsLockout()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
mgr.Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromHours(1);
mgr.Options.Lockout.MaxFailedAccessAttempts = 2;
@@ -1443,10 +1227,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanEnableLockoutManuallyAndLockout()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
mgr.Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromHours(1);
mgr.Options.Lockout.AllowedForNewUsers = false;
@@ -1475,10 +1255,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task UserNotLockedOutWithNullDateTimeAndIsSetToNullDate()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
@@ -1495,10 +1271,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task LockoutFailsIfNotEnabled()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
mgr.Options.Lockout.AllowedForNewUsers = false;
var user = CreateTestUser();
@@ -1517,10 +1289,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task LockoutEndToUtcNowMinus1SecInUserShouldNotBeLockedOut()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
var user = CreateTestUser(lockoutEnd: DateTimeOffset.UtcNow.AddSeconds(-1));
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
@@ -1535,10 +1303,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task LockoutEndToUtcNowSubOneSecondWithManagerShouldNotBeLockedOut()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
@@ -1554,10 +1318,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task LockoutEndToUtcNowPlus5ShouldBeLockedOut()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
var lockoutEnd = DateTimeOffset.UtcNow.AddMinutes(5);
var user = CreateTestUser(lockoutEnd: lockoutEnd);
@@ -1573,10 +1333,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task UserLockedOutWithDateTimeLocalKindNowPlus30()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var mgr = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
@@ -1595,10 +1351,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task SetPhoneNumberTest()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser(phoneNumber: "123-456-7890");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1616,10 +1368,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanChangePhoneNumber()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser(phoneNumber: "123-456-7890");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1639,10 +1387,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ChangePhoneNumberTokenIsInt()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser(phoneNumber: "123-456-7890");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1657,10 +1401,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ChangePhoneNumberFailsWithWrongToken()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser(phoneNumber: "123-456-7890");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1693,10 +1433,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ChangePhoneNumberWithCustomProvider()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
manager.RegisterTokenProvider("Yes", new YesPhoneNumberProvider());
manager.Options.Tokens.ChangePhoneNumberTokenProvider = "Yes";
@@ -1717,10 +1453,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ChangePhoneNumberFailsWithWrongPhoneNumber()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser(phoneNumber: "123-456-7890");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1741,10 +1473,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanVerifyPhoneNumber()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1770,10 +1498,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanChangeEmail()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser("foouser");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1796,10 +1520,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanChangeEmailOnlyIfEmailSame()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser("foouser");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1824,10 +1544,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanChangeEmailWithDifferentTokenProvider()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager(context: null, services: null,
configureServices: s => s.Configure(
o => o.Tokens.ProviderMap["NewProvider2"] = new TokenProviderDescriptor(typeof(EmailTokenProvider))));
@@ -1853,10 +1569,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ChangeEmailTokensFailsAfterEmailChanged()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser("foouser");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1880,10 +1592,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ChangeEmailFailsWithWrongToken()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser("foouser");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1907,10 +1615,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task ChangeEmailFailsWithEmail()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser("foouser");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1936,10 +1640,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/1766", FlakyOn.All)]
public async Task EmailFactorFailsAfterSecurityStampChangeTest()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
string factorId = "Email"; //default
var user = CreateTestUser("foouser");
@@ -1970,10 +1670,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task EnableTwoFactorChangesSecurityStamp()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -1991,10 +1687,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task GenerateTwoFactorWithUnknownFactorProviderWillThrow()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -2020,10 +1712,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task GetValidTwoFactorTestEmptyWithNoProviders()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -2039,10 +1727,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanGetSetUpdateAndRemoveUserToken()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -2067,10 +1751,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanRedeemRecoveryCodeOnlyOnce()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -2099,10 +1779,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task RecoveryCodesInvalidAfterReplace()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -2131,10 +1807,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanGetValidTwoFactor()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -2175,10 +1847,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task PhoneFactorFailsAfterSecurityStampChangeTest()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var factorId = "Phone"; // default
var user = CreateTestUser(phoneNumber: "4251234567");
@@ -2199,10 +1867,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task VerifyTokenFromWrongTokenProviderFails()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser(phoneNumber: "4251234567");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -2219,10 +1883,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task VerifyWithWrongSmsTokenFails()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
var user = CreateTestUser(phoneNumber: "4251234567");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@@ -2237,10 +1897,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task NullableDateTimeOperationTest()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var userMgr = CreateManager();
var user = CreateTestUser(lockoutEnabled: true);
IdentityResultAssert.IsSuccess(await userMgr.CreateAsync(user));
@@ -2263,10 +1919,6 @@ namespace Microsoft.AspNetCore.Identity.Test
[Fact]
public async Task CanGetUsersWithClaims()
{
- if (ShouldSkipDbTests())
- {
- return;
- }
var manager = CreateManager();
for (int i = 0; i < 6; i++)
diff --git a/src/Identity/test/Identity.FunctionalTests/AuthorizationTests.cs b/src/Identity/test/Identity.FunctionalTests/AuthorizationTests.cs
index c4a1b43083..3ccc399bfd 100644
--- a/src/Identity/test/Identity.FunctionalTests/AuthorizationTests.cs
+++ b/src/Identity/test/Identity.FunctionalTests/AuthorizationTests.cs
@@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
where TStartup : class
where TContext : DbContext
{
- public AuthorizationTests(ServerFactory serverFactory)
+ protected AuthorizationTests(ServerFactory serverFactory)
{
ServerFactory = serverFactory;
}
diff --git a/src/Identity/test/Identity.FunctionalTests/Infrastructure/FunctionalTestsServiceCollectionExtensions.cs b/src/Identity/test/Identity.FunctionalTests/Infrastructure/FunctionalTestsServiceCollectionExtensions.cs
index 50f67cad09..9070d6ba14 100644
--- a/src/Identity/test/Identity.FunctionalTests/Infrastructure/FunctionalTestsServiceCollectionExtensions.cs
+++ b/src/Identity/test/Identity.FunctionalTests/Infrastructure/FunctionalTestsServiceCollectionExtensions.cs
@@ -2,12 +2,12 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Data.Common;
using System.Security.Claims;
using System.Threading.Tasks;
using Identity.DefaultUI.WebSite;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
@@ -18,10 +18,10 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
{
public static class FunctionalTestsServiceCollectionExtensions
{
- public static IServiceCollection SetupTestDatabase(this IServiceCollection services, string databaseName) where TContext : DbContext =>
+ public static IServiceCollection SetupTestDatabase(this IServiceCollection services, DbConnection connection) where TContext : DbContext =>
services.AddDbContext(options =>
options.ConfigureWarnings(b => b.Log(CoreEventId.ManyServiceProvidersCreatedWarning))
- .UseInMemoryDatabase(databaseName, memoryOptions => { }));
+ .UseSqlite(connection));
public static IServiceCollection SetupTestThirdPartyLogin(this IServiceCollection services) =>
services.AddAuthentication()
diff --git a/src/Identity/test/Identity.FunctionalTests/Infrastructure/ServerFactory.cs b/src/Identity/test/Identity.FunctionalTests/Infrastructure/ServerFactory.cs
index af4a6d9b81..e84840aa68 100644
--- a/src/Identity/test/Identity.FunctionalTests/Infrastructure/ServerFactory.cs
+++ b/src/Identity/test/Identity.FunctionalTests/Infrastructure/ServerFactory.cs
@@ -3,19 +3,24 @@
using System;
using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Identity.FunctionalTests
{
- public class ServerFactory: WebApplicationFactory
+ public class ServerFactory: WebApplicationFactory
where TStartup : class
where TContext : DbContext
{
+ private readonly SqliteConnection _connection
+ = new SqliteConnection($"DataSource=:memory:");
+
public ServerFactory()
{
+ _connection.Open();
+
ClientOptions.AllowAutoRedirect = false;
ClientOptions.BaseAddress = new Uri("https://localhost");
}
@@ -24,11 +29,30 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
{
base.ConfigureWebHost(builder);
builder.UseStartup();
- builder.ConfigureServices(sc => sc.SetupTestDatabase(Guid.NewGuid().ToString())
+
+ builder.ConfigureServices(sc =>
+ {
+ sc.SetupTestDatabase(_connection)
.AddMvc()
// Mark the cookie as essential for right now, as Identity uses it on
// several places to pass important data in post-redirect-get flows.
- .AddCookieTempDataProvider(o => o.Cookie.IsEssential = true));
+ .AddCookieTempDataProvider(o => o.Cookie.IsEssential = true);
+ });
+ }
+
+ public override void EnsureDatabaseCreated()
+ {
+ using (var scope = Services.CreateScope())
+ {
+ scope.ServiceProvider.GetService().Database.EnsureCreated();
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ _connection.Dispose();
+
+ base.Dispose(disposing);
}
}
}
diff --git a/src/Identity/test/Identity.FunctionalTests/LoginTests.cs b/src/Identity/test/Identity.FunctionalTests/LoginTests.cs
index dc1124a664..d49255a001 100644
--- a/src/Identity/test/Identity.FunctionalTests/LoginTests.cs
+++ b/src/Identity/test/Identity.FunctionalTests/LoginTests.cs
@@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
where TStartup : class
where TContext : DbContext
{
- public LoginTests(ServerFactory serverFactory)
+ protected LoginTests(ServerFactory serverFactory)
{
ServerFactory = serverFactory;
}
@@ -289,6 +289,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
+ ServerFactory.EnsureDatabaseCreated();
+
var client = server.CreateClient();
var newClient = server.CreateClient();
@@ -311,6 +313,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
+ ServerFactory.EnsureDatabaseCreated();
+
var client = server.CreateClient();
var resetPasswordClient = server.CreateClient();
var newClient = server.CreateClient();
diff --git a/src/Identity/test/Identity.FunctionalTests/ManagementTests.cs b/src/Identity/test/Identity.FunctionalTests/ManagementTests.cs
index 6bb5c8e64d..f370d0dec3 100644
--- a/src/Identity/test/Identity.FunctionalTests/ManagementTests.cs
+++ b/src/Identity/test/Identity.FunctionalTests/ManagementTests.cs
@@ -289,6 +289,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
.WithWebHostBuilder(whb => whb.ConfigureTestServices(ConfigureTestServices))
.CreateClient();
+ ServerFactory.EnsureDatabaseCreated();
+
var userName = $"{Guid.NewGuid()}@example.com";
var guid = Guid.NewGuid();
var email = userName;
diff --git a/src/Identity/test/Identity.FunctionalTests/Microsoft.AspNetCore.Identity.FunctionalTests.csproj b/src/Identity/test/Identity.FunctionalTests/Microsoft.AspNetCore.Identity.FunctionalTests.csproj
index 3230a236b9..b3ab76bd7d 100644
--- a/src/Identity/test/Identity.FunctionalTests/Microsoft.AspNetCore.Identity.FunctionalTests.csproj
+++ b/src/Identity/test/Identity.FunctionalTests/Microsoft.AspNetCore.Identity.FunctionalTests.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/src/Identity/test/Identity.FunctionalTests/RegistrationTests.cs b/src/Identity/test/Identity.FunctionalTests/RegistrationTests.cs
index dc07c17992..e1222ed381 100644
--- a/src/Identity/test/Identity.FunctionalTests/RegistrationTests.cs
+++ b/src/Identity/test/Identity.FunctionalTests/RegistrationTests.cs
@@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
where TStartup : class
where TContext : DbContext
{
- public RegistrationTests(ServerFactory serverFactory)
+ protected RegistrationTests(ServerFactory serverFactory)
{
ServerFactory = serverFactory;
}
@@ -31,6 +31,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices))
.CreateClient();
+ ServerFactory.EnsureDatabaseCreated();
+
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"!Test.Password1$";
@@ -49,6 +51,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
var client = server.CreateClient();
var client2 = server.CreateClient();
+ ServerFactory.EnsureDatabaseCreated();
+
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"!Test.Password1$";
@@ -81,6 +85,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
var client = server.CreateClient();
var client2 = server.CreateClient();
+ ServerFactory.EnsureDatabaseCreated();
+
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"!Test.Password1$";
@@ -102,6 +108,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices))
.CreateClient();
+ ServerFactory.EnsureDatabaseCreated();
+
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"!Test.Password1$";
@@ -121,6 +129,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices))
.CreateClient();
+ ServerFactory.EnsureDatabaseCreated();
+
var guid = Guid.NewGuid();
var userName = $"{guid}";
var email = $"{guid}@example.com";
@@ -141,6 +151,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices))
.CreateClient();
+ ServerFactory.EnsureDatabaseCreated();
+
var guid = Guid.NewGuid();
var userName = $"{guid}";
var email = $"{guid}@example.com";
@@ -162,6 +174,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices))
.CreateClient();
+ ServerFactory.EnsureDatabaseCreated();
+
var guid = Guid.NewGuid();
var userName = $"{guid}";
var email = $"{guid}@example.com";
diff --git a/src/Identity/test/InMemory.Test/InMemoryUserStoreTest.cs b/src/Identity/test/InMemory.Test/InMemoryUserStoreTest.cs
index aa9c992523..ac7a08caa6 100644
--- a/src/Identity/test/InMemory.Test/InMemoryUserStoreTest.cs
+++ b/src/Identity/test/InMemory.Test/InMemoryUserStoreTest.cs
@@ -4,11 +4,13 @@
using System;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Identity.Test;
+using Microsoft.Data.Sqlite;
using Microsoft.Extensions.DependencyInjection;
+using Xunit;
namespace Microsoft.AspNetCore.Identity.InMemory.Test
{
- public class InMemoryUserStoreTest : UserManagerSpecificationTestBase
+ public class InMemoryUserStoreTest : UserManagerSpecificationTestBase, IClassFixture
{
protected override object CreateTestContext()
{
@@ -41,5 +43,22 @@ namespace Microsoft.AspNetCore.Identity.InMemory.Test
protected override Expression> UserNameEqualsPredicate(string userName) => u => u.UserName == userName;
protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName);
+
+ public class Fixture : IDisposable
+ {
+ private readonly SqliteConnection _connection
+ = new SqliteConnection($"DataSource=:memory:");
+
+ public Fixture()
+ {
+ _connection.Open();
+ }
+
+ public void Dispose()
+ {
+ _connection.Close();
+ _connection.Dispose();
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/src/Identity/test/InMemory.Test/Microsoft.AspNetCore.Identity.InMemory.Test.csproj b/src/Identity/test/InMemory.Test/Microsoft.AspNetCore.Identity.InMemory.Test.csproj
index 8f4c117c4e..4026796ab7 100644
--- a/src/Identity/test/InMemory.Test/Microsoft.AspNetCore.Identity.InMemory.Test.csproj
+++ b/src/Identity/test/InMemory.Test/Microsoft.AspNetCore.Identity.InMemory.Test.csproj
@@ -1,4 +1,4 @@
-
+
netcoreapp3.0
@@ -14,6 +14,7 @@
+
diff --git a/src/Mvc/Mvc.Testing/ref/Microsoft.AspNetCore.Mvc.Testing.netcoreapp3.0.cs b/src/Mvc/Mvc.Testing/ref/Microsoft.AspNetCore.Mvc.Testing.netcoreapp3.0.cs
index 069eae8180..01c33165e6 100644
--- a/src/Mvc/Mvc.Testing/ref/Microsoft.AspNetCore.Mvc.Testing.netcoreapp3.0.cs
+++ b/src/Mvc/Mvc.Testing/ref/Microsoft.AspNetCore.Mvc.Testing.netcoreapp3.0.cs
@@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.Testing
protected virtual Microsoft.AspNetCore.Hosting.IWebHostBuilder CreateWebHostBuilder() { throw null; }
public void Dispose() { }
protected virtual void Dispose(bool disposing) { }
+ public virtual void EnsureDatabaseCreated() { }
~WebApplicationFactory() { }
protected virtual System.Collections.Generic.IEnumerable GetTestAssemblies() { throw null; }
public Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory WithWebHostBuilder(System.Action configuration) { throw null; }
diff --git a/src/Mvc/Mvc.Testing/src/WebApplicationFactory.cs b/src/Mvc/Mvc.Testing/src/WebApplicationFactory.cs
index d9d9072cb9..43e8b90f9a 100644
--- a/src/Mvc/Mvc.Testing/src/WebApplicationFactory.cs
+++ b/src/Mvc/Mvc.Testing/src/WebApplicationFactory.cs
@@ -162,6 +162,12 @@ namespace Microsoft.AspNetCore.Mvc.Testing
SetContentRoot(builder);
_configuration(builder);
_server = CreateServer(builder);
+
+ EnsureDatabaseCreated();
+ }
+
+ public virtual void EnsureDatabaseCreated()
+ {
}
private void SetContentRoot(IWebHostBuilder builder)
From 166851df325364538c0157d33609f373d8fd6da2 Mon Sep 17 00:00:00 2001
From: John Luo
Date: Thu, 23 May 2019 17:53:11 -0700
Subject: [PATCH 07/95] Make it so Helix runs can be rerun and preserve history
(#10457)
* Make it so Helix runs can be rerun and preserve history
Addresses https://github.com/aspnet/AspNetCore/issues/8235
* Update eng/helix/helix.proj
Co-Authored-By: Nate McMaster
---
eng/helix/helix.proj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eng/helix/helix.proj b/eng/helix/helix.proj
index 9274e5a6df..df0567251a 100644
--- a/eng/helix/helix.proj
+++ b/eng/helix/helix.proj
@@ -19,7 +19,7 @@
ci
aspnetcore
- $(BUILD_BUILDNUMBER)
+ $(BUILD_BUILDNUMBER).$([System.DateTime]::Now.ToString('HH.mm'))
true
true
true
From 3f9f40630102ceff0fbe27a84f662cbf6c0bea43 Mon Sep 17 00:00:00 2001
From: =
Date: Thu, 23 May 2019 18:04:26 -0700
Subject: [PATCH 08/95] Revert "Make it so Helix runs can be rerun and preserve
history (#10457)"
This reverts commit 166851df325364538c0157d33609f373d8fd6da2.
---
eng/helix/helix.proj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eng/helix/helix.proj b/eng/helix/helix.proj
index df0567251a..9274e5a6df 100644
--- a/eng/helix/helix.proj
+++ b/eng/helix/helix.proj
@@ -19,7 +19,7 @@
ci
aspnetcore
- $(BUILD_BUILDNUMBER).$([System.DateTime]::Now.ToString('HH.mm'))
+ $(BUILD_BUILDNUMBER)
true
true
true
From 2c70498c136a13b12005e9afbad727091730709a Mon Sep 17 00:00:00 2001
From: John Luo
Date: Thu, 23 May 2019 20:07:39 -0700
Subject: [PATCH 09/95] Fix TLS protocols used in tests (#10483)
---
.../Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs
index 30847af463..00602983e4 100644
--- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs
+++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs
@@ -408,7 +408,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
using (var sslStream = new SslStream(connection.Stream, true, (sender, certificate, chain, errors) => true))
{
await sslStream.AuthenticateAsClientAsync("127.0.0.1", clientCertificates: null,
- enabledSslProtocols: SslProtocols.None,
+ enabledSslProtocols: SslProtocols.Tls11 | SslProtocols.Tls12,
checkCertificateRevocation: false);
}
}
@@ -447,7 +447,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
using (var sslStream = new SslStream(connection.Stream, true, (sender, certificate, chain, errors) => true))
{
await sslStream.AuthenticateAsClientAsync("127.0.0.1", clientCertificates: null,
- enabledSslProtocols: SslProtocols.None,
+ enabledSslProtocols: SslProtocols.Tls11 | SslProtocols.Tls12,
checkCertificateRevocation: false);
}
}
From 3bb9cda189dabfbd1b992b20a738d9479fd5a58b Mon Sep 17 00:00:00 2001
From: Doug Bunting
Date: Thu, 23 May 2019 22:14:40 -0700
Subject: [PATCH 10/95] Perform symbol publication using
Microsoft.SymbolUploader.Build.Task (#10358)
- aspnet/AspNetCore-Internal#2126
- allow release pipeline to publish symbols on all builds: #10113
- add new project that publishes symbols to MSDL and SymWeb
- release pipeline prepares then restores and builds the new project
- expire symbols after 10 years (or so)
nits:
- add `$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE` to ci.yml
---
.azure/pipelines/ci.yml | 4 +++
eng/PublishSymbols.proj | 62 +++++++++++++++++++++++++++++++++++++++++
eng/Versions.props | 1 +
3 files changed, 67 insertions(+)
create mode 100644 eng/PublishSymbols.proj
diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml
index 755ffe182e..900b033f83 100644
--- a/.azure/pipelines/ci.yml
+++ b/.azure/pipelines/ci.yml
@@ -17,6 +17,10 @@ pr:
include:
- '*'
+variables:
+- name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE
+ value: true
+
jobs:
- template: jobs/default-build.yml
parameters:
diff --git a/eng/PublishSymbols.proj b/eng/PublishSymbols.proj
new file mode 100644
index 0000000000..dd2c968566
--- /dev/null
+++ b/eng/PublishSymbols.proj
@@ -0,0 +1,62 @@
+
+
+
+ netcoreapp3.0
+ true
+ artifacts\manifests\
+ true
+
+
+ 3650
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eng/Versions.props b/eng/Versions.props
index 78e4d044b8..7fdd2d0d75 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -140,6 +140,7 @@
15.9.0
1.0.0-beta2-18618-05
1.0.0-beta2-18618-05
+ 1.0.0-beta-64023-03
4.5.0
4.4.0
From 405d8bbdc91bd7cda376cf6f17cea664d976b8c1 Mon Sep 17 00:00:00 2001
From: Andrew Au
Date: Thu, 23 May 2019 13:33:07 -0700
Subject: [PATCH 11/95] Turn SETLOCAL on so that we don't accumulate in the
PATH
---
startvs.cmd | 1 +
1 file changed, 1 insertion(+)
diff --git a/startvs.cmd b/startvs.cmd
index d15843640b..dd9c798c5b 100644
--- a/startvs.cmd
+++ b/startvs.cmd
@@ -1,4 +1,5 @@
@ECHO OFF
+SETLOCAL
:: This command launches a Visual Studio solution with environment variables required to use a local version of the .NET Core SDK.
From d18a033b1ee6d923a72d440718c5d496b57c2ffc Mon Sep 17 00:00:00 2001
From: Steve Sanderson
Date: Fri, 24 May 2019 15:28:37 +0100
Subject: [PATCH 12/95] Integrate AuthorizeView with actual authorization
(#10487)
---
.../src/Hosting/WebAssemblyHostBuilder.cs | 7 +
.../src/Services/WebAssemblyConsoleLogger.cs | 34 +++
.../src/Services/WebAssemblyLoggerFactory.cs | 23 ++
.../Microsoft.AspNetCore.Components.csproj | 1 +
...etCore.Components.netstandard2.0.Manual.cs | 8 +-
.../src/Auth/AuthorizeDataAdapter.cs | 39 +++
.../Components/src/Auth/AuthorizeView.razor | 49 +++-
.../Microsoft.AspNetCore.Components.csproj | 1 +
.../Components/test/Auth/AuthorizeViewTest.cs | 275 ++++++++++++++++--
src/Components/Shared/test/TestRenderer.cs | 2 +-
src/Components/test/E2ETest/Tests/AuthTest.cs | 52 +++-
.../AuthTest/AuthorizeViewCases.razor | 34 ++-
.../ClientSideAuthenticationStateData.cs | 2 +-
.../ServerAuthenticationStateProvider.cs | 2 +-
.../test/testassets/BasicTestApp/Startup.cs | 6 +
.../TestServer/Controllers/UserController.cs | 20 +-
.../TestServer/Pages/Authentication.cshtml | 19 +-
.../test/testassets/TestServer/Startup.cs | 6 +
18 files changed, 529 insertions(+), 51 deletions(-)
create mode 100644 src/Components/Blazor/Blazor/src/Services/WebAssemblyConsoleLogger.cs
create mode 100644 src/Components/Blazor/Blazor/src/Services/WebAssemblyLoggerFactory.cs
create mode 100644 src/Components/Components/src/Auth/AuthorizeDataAdapter.cs
diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs
index 8cf720e1ca..0b741cbd22 100644
--- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs
+++ b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs
@@ -8,6 +8,8 @@ using Microsoft.AspNetCore.Blazor.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
namespace Microsoft.AspNetCore.Blazor.Hosting
@@ -92,6 +94,7 @@ namespace Microsoft.AspNetCore.Blazor.Hosting
services.AddSingleton();
services.AddSingleton(WebAssemblyUriHelper.Instance);
services.AddSingleton(WebAssemblyNavigationInterception.Instance);
+ services.AddSingleton();
services.AddSingleton(s =>
{
// Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
@@ -102,6 +105,10 @@ namespace Microsoft.AspNetCore.Blazor.Hosting
};
});
+ // Needed for authorization
+ services.AddOptions();
+ services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(WebAssemblyConsoleLogger<>)));
+
foreach (var configureServicesAction in _configureServicesActions)
{
configureServicesAction(_BrowserHostBuilderContext, services);
diff --git a/src/Components/Blazor/Blazor/src/Services/WebAssemblyConsoleLogger.cs b/src/Components/Blazor/Blazor/src/Services/WebAssemblyConsoleLogger.cs
new file mode 100644
index 0000000000..c86c1cf30b
--- /dev/null
+++ b/src/Components/Blazor/Blazor/src/Services/WebAssemblyConsoleLogger.cs
@@ -0,0 +1,34 @@
+// 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 Microsoft.Extensions.Logging;
+
+namespace Microsoft.AspNetCore.Blazor.Services
+{
+ internal class WebAssemblyConsoleLogger : ILogger, ILogger
+ {
+ public IDisposable BeginScope(TState state)
+ {
+ return NoOpDisposable.Instance;
+ }
+
+ public bool IsEnabled(LogLevel logLevel)
+ {
+ return logLevel >= LogLevel.Warning;
+ }
+
+ public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter)
+ {
+ var formattedMessage = formatter(state, exception);
+ Console.WriteLine($"[{logLevel}] {formattedMessage}");
+ }
+
+ private class NoOpDisposable : IDisposable
+ {
+ public static NoOpDisposable Instance = new NoOpDisposable();
+
+ public void Dispose() { }
+ }
+ }
+}
diff --git a/src/Components/Blazor/Blazor/src/Services/WebAssemblyLoggerFactory.cs b/src/Components/Blazor/Blazor/src/Services/WebAssemblyLoggerFactory.cs
new file mode 100644
index 0000000000..73458387e7
--- /dev/null
+++ b/src/Components/Blazor/Blazor/src/Services/WebAssemblyLoggerFactory.cs
@@ -0,0 +1,23 @@
+// 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.Extensions.Logging;
+
+namespace Microsoft.AspNetCore.Blazor.Services
+{
+ internal class WebAssemblyLoggerFactory : ILoggerFactory
+ {
+ public void AddProvider(ILoggerProvider provider)
+ {
+ // No-op
+ }
+
+ public ILogger CreateLogger(string categoryName)
+ => new WebAssemblyConsoleLogger();
+
+ public void Dispose()
+ {
+ // No-op
+ }
+ }
+}
diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.csproj b/src/Components/Components/ref/Microsoft.AspNetCore.Components.csproj
index bb08a3ecfe..4e878d13e3 100644
--- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.csproj
+++ b/src/Components/Components/ref/Microsoft.AspNetCore.Components.csproj
@@ -5,6 +5,7 @@
+
diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs
index 72db875d48..73ee830f5c 100644
--- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs
+++ b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs
@@ -59,7 +59,13 @@ namespace Microsoft.AspNetCore.Components
[Microsoft.AspNetCore.Components.ParameterAttribute]
public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
- public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } }
+ public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } }
+ [Microsoft.AspNetCore.Components.ParameterAttribute]
+ public string Policy { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } }
+ [Microsoft.AspNetCore.Components.ParameterAttribute]
+ public string Roles { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } }
+ [Microsoft.AspNetCore.Components.ParameterAttribute]
+ public object Resource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { }
[System.Diagnostics.DebuggerStepThroughAttribute]
protected override System.Threading.Tasks.Task OnParametersSetAsync() { throw null; }
diff --git a/src/Components/Components/src/Auth/AuthorizeDataAdapter.cs b/src/Components/Components/src/Auth/AuthorizeDataAdapter.cs
new file mode 100644
index 0000000000..3da3e76261
--- /dev/null
+++ b/src/Components/Components/src/Auth/AuthorizeDataAdapter.cs
@@ -0,0 +1,39 @@
+// 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 Microsoft.AspNetCore.Authorization;
+
+namespace Microsoft.AspNetCore.Components
+{
+ // This is so the AuthorizeView can avoid implementing IAuthorizeData (even privately)
+ internal class AuthorizeDataAdapter : IAuthorizeData
+ {
+ private readonly AuthorizeView _component;
+
+ public AuthorizeDataAdapter(AuthorizeView component)
+ {
+ _component = component ?? throw new ArgumentNullException(nameof(component));
+ }
+
+ public string Policy
+ {
+ get => _component.Policy;
+ set => throw new NotSupportedException();
+ }
+
+ public string Roles
+ {
+ get => _component.Roles;
+ set => throw new NotSupportedException();
+ }
+
+ // AuthorizeView doesn't expose any such parameter, as it wouldn't be used anyway,
+ // since we already have the ClaimsPrincipal by the time AuthorizeView gets involved.
+ public string AuthenticationSchemes
+ {
+ get => null;
+ set => throw new NotSupportedException();
+ }
+ }
+}
diff --git a/src/Components/Components/src/Auth/AuthorizeView.razor b/src/Components/Components/src/Auth/AuthorizeView.razor
index ae7b1682d5..0514ba3f9c 100644
--- a/src/Components/Components/src/Auth/AuthorizeView.razor
+++ b/src/Components/Components/src/Auth/AuthorizeView.razor
@@ -1,20 +1,26 @@
@namespace Microsoft.AspNetCore.Components
+@using System.Security.Claims
+@using Microsoft.AspNetCore.Authorization
+@inject IAuthorizationService AuthorizationService
+@inject IAuthorizationPolicyProvider AuthorizationPolicyProvider
@if (currentAuthenticationState == null)
{
@Authorizing
}
-else if (IsAuthorized())
+else if (isAuthorized)
{
@((Authorized ?? ChildContent)?.Invoke(currentAuthenticationState))
}
else
{
- @NotAuthorized
+ @(NotAuthorized?.Invoke(currentAuthenticationState))
}
@functions {
+ private IAuthorizeData[] selfAsAuthorizeData;
private AuthenticationState currentAuthenticationState;
+ private bool isAuthorized;
[CascadingParameter] private Task AuthenticationState { get; set; }
@@ -26,7 +32,7 @@ else
///
/// The content that will be displayed if the user is not authorized.
///
- [Parameter] public RenderFragment NotAuthorized { get; private set; }
+ [Parameter] public RenderFragment NotAuthorized { get; private set; }
///
/// The content that will be displayed if the user is authorized.
@@ -39,6 +45,29 @@ else
///
[Parameter] public RenderFragment Authorizing { get; private set; }
+ ///
+ /// The policy name that determines whether the content can be displayed.
+ ///
+ [Parameter] public string Policy { get; private set; }
+
+ ///
+ /// A comma delimited list of roles that are allowed to display the content.
+ ///
+ [Parameter] public string Roles { get; private set; }
+
+ ///
+ /// The resource to which access is being controlled.
+ ///
+ [Parameter] public object Resource { get; private set; }
+
+ protected override void OnInit()
+ {
+ selfAsAuthorizeData = new[]
+ {
+ new AuthorizeDataAdapter((AuthorizeView)(object)this)
+ };
+ }
+
protected override async Task OnParametersSetAsync()
{
// We allow 'ChildContent' for convenience in basic cases, and 'Authorized' for symmetry
@@ -54,15 +83,17 @@ else
currentAuthenticationState = null;
// Then render in completed state
+ // Importantly, we *don't* call StateHasChanged between the following async steps,
+ // otherwise we'd display an incorrect UI state while waiting for IsAuthorizedAsync
currentAuthenticationState = await AuthenticationState;
+ isAuthorized = await IsAuthorizedAsync(currentAuthenticationState.User);
}
- private bool IsAuthorized()
+ private async Task IsAuthorizedAsync(ClaimsPrincipal user)
{
- // TODO: Support various authorization condition parameters, equivalent to those offered
- // by the [Authorize] attribute, e.g., "Roles" and "Policy". This is on hold until we're
- // able to reference the policy evaluator APIs from this package.
-
- return currentAuthenticationState.User?.Identity?.IsAuthenticated == true;
+ var policy = await AuthorizationPolicy.CombineAsync(
+ AuthorizationPolicyProvider, selfAsAuthorizeData);
+ var result = await AuthorizationService.AuthorizeAsync(user, Resource, policy);
+ return result.Succeeded;
}
}
diff --git a/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj b/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj
index 46121def31..abdf16892e 100644
--- a/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj
+++ b/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj
@@ -10,6 +10,7 @@
+
diff --git a/src/Components/Components/test/Auth/AuthorizeViewTest.cs b/src/Components/Components/test/Auth/AuthorizeViewTest.cs
index 5617c3b32d..60c3f445d6 100644
--- a/src/Components/Components/test/Auth/AuthorizeViewTest.cs
+++ b/src/Components/Components/test/Auth/AuthorizeViewTest.cs
@@ -2,14 +2,18 @@
// 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.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers;
+using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace Microsoft.AspNetCore.Components
@@ -24,7 +28,8 @@ namespace Microsoft.AspNetCore.Components
public void RendersNothingIfNotAuthorized()
{
// Arrange
- var renderer = new TestRenderer();
+ var authorizationService = new TestAuthorizationService();
+ var renderer = CreateTestRenderer(authorizationService);
var rootComponent = WrapInAuthorizeView(
childContent:
context => builder => builder.AddContent(0, "This should not be rendered"));
@@ -36,18 +41,27 @@ namespace Microsoft.AspNetCore.Components
// Assert
var diff = renderer.Batches.Single().GetComponentDiffs().Single();
Assert.Empty(diff.Edits);
+
+ // Assert: The IAuthorizationService was given expected criteria
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Null(call.user.Identity);
+ Assert.Null(call.resource);
+ Assert.Collection(call.requirements,
+ req => Assert.IsType(req));
+ });
}
[Fact]
public void RendersNotAuthorizedContentIfNotAuthorized()
{
// Arrange
- var renderer = new TestRenderer();
+ var authorizationService = new TestAuthorizationService();
+ var renderer = CreateTestRenderer(authorizationService);
var rootComponent = WrapInAuthorizeView(
- childContent:
- context => builder => builder.AddContent(0, "This should not be rendered"),
notAuthorizedContent:
- builder => builder.AddContent(0, "You are not authorized"));
+ context => builder => builder.AddContent(0, $"You are not authorized, even though we know you are {context.User.Identity.Name}"));
+ rootComponent.AuthenticationState = CreateAuthenticationState("Nellie");
// Act
renderer.AssignRootComponentId(rootComponent);
@@ -60,7 +74,16 @@ namespace Microsoft.AspNetCore.Components
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
AssertFrame.Text(
renderer.Batches.Single().ReferenceFrames[edit.ReferenceFrameIndex],
- "You are not authorized");
+ "You are not authorized, even though we know you are Nellie");
+ });
+
+ // Assert: The IAuthorizationService was given expected criteria
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Equal("Nellie", call.user.Identity.Name);
+ Assert.Null(call.resource);
+ Assert.Collection(call.requirements,
+ req => Assert.IsType(req));
});
}
@@ -68,7 +91,9 @@ namespace Microsoft.AspNetCore.Components
public void RendersNothingIfAuthorizedButNoChildContentOrAuthorizedContentProvided()
{
// Arrange
- var renderer = new TestRenderer();
+ var authorizationService = new TestAuthorizationService();
+ authorizationService.NextResult = AuthorizationResult.Success();
+ var renderer = CreateTestRenderer(authorizationService);
var rootComponent = WrapInAuthorizeView();
rootComponent.AuthenticationState = CreateAuthenticationState("Nellie");
@@ -79,13 +104,24 @@ namespace Microsoft.AspNetCore.Components
// Assert
var diff = renderer.Batches.Single().GetComponentDiffs().Single();
Assert.Empty(diff.Edits);
+
+ // Assert: The IAuthorizationService was given expected criteria
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Equal("Nellie", call.user.Identity.Name);
+ Assert.Null(call.resource);
+ Assert.Collection(call.requirements,
+ req => Assert.IsType(req));
+ });
}
[Fact]
public void RendersChildContentIfAuthorized()
{
// Arrange
- var renderer = new TestRenderer();
+ var authorizationService = new TestAuthorizationService();
+ authorizationService.NextResult = AuthorizationResult.Success();
+ var renderer = CreateTestRenderer(authorizationService);
var rootComponent = WrapInAuthorizeView(
childContent: context => builder =>
builder.AddContent(0, $"You are authenticated as {context.User.Identity.Name}"));
@@ -104,13 +140,24 @@ namespace Microsoft.AspNetCore.Components
renderer.Batches.Single().ReferenceFrames[edit.ReferenceFrameIndex],
"You are authenticated as Nellie");
});
+
+ // Assert: The IAuthorizationService was given expected criteria
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Equal("Nellie", call.user.Identity.Name);
+ Assert.Null(call.resource);
+ Assert.Collection(call.requirements,
+ req => Assert.IsType(req));
+ });
}
[Fact]
public void RendersAuthorizedContentIfAuthorized()
{
// Arrange
- var renderer = new TestRenderer();
+ var authorizationService = new TestAuthorizationService();
+ authorizationService.NextResult = AuthorizationResult.Success();
+ var renderer = CreateTestRenderer(authorizationService);
var rootComponent = WrapInAuthorizeView(
authorizedContent: context => builder =>
builder.AddContent(0, $"You are authenticated as {context.User.Identity.Name}"));
@@ -129,13 +176,24 @@ namespace Microsoft.AspNetCore.Components
renderer.Batches.Single().ReferenceFrames[edit.ReferenceFrameIndex],
"You are authenticated as Nellie");
});
+
+ // Assert: The IAuthorizationService was given expected criteria
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Equal("Nellie", call.user.Identity.Name);
+ Assert.Null(call.resource);
+ Assert.Collection(call.requirements,
+ req => Assert.IsType(req));
+ });
}
[Fact]
public void RespondsToChangeInAuthorizationState()
{
// Arrange
- var renderer = new TestRenderer();
+ var authorizationService = new TestAuthorizationService();
+ authorizationService.NextResult = AuthorizationResult.Success();
+ var renderer = CreateTestRenderer(authorizationService);
var rootComponent = WrapInAuthorizeView(
childContent: context => builder =>
builder.AddContent(0, $"You are authenticated as {context.User.Identity.Name}"));
@@ -147,6 +205,7 @@ namespace Microsoft.AspNetCore.Components
rootComponent.TriggerRender();
var authorizeViewComponentId = renderer.Batches.Single()
.GetComponentFrames().Single().ComponentId;
+ authorizationService.AuthorizeCalls.Clear();
// Act
rootComponent.AuthenticationState = CreateAuthenticationState("Ronaldo");
@@ -164,13 +223,23 @@ namespace Microsoft.AspNetCore.Components
batch.ReferenceFrames[edit.ReferenceFrameIndex],
"You are authenticated as Ronaldo");
});
+
+ // Assert: The IAuthorizationService was given expected criteria
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Equal("Ronaldo", call.user.Identity.Name);
+ Assert.Null(call.resource);
+ Assert.Collection(call.requirements,
+ req => Assert.IsType(req));
+ });
}
[Fact]
public void ThrowsIfBothChildContentAndAuthorizedContentProvided()
{
// Arrange
- var renderer = new TestRenderer();
+ var authorizationService = new TestAuthorizationService();
+ var renderer = CreateTestRenderer(authorizationService);
var rootComponent = WrapInAuthorizeView(
authorizedContent: context => builder => { },
childContent: context => builder => { });
@@ -187,12 +256,12 @@ namespace Microsoft.AspNetCore.Components
{
// Arrange
var @event = new ManualResetEventSlim();
- var renderer = new TestRenderer()
- {
- OnUpdateDisplayComplete = () => { @event.Set(); },
- };
+ var authorizationService = new TestAuthorizationService();
+ var renderer = CreateTestRenderer(authorizationService);
+ renderer.OnUpdateDisplayComplete = () => { @event.Set(); };
var rootComponent = WrapInAuthorizeView(
- notAuthorizedContent: builder => builder.AddContent(0, "You are not authorized"));
+ notAuthorizedContent:
+ context => builder => builder.AddContent(0, "You are not authorized"));
var authTcs = new TaskCompletionSource();
rootComponent.AuthenticationState = authTcs.Task;
@@ -228,10 +297,10 @@ namespace Microsoft.AspNetCore.Components
{
// Arrange
var @event = new ManualResetEventSlim();
- var renderer = new TestRenderer()
- {
- OnUpdateDisplayComplete = () => { @event.Set(); },
- };
+ var authorizationService = new TestAuthorizationService();
+ authorizationService.NextResult = AuthorizationResult.Success();
+ var renderer = CreateTestRenderer(authorizationService);
+ renderer.OnUpdateDisplayComplete = () => { @event.Set(); };
var rootComponent = WrapInAuthorizeView(
authorizingContent: builder => builder.AddContent(0, "Auth pending..."),
authorizedContent: context => builder => builder.AddContent(0, $"Hello, {context.User.Identity.Name}!"));
@@ -276,13 +345,96 @@ namespace Microsoft.AspNetCore.Components
batch2.ReferenceFrames[edit.ReferenceFrameIndex],
"Hello, Monsieur!");
});
+
+ // Assert: The IAuthorizationService was given expected criteria
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Equal("Monsieur", call.user.Identity.Name);
+ Assert.Null(call.resource);
+ Assert.Collection(call.requirements,
+ req => Assert.IsType(req));
+ });
+ }
+
+ [Fact]
+ public void IncludesPolicyInAuthorizeCall()
+ {
+ // Arrange
+ var authorizationService = new TestAuthorizationService();
+ var renderer = CreateTestRenderer(authorizationService);
+ var rootComponent = WrapInAuthorizeView(policy: "MyTestPolicy");
+ rootComponent.AuthenticationState = CreateAuthenticationState("Nellie");
+
+ // Act
+ renderer.AssignRootComponentId(rootComponent);
+ rootComponent.TriggerRender();
+
+ // Assert
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Equal("Nellie", call.user.Identity.Name);
+ Assert.Null(call.resource);
+ Assert.Collection(call.requirements,
+ req => Assert.Equal("MyTestPolicy", ((TestPolicyRequirement)req).PolicyName));
+ });
+ }
+
+ [Fact]
+ public void IncludesRolesInAuthorizeCall()
+ {
+ // Arrange
+ var authorizationService = new TestAuthorizationService();
+ var renderer = CreateTestRenderer(authorizationService);
+ var rootComponent = WrapInAuthorizeView(roles: "SuperTestRole1, SuperTestRole2");
+ rootComponent.AuthenticationState = CreateAuthenticationState("Nellie");
+
+ // Act
+ renderer.AssignRootComponentId(rootComponent);
+ rootComponent.TriggerRender();
+
+ // Assert
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Equal("Nellie", call.user.Identity.Name);
+ Assert.Null(call.resource);
+ Assert.Collection(call.requirements, req => Assert.Equal(
+ new[] { "SuperTestRole1", "SuperTestRole2" },
+ ((RolesAuthorizationRequirement)req).AllowedRoles));
+ });
+ }
+
+ [Fact]
+ public void IncludesResourceInAuthorizeCall()
+ {
+ // Arrange
+ var authorizationService = new TestAuthorizationService();
+ var renderer = CreateTestRenderer(authorizationService);
+ var resource = new object();
+ var rootComponent = WrapInAuthorizeView(resource: resource);
+ rootComponent.AuthenticationState = CreateAuthenticationState("Nellie");
+
+ // Act
+ renderer.AssignRootComponentId(rootComponent);
+ rootComponent.TriggerRender();
+
+ // Assert
+ Assert.Collection(authorizationService.AuthorizeCalls, call =>
+ {
+ Assert.Equal("Nellie", call.user.Identity.Name);
+ Assert.Same(resource, call.resource);
+ Assert.Collection(call.requirements, req =>
+ Assert.IsType(req));
+ });
}
private static TestAuthStateProviderComponent WrapInAuthorizeView(
RenderFragment childContent = null,
RenderFragment authorizedContent = null,
- RenderFragment notAuthorizedContent = null,
- RenderFragment authorizingContent = null)
+ RenderFragment notAuthorizedContent = null,
+ RenderFragment authorizingContent = null,
+ string policy = null,
+ string roles = null,
+ object resource = null)
{
return new TestAuthStateProviderComponent(builder =>
{
@@ -291,6 +443,9 @@ namespace Microsoft.AspNetCore.Components
builder.AddAttribute(2, nameof(AuthorizeView.Authorized), authorizedContent);
builder.AddAttribute(3, nameof(AuthorizeView.NotAuthorized), notAuthorizedContent);
builder.AddAttribute(4, nameof(AuthorizeView.Authorizing), authorizingContent);
+ builder.AddAttribute(5, nameof(AuthorizeView.Policy), policy);
+ builder.AddAttribute(6, nameof(AuthorizeView.Roles), roles);
+ builder.AddAttribute(7, nameof(AuthorizeView.Resource), resource);
builder.CloseComponent();
});
}
@@ -311,11 +466,31 @@ namespace Microsoft.AspNetCore.Components
{
builder.OpenComponent>>(0);
builder.AddAttribute(1, nameof(CascadingValue>.Value), AuthenticationState);
- builder.AddAttribute(2, RenderTreeBuilder.ChildContent, _childContent);
+ builder.AddAttribute(2, RenderTreeBuilder.ChildContent, (RenderFragment)(builder =>
+ {
+ builder.OpenComponent(0);
+ builder.AddAttribute(1, RenderTreeBuilder.ChildContent, _childContent);
+ builder.CloseComponent();
+ }));
builder.CloseComponent();
}
}
+ // This is useful to show that the reason why a CascadingValue refreshes is because the
+ // value itself changed, not just that we're re-rendering the entire tree and have to
+ // recurse into all descendants because we're passing ChildContent
+ class NeverReRenderComponent : ComponentBase
+ {
+ [Parameter] RenderFragment ChildContent { get; set; }
+
+ protected override bool ShouldRender() => false;
+
+ protected override void BuildRenderTree(RenderTreeBuilder builder)
+ {
+ builder.AddContent(0, ChildContent);
+ }
+ }
+
public static Task CreateAuthenticationState(string username)
=> Task.FromResult(new AuthenticationState(
new ClaimsPrincipal(new TestIdentity { Name = username })));
@@ -328,5 +503,59 @@ namespace Microsoft.AspNetCore.Components
public string Name { get; set; }
}
+
+ public TestRenderer CreateTestRenderer(IAuthorizationService authorizationService)
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSingleton(authorizationService);
+ serviceCollection.AddSingleton(new TestAuthorizationPolicyProvider());
+ return new TestRenderer(serviceCollection.BuildServiceProvider());
+ }
+
+ private class TestAuthorizationService : IAuthorizationService
+ {
+ public AuthorizationResult NextResult { get; set; }
+ = AuthorizationResult.Failed();
+
+ public List<(ClaimsPrincipal user, object resource, IEnumerable requirements)> AuthorizeCalls { get; }
+ = new List<(ClaimsPrincipal user, object resource, IEnumerable requirements)>();
+
+ public Task AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable requirements)
+ {
+ AuthorizeCalls.Add((user, resource, requirements));
+
+ // The TestAuthorizationService doesn't actually apply any authorization requirements
+ // It just returns the specified NextResult, since we're not trying to test the logic
+ // in DefaultAuthorizationService or similar here. So it's up to tests to set a desired
+ // NextResult and assert that the expected criteria were passed by inspecting AuthorizeCalls.
+ return Task.FromResult(NextResult);
+ }
+
+ public Task AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName)
+ => throw new NotImplementedException();
+ }
+
+ private class TestAuthorizationPolicyProvider : IAuthorizationPolicyProvider
+ {
+ private readonly AuthorizationOptions options = new AuthorizationOptions();
+
+ public Task GetDefaultPolicyAsync()
+ => Task.FromResult(options.DefaultPolicy);
+
+ public Task GetFallbackPolicyAsync()
+ => Task.FromResult(options.FallbackPolicy);
+
+ public Task GetPolicyAsync(string policyName) => Task.FromResult(
+ new AuthorizationPolicy(new[]
+ {
+ new TestPolicyRequirement { PolicyName = policyName }
+ },
+ new[] { $"TestScheme:{policyName}" }));
+ }
+
+ public class TestPolicyRequirement : IAuthorizationRequirement
+ {
+ public string PolicyName { get; set; }
+ }
}
}
diff --git a/src/Components/Shared/test/TestRenderer.cs b/src/Components/Shared/test/TestRenderer.cs
index f2a99ccdd4..d838ea007b 100644
--- a/src/Components/Shared/test/TestRenderer.cs
+++ b/src/Components/Shared/test/TestRenderer.cs
@@ -81,7 +81,7 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers
{
if (!ShouldHandleExceptions)
{
- throw exception;
+ ExceptionDispatchInfo.Capture(exception).Throw();
}
HandledExceptions.Add(exception);
diff --git a/src/Components/test/E2ETest/Tests/AuthTest.cs b/src/Components/test/E2ETest/Tests/AuthTest.cs
index cc3139b6ab..3e9e6ef478 100644
--- a/src/Components/test/E2ETest/Tests/AuthTest.cs
+++ b/src/Components/test/E2ETest/Tests/AuthTest.cs
@@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
[Fact]
public void CascadingAuthenticationState_Unauthenticated()
{
- SignInAs(null);
+ SignInAs(null, null);
var appElement = MountAndNavigateToAuthTest(CascadingAuthenticationStateLink);
@@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
[Fact]
public void CascadingAuthenticationState_Authenticated()
{
- SignInAs("someone cool");
+ SignInAs("someone cool", null);
var appElement = MountAndNavigateToAuthTest(CascadingAuthenticationStateLink);
@@ -56,20 +56,58 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
[Fact]
public void AuthorizeViewCases_NoAuthorizationRule_Unauthenticated()
{
- SignInAs(null);
- MountAndNavigateToAuthTest(AuthorizeViewCases);
+ SignInAs(null, null);
+ var appElement = MountAndNavigateToAuthTest(AuthorizeViewCases);
WaitUntilExists(By.CssSelector("#no-authorization-rule .not-authorized"));
+ Browser.Equal("You're not authorized, anonymous", () =>
+ appElement.FindElement(By.CssSelector("#no-authorization-rule .not-authorized")).Text);
}
[Fact]
public void AuthorizeViewCases_NoAuthorizationRule_Authenticated()
{
- SignInAs("Some User");
+ SignInAs("Some User", null);
var appElement = MountAndNavigateToAuthTest(AuthorizeViewCases);
Browser.Equal("Welcome, Some User!", () =>
appElement.FindElement(By.CssSelector("#no-authorization-rule .authorized")).Text);
}
+ [Fact]
+ public void AuthorizeViewCases_RequireRole_Authenticated()
+ {
+ SignInAs("Some User", "IrrelevantRole,TestRole");
+ var appElement = MountAndNavigateToAuthTest(AuthorizeViewCases);
+ Browser.Equal("Welcome, Some User!", () =>
+ appElement.FindElement(By.CssSelector("#authorize-role .authorized")).Text);
+ }
+
+ [Fact]
+ public void AuthorizeViewCases_RequireRole_Unauthenticated()
+ {
+ SignInAs("Some User", "IrrelevantRole");
+ var appElement = MountAndNavigateToAuthTest(AuthorizeViewCases);
+ Browser.Equal("You're not authorized, Some User", () =>
+ appElement.FindElement(By.CssSelector("#authorize-role .not-authorized")).Text);
+ }
+
+ [Fact]
+ public void AuthorizeViewCases_RequirePolicy_Authenticated()
+ {
+ SignInAs("Bert", null);
+ var appElement = MountAndNavigateToAuthTest(AuthorizeViewCases);
+ Browser.Equal("Welcome, Bert!", () =>
+ appElement.FindElement(By.CssSelector("#authorize-policy .authorized")).Text);
+ }
+
+ [Fact]
+ public void AuthorizeViewCases_RequirePolicy_Unauthenticated()
+ {
+ SignInAs("Mallory", null);
+ var appElement = MountAndNavigateToAuthTest(AuthorizeViewCases);
+ Browser.Equal("You're not authorized, Mallory", () =>
+ appElement.FindElement(By.CssSelector("#authorize-policy .not-authorized")).Text);
+ }
+
IWebElement MountAndNavigateToAuthTest(string authLinkText)
{
Navigate(ServerPathBase);
@@ -79,12 +117,12 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
return appElement;
}
- void SignInAs(string usernameOrNull)
+ void SignInAs(string usernameOrNull, string rolesOrNull)
{
const string authenticationPageUrl = "/Authentication";
var baseRelativeUri = usernameOrNull == null
? $"{authenticationPageUrl}?signout=true"
- : $"{authenticationPageUrl}?username={usernameOrNull}";
+ : $"{authenticationPageUrl}?username={usernameOrNull}&roles={rolesOrNull}";
Navigate(baseRelativeUri);
WaitUntilExists(By.CssSelector("h1#authentication"));
}
diff --git a/src/Components/test/testassets/BasicTestApp/AuthTest/AuthorizeViewCases.razor b/src/Components/test/testassets/BasicTestApp/AuthTest/AuthorizeViewCases.razor
index d78c70f72a..00b39652f2 100644
--- a/src/Components/test/testassets/BasicTestApp/AuthTest/AuthorizeViewCases.razor
+++ b/src/Components/test/testassets/BasicTestApp/AuthTest/AuthorizeViewCases.razor
@@ -11,7 +11,39 @@
Welcome, @context.User.Identity.Name!
- You're not logged in.
+ You're not authorized, @(context.User.Identity.Name ?? "anonymous")
+
+
+
+
+
+
Scenario: Require role
+
+
+
+ Authorizing...
+
+
+ Welcome, @context.User.Identity.Name!
+
+
+ You're not authorized, @(context.User.Identity.Name ?? "anonymous")
+
+
+
+
+
+
Scenario: Require policy
+
+
+
+ Authorizing...
+
+
+ Welcome, @context.User.Identity.Name!
+
+
+ You're not authorized, @(context.User.Identity.Name ?? "anonymous")
diff --git a/src/Components/test/testassets/BasicTestApp/AuthTest/ClientSideAuthenticationStateData.cs b/src/Components/test/testassets/BasicTestApp/AuthTest/ClientSideAuthenticationStateData.cs
index 15178b5d82..f4845803ac 100644
--- a/src/Components/test/testassets/BasicTestApp/AuthTest/ClientSideAuthenticationStateData.cs
+++ b/src/Components/test/testassets/BasicTestApp/AuthTest/ClientSideAuthenticationStateData.cs
@@ -12,6 +12,6 @@ namespace BasicTestApp.AuthTest
public string UserName { get; set; }
- public Dictionary ExposedClaims { get; set; }
+ public List<(string Type, string Value)> ExposedClaims { get; set; }
}
}
diff --git a/src/Components/test/testassets/BasicTestApp/AuthTest/ServerAuthenticationStateProvider.cs b/src/Components/test/testassets/BasicTestApp/AuthTest/ServerAuthenticationStateProvider.cs
index 08639f9254..40750c9c9d 100644
--- a/src/Components/test/testassets/BasicTestApp/AuthTest/ServerAuthenticationStateProvider.cs
+++ b/src/Components/test/testassets/BasicTestApp/AuthTest/ServerAuthenticationStateProvider.cs
@@ -29,7 +29,7 @@ namespace BasicTestApp.AuthTest
if (data.IsAuthenticated)
{
var claims = new[] { new Claim(ClaimTypes.Name, data.UserName) }
- .Concat(data.ExposedClaims.Select(c => new Claim(c.Key, c.Value)));
+ .Concat(data.ExposedClaims.Select(c => new Claim(c.Type, c.Value)));
identity = new ClaimsIdentity(claims, "Server authentication");
}
else
diff --git a/src/Components/test/testassets/BasicTestApp/Startup.cs b/src/Components/test/testassets/BasicTestApp/Startup.cs
index 73084e0260..a97b966f69 100644
--- a/src/Components/test/testassets/BasicTestApp/Startup.cs
+++ b/src/Components/test/testassets/BasicTestApp/Startup.cs
@@ -15,6 +15,12 @@ namespace BasicTestApp
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton();
+
+ services.AddAuthorizationCore(options =>
+ {
+ options.AddPolicy("NameMustStartWithB", policy =>
+ policy.RequireAssertion(ctx => ctx.User.Identity.Name?.StartsWith("B") ?? false));
+ });
}
public void Configure(IComponentsApplicationBuilder app)
diff --git a/src/Components/test/testassets/TestServer/Controllers/UserController.cs b/src/Components/test/testassets/TestServer/Controllers/UserController.cs
index 16764e4080..da6a424419 100644
--- a/src/Components/test/testassets/TestServer/Controllers/UserController.cs
+++ b/src/Components/test/testassets/TestServer/Controllers/UserController.cs
@@ -1,4 +1,6 @@
+using System;
using System.Linq;
+using System.Security.Claims;
using BasicTestApp.AuthTest;
using Microsoft.AspNetCore.Mvc;
@@ -7,22 +9,28 @@ namespace Components.TestServer.Controllers
[Route("api/[controller]")]
public class UserController : Controller
{
+ // Servers are not expected to expose everything from the server-side ClaimsPrincipal
+ // to the client. It's up to the developer to choose what kind of authentication state
+ // data is needed on the client so it can display suitable options in the UI.
+ // In this class, we inform the client only about certain roles and certain other claims.
+ static string[] ExposedRoles = new[] { "IrrelevantRole", "TestRole" };
+
// GET api/user
[HttpGet]
public ClientSideAuthenticationStateData Get()
{
- // Servers are not expected to expose everything from the server-side ClaimsPrincipal
- // to the client. It's up to the developer to choose what kind of authentication state
- // data is needed on the client so it can display suitable options in the UI.
-
return new ClientSideAuthenticationStateData
{
IsAuthenticated = User.Identity.IsAuthenticated,
UserName = User.Identity.Name,
ExposedClaims = User.Claims
- .Where(c => c.Type == "test-claim")
- .ToDictionary(c => c.Type, c => c.Value)
+ .Where(c => c.Type == "test-claim" || IsExposedRole(c))
+ .Select(c => (c.Type, c.Value)).ToList()
};
}
+
+ private bool IsExposedRole(Claim claim)
+ => claim.Type == ClaimTypes.Role
+ && ExposedRoles.Contains(claim.Value);
}
}
diff --git a/src/Components/test/testassets/TestServer/Pages/Authentication.cshtml b/src/Components/test/testassets/TestServer/Pages/Authentication.cshtml
index 3f6cbdefd5..165618a019 100644
--- a/src/Components/test/testassets/TestServer/Pages/Authentication.cshtml
+++ b/src/Components/test/testassets/TestServer/Pages/Authentication.cshtml
@@ -26,6 +26,10 @@
User name:
+
+ Roles:
+
+
Submit
@@ -37,7 +41,11 @@
Authenticated: @User.Identity.IsAuthenticated
Username: @User.Identity.Name
-
+ Roles:
+
+ @string.Join(", ", User.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray())
+
+ foreach
Sign out