Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
COPY . .
WORKDIR "/examples/WebSocketsSimulator/"
RUN dotnet build "WebSocketsSimulator.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WebSocketsSimulator.csproj" -c Release -o /app/publish /p:UseAppHost=false

FROM base AS final
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebSocketsSimulator.dll"]
42 changes: 42 additions & 0 deletions NBomber.WebSockets.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35818.85
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBomber.WebSockets", "src\NBomber.WebSockets\NBomber.WebSockets.csproj", "{D51D0751-127B-4B98-A19F-8B9DE2EC9307}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "simulators", "simulators", "{B9FB143E-EE4C-4A54-9EB2-582FDABC5DAE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebSocketsSimulator", "examples\WebSocketsSimulator\WebSocketsSimulator.csproj", "{46A32EDA-64C0-493E-91DD-F1E961AB16CD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo", "examples\Demo\Demo.csproj", "{570BC395-3909-4782-9907-B8884CDF4144}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{EE0EB6BE-DECE-404F-A9C6-D418991A938E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBomber.WebSockets.Tests", "tests\NBomber.WebSockets.Tests\NBomber.WebSockets.Tests.csproj", "{230CCC53-5938-40EE-A808-0D29A2C60B76}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution items", "solution items", "{EE79065A-2614-411A-9AD6-6174B947C6CF}"
ProjectSection(SolutionItems) = preProject
docker-compose.yml = docker-compose.yml
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -12,7 +32,29 @@ Global
{D51D0751-127B-4B98-A19F-8B9DE2EC9307}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D51D0751-127B-4B98-A19F-8B9DE2EC9307}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D51D0751-127B-4B98-A19F-8B9DE2EC9307}.Release|Any CPU.Build.0 = Release|Any CPU
{46A32EDA-64C0-493E-91DD-F1E961AB16CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46A32EDA-64C0-493E-91DD-F1E961AB16CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46A32EDA-64C0-493E-91DD-F1E961AB16CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46A32EDA-64C0-493E-91DD-F1E961AB16CD}.Release|Any CPU.Build.0 = Release|Any CPU
{570BC395-3909-4782-9907-B8884CDF4144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{570BC395-3909-4782-9907-B8884CDF4144}.Debug|Any CPU.Build.0 = Debug|Any CPU
{570BC395-3909-4782-9907-B8884CDF4144}.Release|Any CPU.ActiveCfg = Release|Any CPU
{570BC395-3909-4782-9907-B8884CDF4144}.Release|Any CPU.Build.0 = Release|Any CPU
{230CCC53-5938-40EE-A808-0D29A2C60B76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{230CCC53-5938-40EE-A808-0D29A2C60B76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{230CCC53-5938-40EE-A808-0D29A2C60B76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{230CCC53-5938-40EE-A808-0D29A2C60B76}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{B9FB143E-EE4C-4A54-9EB2-582FDABC5DAE} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{46A32EDA-64C0-493E-91DD-F1E961AB16CD} = {B9FB143E-EE4C-4A54-9EB2-582FDABC5DAE}
{570BC395-3909-4782-9907-B8884CDF4144} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{230CCC53-5938-40EE-A808-0D29A2C60B76} = {EE0EB6BE-DECE-404F-A9C6-D418991A938E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CE7E10B1-5819-4A63-94A7-DA4D10007B42}
EndGlobalSection
EndGlobal
7 changes: 7 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:

websockets-simulator:
build:
dockerfile: Dockerfile
ports:
- "5139:8080"
19 changes: 19 additions & 0 deletions examples/Demo/Demo.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NBomber" Version="6.1.0-beta.2" />
<PackageReference Include="NBomber.Data" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\NBomber.WebSockets\NBomber.WebSockets.csproj" />
</ItemGroup>

</Project>
57 changes: 57 additions & 0 deletions examples/Demo/PingPongExample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using NBomber.CSharp;
using NBomber.Data;
using NBomber.WebSockets;

new PingPongWebSocketsTest().Run();

public class PingPongWebSocketsTest
{
// To run this example you need to spin up local server examples/simulators/WebSocketsSimulator
// The server should run on localhost:5139

public void Run()
{
var payload = Data.GenerateRandomBytes(sizeInBytes: 500);

var scenario = Scenario.Create("ping_pong_websockets", async ctx =>
{
using var websocket = new WebSocket(new WebSocketConfig());

var connect = await Step.Run("connect", ctx, async () =>
{
await websocket.Connect("ws://localhost:5139/ws");
return Response.Ok();
});

var ping = await Step.Run("ping", ctx, async () =>
{
await websocket.Send(payload);
return Response.Ok(sizeBytes: payload.Length);
});

var pong = await Step.Run("pong", ctx, async () =>
{
using var response = await websocket.Receive(ctx.ScenarioCancellationToken);
// var str = Encoding.UTF8.GetString(response.Data.Span);
// var user = JsonSerializer.Deserialize<T>(response.Data.Span);
return Response.Ok(sizeBytes: response.Data.Length);
});

var disconnect = await Step.Run("disconnect", ctx, async () =>
{
await websocket.Close();
return Response.Ok();
});

return Response.Ok();
})
.WithoutWarmUp()
.WithLoadSimulations(
Simulation.KeepConstant(1, TimeSpan.FromSeconds(30))
);

NBomberRunner
.RegisterScenarios(scenario)
.Run();
}
}
74 changes: 74 additions & 0 deletions examples/WebSocketsSimulator/Controllers/WebSocketController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System.Net.WebSockets;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IO;

namespace WebAppSimulator.Controllers;

public class WebSocketController : ControllerBase
{
private static readonly RecyclableMemoryStreamManager MsStreamManager = new();
private const int BufferSize = 1024 * 16;

[Route("/ws")]
public async Task Get()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();

await Receive(webSocket);
//await Send(webSocket, ms);
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}

private async Task Receive(WebSocket webSocket)
{
try
{
var closeSocket = false;

while (!closeSocket)
{
var endOfMessage = false;
using var ms = MsStreamManager.GetStream();

while (!endOfMessage)
{
var buffer = ms.GetMemory(BufferSize);
var message = await webSocket.ReceiveAsync(buffer, CancellationToken.None);

if (message.MessageType == WebSocketMessageType.Close)
{
closeSocket = true;
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
break;
}

ms.Advance(message.Count);
endOfMessage = message.EndOfMessage;
}

if (!closeSocket)
await Send(webSocket, ms);
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}

private async Task Send(WebSocket webSocket, RecyclableMemoryStream ms)
{
if (ms.Length > 0)
{
var msg = ms.GetBuffer().AsMemory(0, (int)ms.Length);
await webSocket.SendAsync(msg, WebSocketMessageType.Binary, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
}
}
}
11 changes: 11 additions & 0 deletions examples/WebSocketsSimulator/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

app.UseWebSockets();

app.MapControllers();

app.Run();
12 changes: 12 additions & 0 deletions examples/WebSocketsSimulator/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"profiles": {
"WebSocketsSimulator": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5139"
}
}
}
13 changes: 13 additions & 0 deletions examples/WebSocketsSimulator/WebSocketsSimulator.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
</ItemGroup>

</Project>
8 changes: 8 additions & 0 deletions examples/WebSocketsSimulator/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions examples/WebSocketsSimulator/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
2 changes: 1 addition & 1 deletion src/NBomber.WebSockets/NBomber.WebSockets.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
<PackageReference Include="NBomber.Contracts" Version="6.1.0-beta.0" />
<PackageReference Include="NBomber.Contracts" Version="6.1.0-beta.1" />
</ItemGroup>

</Project>
29 changes: 29 additions & 0 deletions tests/NBomber.WebSockets.Tests/NBomber.WebSockets.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NBomber" Version="6.1.0-beta.2" />
<PackageReference Include="NBomber.Data" Version="6.0.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\NBomber.WebSockets\NBomber.WebSockets.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

</Project>
Loading
Loading