Skip to content

Commit 15fb8c8

Browse files
committed
Adding keepalive tests (#46)
1 parent 5de3000 commit 15fb8c8

16 files changed

+229
-18
lines changed

DocFx.AspNetCore.ServerSentEvents/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ You can install [Lib.AspNetCore.ServerSentEvents](https://www.nuget.org/packages
1212
PM> Install-Package Lib.AspNetCore.ServerSentEvents
1313
```
1414

15-
The configuration and basic usage patterns are described [here](articles/getting-started.md).
15+
The configuration and basic usage patterns are described [here](articles/getting-started.html).
1616

1717
## Demos
1818

Lib.AspNetCore.ServerSentEvents/Lib.AspNetCore.ServerSentEvents.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<PackageTags>aspnetcore;sse;server-sent;events;eventsource</PackageTags>
1313
<PackageProjectUrl>https://github.com/tpeczek/Lib.AspNetCore.ServerSentEvents</PackageProjectUrl>
1414
<PackageLicenseExpression>MIT</PackageLicenseExpression>
15+
<PackageReadmeFile>README.md</PackageReadmeFile>
1516
<RepositoryType>git</RepositoryType>
1617
<RepositoryUrl>git://github.com/tpeczek/Lib.AspNetCore.ServerSentEvents</RepositoryUrl>
1718
<GenerateAssemblyTitleAttribute>true</GenerateAssemblyTitleAttribute>

Lib.AspNetCore.ServerSentEvents/ServerSentEventsEndpointRouteBuilderExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if !NETCOREAPP2_1 && !NET461
1+
#if !NET461
22
using System;
33
using Microsoft.AspNetCore.Http;
44
using Microsoft.AspNetCore.Builder;

Lib.AspNetCore.ServerSentEvents/ServerSentEventsMiddleware.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ private async Task ForbidAsync(HttpContext context)
217217

218218
private void DisableResponseBuffering(HttpContext context)
219219
{
220-
#if !NETCOREAPP2_1 && !NET461
220+
#if !NET461
221221
IHttpResponseBodyFeature responseBodyFeature = context.Features.Get<IHttpResponseBodyFeature>();
222222
if (responseBodyFeature != null)
223223
{
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
using Microsoft.AspNetCore.Builder;
3+
using Microsoft.Extensions.Configuration;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using Lib.AspNetCore.ServerSentEvents;
6+
7+
namespace Test.AspNetCore.ServerSentEvents.Functional.Infrastructure
8+
{
9+
internal abstract class FakeServerSentEventsServerStartup
10+
{
11+
public const string SERVER_SENT_EVENTS_ENDPOINT = "/sse";
12+
13+
protected abstract Action<ServerSentEventsServiceOptions<ServerSentEventsService>> ConfigureServerSentEventsOption { get; }
14+
15+
public IConfiguration Configuration { get; }
16+
17+
public FakeServerSentEventsServerStartup(IConfiguration configuration)
18+
{
19+
Configuration = configuration;
20+
}
21+
22+
public void ConfigureServices(IServiceCollection services)
23+
{
24+
services.AddServerSentEvents(ConfigureServerSentEventsOption);
25+
}
26+
27+
#if !NET461
28+
public void Configure(IApplicationBuilder app)
29+
{
30+
app.UseRouting()
31+
.UseEndpoints(endpoints =>
32+
{
33+
endpoints.MapServerSentEvents(SERVER_SENT_EVENTS_ENDPOINT);
34+
});
35+
}
36+
#else
37+
public void Configure(IApplicationBuilder app)
38+
{
39+
app.MapServerSentEvents(SERVER_SENT_EVENTS_ENDPOINT);
40+
}
41+
#endif
42+
}
43+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.IO;
2+
using Microsoft.AspNetCore;
3+
using Microsoft.AspNetCore.Hosting;
4+
using Microsoft.AspNetCore.Mvc.Testing;
5+
6+
namespace Test.AspNetCore.ServerSentEvents.Functional.Infrastructure
7+
{
8+
internal class FakeServerSentEventsServerrApplicationFactory<TFakeServerSentEventsServerStartup> : WebApplicationFactory<TFakeServerSentEventsServerStartup> where TFakeServerSentEventsServerStartup : FakeServerSentEventsServerStartup
9+
{
10+
#if !NET461
11+
protected override IWebHostBuilder CreateWebHostBuilder()
12+
{
13+
return WebHost.CreateDefaultBuilder()
14+
.UseStartup<TFakeServerSentEventsServerStartup>();
15+
}
16+
#else
17+
protected override IWebHostBuilder CreateWebHostBuilder()
18+
{
19+
return new WebHostBuilder()
20+
.UseStartup<TFakeServerSentEventsServerStartup>();
21+
}
22+
#endif
23+
24+
protected override void ConfigureWebHost(IWebHostBuilder builder)
25+
{
26+
builder.UseContentRoot(Path.GetTempPath());
27+
}
28+
}
29+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
using System;
2+
using System.IO;
3+
using System.Text;
4+
using System.Buffers;
5+
using System.Net.Http;
6+
using System.Threading;
7+
using System.Diagnostics;
8+
using System.Threading.Tasks;
9+
using Microsoft.Extensions.Configuration;
10+
using Xunit;
11+
using Lib.AspNetCore.ServerSentEvents;
12+
using Test.AspNetCore.ServerSentEvents.Functional.Infrastructure;
13+
14+
namespace Test.AspNetCore.ServerSentEvents.Functional
15+
{
16+
public class KeepAliveTests
17+
{
18+
#region Fields
19+
private const int KEEPALIVE_INTERVAL = 1;
20+
private readonly static TimeSpan KEEPALIVE_TIMESPAN = TimeSpan.FromSeconds(KEEPALIVE_INTERVAL);
21+
22+
private const string DEFAULT_KEEPALIVE = ": KEEPALIVE\r\n\r\n";
23+
#endregion
24+
25+
#region SUT
26+
private class KeepaliveModeNeverServerSentEventsServerStartup : FakeServerSentEventsServerStartup
27+
{
28+
public KeepaliveModeNeverServerSentEventsServerStartup(IConfiguration configuration) : base(configuration)
29+
{ }
30+
31+
protected override Action<ServerSentEventsServiceOptions<ServerSentEventsService>> ConfigureServerSentEventsOption
32+
{
33+
get
34+
{
35+
return options =>
36+
{
37+
options.KeepaliveMode = ServerSentEventsKeepaliveMode.Never;
38+
options.KeepaliveInterval = KEEPALIVE_INTERVAL;
39+
};
40+
}
41+
}
42+
}
43+
44+
private class KeepaliveModeAlwaysServerSentEventsServerStartup : FakeServerSentEventsServerStartup
45+
{
46+
public KeepaliveModeAlwaysServerSentEventsServerStartup(IConfiguration configuration) : base(configuration)
47+
{ }
48+
49+
protected override Action<ServerSentEventsServiceOptions<ServerSentEventsService>> ConfigureServerSentEventsOption
50+
{
51+
get
52+
{
53+
return options =>
54+
{
55+
options.KeepaliveMode = ServerSentEventsKeepaliveMode.Always;
56+
options.KeepaliveInterval = KEEPALIVE_INTERVAL;
57+
};
58+
}
59+
}
60+
}
61+
#endregion
62+
63+
#region Tests
64+
[Fact]
65+
public async Task ServerSentEventsServer_KeepaliveModeNever_DoesNotSendKeepalive()
66+
{
67+
using FakeServerSentEventsServerrApplicationFactory<KeepaliveModeNeverServerSentEventsServerStartup> serverSentEventsServerApplicationFactory = new();
68+
HttpClient serverSentEventsClient = serverSentEventsServerApplicationFactory.CreateClient();
69+
70+
string serverSentEvents = await GetServerSentEvents(serverSentEventsClient).ConfigureAwait(false);
71+
72+
Assert.Equal(String.Empty, serverSentEvents);
73+
}
74+
75+
[Fact]
76+
public async Task ServerSentEventsServer_KeepaliveModeAlways_SendsDefaultKeepalive()
77+
{
78+
using FakeServerSentEventsServerrApplicationFactory<KeepaliveModeAlwaysServerSentEventsServerStartup> serverSentEventsServerApplicationFactory = new ();
79+
HttpClient serverSentEventsClient = serverSentEventsServerApplicationFactory.CreateClient();
80+
81+
string serverSentEvents = await GetServerSentEvents(serverSentEventsClient).ConfigureAwait(false);
82+
83+
Assert.Matches($"^({DEFAULT_KEEPALIVE})+$", serverSentEvents);
84+
}
85+
86+
private static async Task<string> GetServerSentEvents(HttpClient serverSentEventsClient)
87+
{
88+
Stopwatch keepaliveStopwatch = new Stopwatch();
89+
string serverSentEventsResponseContent = String.Empty;
90+
91+
serverSentEventsClient.DefaultRequestHeaders.Add("Accept", "text/event-stream");
92+
using (HttpResponseMessage serverSentEventsResponse = await serverSentEventsClient.GetAsync(FakeServerSentEventsServerStartup.SERVER_SENT_EVENTS_ENDPOINT, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
93+
{
94+
serverSentEventsResponse.EnsureSuccessStatusCode();
95+
96+
keepaliveStopwatch.Start();
97+
98+
using (Stream responseStream = await serverSentEventsResponse.Content.ReadAsStreamAsync().ConfigureAwait(false))
99+
{
100+
do
101+
{
102+
byte[] buffer = ArrayPool<byte>.Shared.Rent(128);
103+
104+
try
105+
{
106+
CancellationTokenSource keepaliveCancellationTokenSource = new CancellationTokenSource();
107+
keepaliveCancellationTokenSource.CancelAfter(KEEPALIVE_TIMESPAN);
108+
109+
int bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length, keepaliveCancellationTokenSource.Token).ConfigureAwait(false);
110+
serverSentEventsResponseContent += Encoding.UTF8.GetString(buffer, 0, bytesRead);
111+
}
112+
catch (OperationCanceledException)
113+
{ }
114+
115+
ArrayPool<byte>.Shared.Return(buffer);
116+
} while (keepaliveStopwatch.Elapsed < KEEPALIVE_TIMESPAN);
117+
}
118+
}
119+
120+
keepaliveStopwatch.Stop();
121+
122+
return serverSentEventsResponseContent;
123+
}
124+
#endregion
125+
}
126+
}

Test.AspNetCore.ServerSentEvents/Test.AspNetCore.ServerSentEvents.csproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
<PropertyGroup>
33
<TargetFrameworks>netcoreapp3.1;net5.0;net6.0;net461</TargetFrameworks>
44
<IsPackable>false</IsPackable>
5+
<LangVersion>latest</LangVersion>
6+
<PreserveCompilationContext>true</PreserveCompilationContext>
57
</PropertyGroup>
68
<ItemGroup>
79
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
@@ -14,11 +16,21 @@
1416
</ItemGroup>
1517
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
1618
<PackageReference Include="Microsoft.AspNetCore.Http" Version="[2.1.0,3.0.0)" />
19+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="[2.1.0,3.0.0)" />
1720
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[2.1.0,3.0.0)" />
1821
</ItemGroup>
1922
<ItemGroup Condition="'$(TargetFramework)' != 'net461'">
2023
<FrameworkReference Include="Microsoft.AspNetCore.App" />
2124
</ItemGroup>
25+
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
26+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.0" />
27+
</ItemGroup>
28+
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
29+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.0" />
30+
</ItemGroup>
31+
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
32+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0" />
33+
</ItemGroup>
2234
<ItemGroup>
2335
<ProjectReference Include="..\Lib.AspNetCore.ServerSentEvents\Lib.AspNetCore.ServerSentEvents.csproj" />
2436
</ItemGroup>

Test.AspNetCore.ServerSentEvents/Middleware/AuthorizationTests.cs renamed to Test.AspNetCore.ServerSentEvents/Unit/Middleware/AuthorizationTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
using Moq;
77
using Xunit;
88
using Lib.AspNetCore.ServerSentEvents;
9-
using Test.AspNetCore.ServerSentEvents.Middleware.Infrastructure;
9+
using Test.AspNetCore.ServerSentEvents.Unit.Middleware.Infrastructure;
1010

11-
namespace Test.AspNetCore.ServerSentEvents.Middleware
11+
namespace Test.AspNetCore.ServerSentEvents.Unit.Middleware
1212
{
1313
public class AuthorizationTests
1414
{

Test.AspNetCore.ServerSentEvents/Middleware/DisconnectTests.cs renamed to Test.AspNetCore.ServerSentEvents/Unit/Middleware/DisconnectTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
using Moq;
77
using Xunit;
88
using Lib.AspNetCore.ServerSentEvents;
9-
using Test.AspNetCore.ServerSentEvents.Middleware.Infrastructure;
9+
using Test.AspNetCore.ServerSentEvents.Unit.Middleware.Infrastructure;
1010

11-
namespace Test.AspNetCore.ServerSentEvents.Middleware
11+
namespace Test.AspNetCore.ServerSentEvents.Unit.Middleware
1212
{
1313
public class DisconnectTests
1414
{

0 commit comments

Comments
 (0)