mirror of https://github.com/dapr/dotnet-sdk.git
242 lines
8.6 KiB
C#
242 lines
8.6 KiB
C#
// ------------------------------------------------------------------------
|
|
// Copyright 2021 The Dapr Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// ------------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Net.Http;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Authentication;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.TestHost;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Xunit;
|
|
using Xunit.Sdk;
|
|
|
|
namespace Dapr.Actors.AspNetCore.IntegrationTest
|
|
{
|
|
public class HostingTests
|
|
{
|
|
[Fact]
|
|
public void MapActorsHandlers_WithoutAddActors_Throws()
|
|
{
|
|
var exception = Assert.Throws<InvalidOperationException>(() =>
|
|
{
|
|
// Initializes web pipeline which will trigger the exception we throw.
|
|
//
|
|
// NOTE: in 3.1 TestServer.CreateClient triggers the failure, in 5.0 it's Host.Start
|
|
using var host = CreateHost<BadStartup>();
|
|
var server = host.GetTestServer();
|
|
server.CreateClient();
|
|
});
|
|
|
|
Assert.Equal(
|
|
"The ActorRuntime service is not registered with the dependency injection container. " +
|
|
"Call AddActors() inside ConfigureServices() to register the actor runtime and actor types.",
|
|
exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task MapActorsHandlers_IncludesHealthChecks()
|
|
{
|
|
using var factory = new AppWebApplicationFactory();
|
|
|
|
var httpClient = factory.CreateClient(new Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactoryClientOptions { HandleCookies = false });
|
|
var response = await httpClient.GetAsync("/healthz");
|
|
await Assert2XXStatusAsync(response);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ActorsHealthz_ShouldNotRequireAuthorization()
|
|
{
|
|
using var host = CreateHost<AuthorizedRoutesStartup>();
|
|
var server = host.GetTestServer();
|
|
|
|
var httpClient = server.CreateClient();
|
|
var response = await httpClient.GetAsync("/healthz");
|
|
await Assert2XXStatusAsync(response);
|
|
}
|
|
|
|
// We add our own health check on /healthz with worse priority than one
|
|
// that would be added by a user. Make sure this works and the if the user
|
|
// adds their own health check it will win.
|
|
[Fact]
|
|
public async Task MapActorsHandlers_ActorHealthCheckDoesNotConflict()
|
|
{
|
|
using var host = CreateHost<HealthCheckStartup>();
|
|
var server = host.GetTestServer();
|
|
|
|
var httpClient = server.CreateClient();
|
|
var response = await httpClient.GetAsync("/healthz");
|
|
await Assert2XXStatusAsync(response);
|
|
|
|
var text = await response.Content.ReadAsStringAsync();
|
|
Assert.Equal("Ice Cold, Solid Gold!", text);
|
|
}
|
|
|
|
// Regression test for #434
|
|
[Fact]
|
|
public async Task MapActorsHandlers_WorksWithFallbackRoute()
|
|
{
|
|
using var host = CreateHost<FallbackRouteStartup>();
|
|
var server = host.GetTestServer();
|
|
|
|
var httpClient = server.CreateClient();
|
|
var response = await httpClient.GetAsync("/dapr/config");
|
|
await Assert2XXStatusAsync(response);
|
|
}
|
|
|
|
private static IHost CreateHost<TStartup>() where TStartup : class
|
|
{
|
|
var builder = Host
|
|
.CreateDefaultBuilder()
|
|
.ConfigureLogging(b =>
|
|
{
|
|
// shhhh
|
|
b.SetMinimumLevel(LogLevel.None);
|
|
})
|
|
.ConfigureWebHostDefaults(webBuilder =>
|
|
{
|
|
webBuilder.UseStartup<TStartup>();
|
|
webBuilder.UseTestServer();
|
|
});
|
|
var host = builder.Build();
|
|
try
|
|
{
|
|
host.Start();
|
|
}
|
|
catch
|
|
{
|
|
host.Dispose();
|
|
throw;
|
|
}
|
|
|
|
return host;
|
|
}
|
|
|
|
private class BadStartup
|
|
{
|
|
public void ConfigureServices(IServiceCollection services)
|
|
{
|
|
// no call to AddActors here. That's bad!
|
|
services.AddRouting();
|
|
services.AddHealthChecks();
|
|
}
|
|
|
|
public void Configure(IApplicationBuilder app)
|
|
{
|
|
app.UseRouting();
|
|
app.UseEndpoints(endpoints =>
|
|
{
|
|
endpoints.MapActorsHandlers();
|
|
});
|
|
}
|
|
}
|
|
|
|
private class AuthorizedRoutesStartup
|
|
{
|
|
public void ConfigureServices(IServiceCollection services)
|
|
{
|
|
services.AddActors(default);
|
|
services.AddAuthentication().AddDapr(options => options.Token = "abcdefg");
|
|
|
|
services.AddAuthorization(o => o.AddDapr());
|
|
}
|
|
|
|
public void Configure(IApplicationBuilder app)
|
|
{
|
|
app.UseRouting();
|
|
app.UseAuthentication();
|
|
app.UseAuthorization();
|
|
app.UseEndpoints(endpoints =>
|
|
{
|
|
endpoints.MapActorsHandlers().RequireAuthorization("Dapr");
|
|
});
|
|
}
|
|
}
|
|
|
|
private class FallbackRouteStartup
|
|
{
|
|
public void ConfigureServices(IServiceCollection services)
|
|
{
|
|
services.AddActors(default);
|
|
}
|
|
|
|
public void Configure(IApplicationBuilder app)
|
|
{
|
|
app.UseRouting();
|
|
app.UseEndpoints(endpoints =>
|
|
{
|
|
// This routing feature registers a "route of last resort" which is what
|
|
// was tripping out Actors prior to changing how they are registered.
|
|
endpoints.MapFallback(context =>
|
|
{
|
|
throw new InvalidTimeZoneException("This should not be called!");
|
|
});
|
|
endpoints.MapActorsHandlers();
|
|
});
|
|
}
|
|
}
|
|
|
|
private class HealthCheckStartup
|
|
{
|
|
public void ConfigureServices(IServiceCollection services)
|
|
{
|
|
services.AddActors(default);
|
|
}
|
|
|
|
public void Configure(IApplicationBuilder app)
|
|
{
|
|
app.UseRouting();
|
|
app.UseEndpoints(endpoints =>
|
|
{
|
|
endpoints.MapHealthChecks("/healthz", new HealthCheckOptions()
|
|
{
|
|
// Write something different so we know this one is called.
|
|
ResponseWriter = async (httpContext, report) =>
|
|
{
|
|
await httpContext.Response.WriteAsync(
|
|
report.Status == HealthStatus.Healthy ?
|
|
"Ice Cold, Solid Gold!" :
|
|
"Oh Noes!");
|
|
},
|
|
});
|
|
endpoints.MapActorsHandlers();
|
|
});
|
|
}
|
|
}
|
|
|
|
private async Task Assert2XXStatusAsync(HttpResponseMessage response)
|
|
{
|
|
if (response.IsSuccessStatusCode)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (response.Content == null)
|
|
{
|
|
throw new XunitException($"The response failed with a {response.StatusCode} and no body.");
|
|
}
|
|
|
|
// We assume a textual response. #YOLO
|
|
var text = await response.Content.ReadAsStringAsync();
|
|
throw new XunitException($"The response failed with a {response.StatusCode} and body:" + Environment.NewLine + text);
|
|
}
|
|
}
|
|
}
|