From 2eef115f0bafb90c8e119791514a26b51e86c2b2 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 12 May 2025 13:53:25 +0300 Subject: [PATCH 1/2] Add the GraphQL server simulator --- NBomber.sln | 15 +++++++ .../GraphQLServerSimulator/Contracts/Role.cs | 8 ++++ .../GraphQLServerSimulator/Contracts/User.cs | 11 +++++ .../Data/DbInitializer.cs | 29 +++++++++++++ .../GraphQLServerSimulator/Data/Extensions.cs | 15 +++++++ .../Data/UserDbContext.cs | 23 +++++++++++ .../GraphQLServerSimulator.csproj | 18 ++++++++ examples/GraphQLServerSimulator/Program.cs | 22 ++++++++++ .../Properties/launchSettings.json | 41 +++++++++++++++++++ examples/GraphQLServerSimulator/Query.cs | 11 +++++ .../appsettings.Development.json | 8 ++++ .../GraphQLServerSimulator/appsettings.json | 9 ++++ 12 files changed, 210 insertions(+) create mode 100644 examples/GraphQLServerSimulator/Contracts/Role.cs create mode 100644 examples/GraphQLServerSimulator/Contracts/User.cs create mode 100644 examples/GraphQLServerSimulator/Data/DbInitializer.cs create mode 100644 examples/GraphQLServerSimulator/Data/Extensions.cs create mode 100644 examples/GraphQLServerSimulator/Data/UserDbContext.cs create mode 100644 examples/GraphQLServerSimulator/GraphQLServerSimulator.csproj create mode 100644 examples/GraphQLServerSimulator/Program.cs create mode 100644 examples/GraphQLServerSimulator/Properties/launchSettings.json create mode 100644 examples/GraphQLServerSimulator/Query.cs create mode 100644 examples/GraphQLServerSimulator/appsettings.Development.json create mode 100644 examples/GraphQLServerSimulator/appsettings.json diff --git a/NBomber.sln b/NBomber.sln index 64573266..e48a5d0e 100644 --- a/NBomber.sln +++ b/NBomber.sln @@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcClient", "examples\Grpc EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookstoreSimulator", "examples\BookstoreSimulator\BookstoreSimulator.csproj", "{BB8FF9AE-4D47-47E7-9B22-F3ABDFDE28D1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphQLServerSimulator", "examples\GraphQLServerSimulator\GraphQLServerSimulator.csproj", "{26A207DB-5268-4C0E-B92F-72005815AC4A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -129,6 +131,18 @@ Global {BB8FF9AE-4D47-47E7-9B22-F3ABDFDE28D1}.Release|x64.Build.0 = Release|Any CPU {BB8FF9AE-4D47-47E7-9B22-F3ABDFDE28D1}.Release|x86.ActiveCfg = Release|Any CPU {BB8FF9AE-4D47-47E7-9B22-F3ABDFDE28D1}.Release|x86.Build.0 = Release|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Debug|x64.ActiveCfg = Debug|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Debug|x64.Build.0 = Debug|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Debug|x86.ActiveCfg = Debug|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Debug|x86.Build.0 = Debug|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Release|Any CPU.Build.0 = Release|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Release|x64.ActiveCfg = Release|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Release|x64.Build.0 = Release|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Release|x86.ActiveCfg = Release|Any CPU + {26A207DB-5268-4C0E-B92F-72005815AC4A}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -142,6 +156,7 @@ Global {D4E6343A-1042-CDB6-308D-6C1662607E77} = {B20C9B19-52F5-4AF1-B41D-D01294BEC6C9} {EBBD9F26-59E7-0C55-0059-93AD3EB3469A} = {B20C9B19-52F5-4AF1-B41D-D01294BEC6C9} {BB8FF9AE-4D47-47E7-9B22-F3ABDFDE28D1} = {B20C9B19-52F5-4AF1-B41D-D01294BEC6C9} + {26A207DB-5268-4C0E-B92F-72005815AC4A} = {B20C9B19-52F5-4AF1-B41D-D01294BEC6C9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C7E9329B-84FE-436E-8A44-26D8176C5C6F} diff --git a/examples/GraphQLServerSimulator/Contracts/Role.cs b/examples/GraphQLServerSimulator/Contracts/Role.cs new file mode 100644 index 00000000..fe1b7077 --- /dev/null +++ b/examples/GraphQLServerSimulator/Contracts/Role.cs @@ -0,0 +1,8 @@ +namespace GraphQLServer.Contracts; + +public class Role +{ + public int Id { get; set; } + public string Name { get; set; } + public ICollection Users { get; set; } +} diff --git a/examples/GraphQLServerSimulator/Contracts/User.cs b/examples/GraphQLServerSimulator/Contracts/User.cs new file mode 100644 index 00000000..960c3b27 --- /dev/null +++ b/examples/GraphQLServerSimulator/Contracts/User.cs @@ -0,0 +1,11 @@ +namespace GraphQLServer.Contracts; + +public class User +{ + public int Id { get; set; } + public string Name { get; set; } + public string Country { get; set; } + public int Age { get; set; } + public int RoleId { get; set; } + public Role Role { get; set; } +} diff --git a/examples/GraphQLServerSimulator/Data/DbInitializer.cs b/examples/GraphQLServerSimulator/Data/DbInitializer.cs new file mode 100644 index 00000000..c711a308 --- /dev/null +++ b/examples/GraphQLServerSimulator/Data/DbInitializer.cs @@ -0,0 +1,29 @@ +using Bogus; +using GraphQLServer.Contracts; + +namespace GraphQLServer.Data; + +public static class DbInitializer +{ + public static void Initialize(UserDbContext context) + { + if (context.Users.Any()) + return; + + var roleAdmin = new Role { Name = "Admin" }; + var roleGuest = new Role { Name = "Guest" }; + + var testUsers = new Faker() + .RuleFor(u => u.Name, f => f.Name.FullName()) + .RuleFor(u => u.Country, f => f.Address.Country()) + .RuleFor(u => u.Age, f => f.Random.Int(1, 100)) + .RuleFor(u => u.RoleId, f => f.Random.Int(1, 2)); + + testUsers.GenerateBetween(100, 100); + + context.Roles.AddRange(roleAdmin, roleGuest); + context.Users.AddRange(testUsers.GenerateBetween(5, 10)); + + context.SaveChanges(); + } +} diff --git a/examples/GraphQLServerSimulator/Data/Extensions.cs b/examples/GraphQLServerSimulator/Data/Extensions.cs new file mode 100644 index 00000000..cf37765e --- /dev/null +++ b/examples/GraphQLServerSimulator/Data/Extensions.cs @@ -0,0 +1,15 @@ +namespace GraphQLServer.Data; + +public static class Extensions +{ + public static void CreateDbIfNotExists(this IHost host) + { + using (var scope = host.Services.CreateScope()) + { + var services = scope.ServiceProvider; + var context = services.GetRequiredService(); + context.Database.EnsureCreated(); + DbInitializer.Initialize(context); + } + } +} diff --git a/examples/GraphQLServerSimulator/Data/UserDbContext.cs b/examples/GraphQLServerSimulator/Data/UserDbContext.cs new file mode 100644 index 00000000..820b7af3 --- /dev/null +++ b/examples/GraphQLServerSimulator/Data/UserDbContext.cs @@ -0,0 +1,23 @@ +using GraphQLServer.Contracts; +using Microsoft.EntityFrameworkCore; + +namespace GraphQLServer.Data; + +public class UserDbContext : DbContext +{ + public DbSet Users => Set(); + public DbSet Roles => Set(); + + public UserDbContext(DbContextOptions options) : base(options) { } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity() + .HasOne(u => u.Role) + .WithMany(r => r.Users) + .HasForeignKey(u => u.RoleId) + .OnDelete(DeleteBehavior.Restrict); + } +} diff --git a/examples/GraphQLServerSimulator/GraphQLServerSimulator.csproj b/examples/GraphQLServerSimulator/GraphQLServerSimulator.csproj new file mode 100644 index 00000000..fc980b9d --- /dev/null +++ b/examples/GraphQLServerSimulator/GraphQLServerSimulator.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/examples/GraphQLServerSimulator/Program.cs b/examples/GraphQLServerSimulator/Program.cs new file mode 100644 index 00000000..94b6657d --- /dev/null +++ b/examples/GraphQLServerSimulator/Program.cs @@ -0,0 +1,22 @@ +using GraphQLServer; +using GraphQLServer.Data; +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddDbContext(options => + options.UseInMemoryDatabase("UserDb")) + .AddLogging(Console.WriteLine); + +builder.Services + .AddGraphQLServer() + .AddQueryType() + .AddFiltering(); + +var app = builder.Build(); + +app.CreateDbIfNotExists(); + +app.MapGraphQL(); + +app.Run(); diff --git a/examples/GraphQLServerSimulator/Properties/launchSettings.json b/examples/GraphQLServerSimulator/Properties/launchSettings.json new file mode 100644 index 00000000..f07bd8af --- /dev/null +++ b/examples/GraphQLServerSimulator/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62323", + "sslPort": 44337 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "weatherforecast", + "applicationUrl": "http://localhost:5088", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "weatherforecast", + "applicationUrl": "https://localhost:7287;http://localhost:5088", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/examples/GraphQLServerSimulator/Query.cs b/examples/GraphQLServerSimulator/Query.cs new file mode 100644 index 00000000..dcb40fbc --- /dev/null +++ b/examples/GraphQLServerSimulator/Query.cs @@ -0,0 +1,11 @@ +using GraphQLServer.Contracts; +using GraphQLServer.Data; +using Microsoft.EntityFrameworkCore; + +namespace GraphQLServer; + +public class Query +{ + [UseFiltering] + public IQueryable GetUsers(UserDbContext dbContext) => dbContext.Users.Include(u => u.Role); +} diff --git a/examples/GraphQLServerSimulator/appsettings.Development.json b/examples/GraphQLServerSimulator/appsettings.Development.json new file mode 100644 index 00000000..0c208ae9 --- /dev/null +++ b/examples/GraphQLServerSimulator/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/examples/GraphQLServerSimulator/appsettings.json b/examples/GraphQLServerSimulator/appsettings.json new file mode 100644 index 00000000..10f68b8c --- /dev/null +++ b/examples/GraphQLServerSimulator/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} From 26f5858078d371842b26dd87aab07c897468603e Mon Sep 17 00:00:00 2001 From: User Date: Mon, 12 May 2025 14:12:39 +0300 Subject: [PATCH 2/2] Add the GraphQL scenario example --- examples/Demo/GraphQL/GraphQLExample.cs | 47 +++++++++++++++++++ examples/Demo/Program.cs | 8 +++- .../Data/DbInitializer.cs | 4 +- .../Properties/launchSettings.json | 30 +----------- 4 files changed, 57 insertions(+), 32 deletions(-) create mode 100644 examples/Demo/GraphQL/GraphQLExample.cs diff --git a/examples/Demo/GraphQL/GraphQLExample.cs b/examples/Demo/GraphQL/GraphQLExample.cs new file mode 100644 index 00000000..13256cb1 --- /dev/null +++ b/examples/Demo/GraphQL/GraphQLExample.cs @@ -0,0 +1,47 @@ +using NBomber.CSharp; +using NBomber.Http.CSharp; +using System.Text; +using System.Text.Json; + +namespace Demo.GraphQL; + +class GraphQLExample +{ + public void Run() + { + // For this example, you'll need to start the GraphQLServerSimulator, which is located in the examples/simulators solution folder. + // Make sure it’s running before executing the client tests to ensure proper communication. + + var httpClient = new HttpClient(); + + var scenario = Scenario.Create("graphql_scenario", async context => + { + var queryObject = new + { + query = @" + query { + users(where: { age: { gt: 20 } }) { + name + age + role { + name + } + } + } + " + }; + string jsonQuery = JsonSerializer.Serialize(queryObject); + + var request = Http.CreateRequest("POST", "http://localhost:5088/graphql") + .WithBody(new StringContent(jsonQuery, Encoding.UTF8, "application/json")); + + return await Http.Send(httpClient, request); + }) + .WithoutWarmUp() + .WithLoadSimulations(Simulation.KeepConstant(1, TimeSpan.FromSeconds(30))); + + NBomberRunner + .RegisterScenarios(scenario) + .Run(); + } +} diff --git a/examples/Demo/Program.cs b/examples/Demo/Program.cs index e19d1c9a..cecaae84 100644 --- a/examples/Demo/Program.cs +++ b/examples/Demo/Program.cs @@ -33,11 +33,12 @@ using Demo.AMQP; using Demo.AMQP.ClientPool; using Demo.AMQP.IndependentActors; +using Demo.GraphQL; // ------------------------------- // ----- Hello World examples ----- // ------------------------------- -new HelloWorldExample().Run(); +//new HelloWorldExample().Run(); // new ScenarioWithInit().Run(); // new ScenarioWithSteps().Run(); // new StepsShareData().Run(); @@ -134,6 +135,11 @@ // ---------------- // new GrpcExample().Run(); +// ---------------- +// ---- GraphQL --- +// ---------------- +new GraphQLExample().Run(); + // ---------------- // ----- Db ------- // ---------------- diff --git a/examples/GraphQLServerSimulator/Data/DbInitializer.cs b/examples/GraphQLServerSimulator/Data/DbInitializer.cs index c711a308..04b383b2 100644 --- a/examples/GraphQLServerSimulator/Data/DbInitializer.cs +++ b/examples/GraphQLServerSimulator/Data/DbInitializer.cs @@ -1,4 +1,4 @@ -using Bogus; +using Bogus; using GraphQLServer.Contracts; namespace GraphQLServer.Data; @@ -22,7 +22,7 @@ public static void Initialize(UserDbContext context) testUsers.GenerateBetween(100, 100); context.Roles.AddRange(roleAdmin, roleGuest); - context.Users.AddRange(testUsers.GenerateBetween(5, 10)); + context.Users.AddRange(testUsers.GenerateBetween(100, 1000)); context.SaveChanges(); } diff --git a/examples/GraphQLServerSimulator/Properties/launchSettings.json b/examples/GraphQLServerSimulator/Properties/launchSettings.json index f07bd8af..bc52ac5a 100644 --- a/examples/GraphQLServerSimulator/Properties/launchSettings.json +++ b/examples/GraphQLServerSimulator/Properties/launchSettings.json @@ -1,41 +1,13 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:62323", - "sslPort": 44337 - } - }, +{ "profiles": { "http": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, "launchUrl": "weatherforecast", "applicationUrl": "http://localhost:5088", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "weatherforecast", - "applicationUrl": "https://localhost:7287;http://localhost:5088", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "weatherforecast", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } } } }