Files
git.stella-ops.org/examples/router/tests/Examples.Integration.Tests/GatewayFixture.cs
master 8779e9226f feat: add stella-callgraph-node for JavaScript/TypeScript call graph extraction
- Implemented a new tool `stella-callgraph-node` that extracts call graphs from JavaScript/TypeScript projects using Babel AST.
- Added command-line interface with options for JSON output and help.
- Included functionality to analyze project structure, detect functions, and build call graphs.
- Created a package.json file for dependency management.

feat: introduce stella-callgraph-python for Python call graph extraction

- Developed `stella-callgraph-python` to extract call graphs from Python projects using AST analysis.
- Implemented command-line interface with options for JSON output and verbose logging.
- Added framework detection to identify popular web frameworks and their entry points.
- Created an AST analyzer to traverse Python code and extract function definitions and calls.
- Included requirements.txt for project dependencies.

chore: add framework detection for Python projects

- Implemented framework detection logic to identify frameworks like Flask, FastAPI, Django, and others based on project files and import patterns.
- Enhanced the AST analyzer to recognize entry points based on decorators and function definitions.
2025-12-19 18:11:59 +02:00

148 lines
5.0 KiB
C#

using Examples.Billing.Microservice.Endpoints;
using Examples.Inventory.Microservice.Endpoints;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using StellaOps.Microservice;
using StellaOps.Router.Common.Abstractions;
using StellaOps.Router.Common.Enums;
using StellaOps.Router.Transport.InMemory;
using Xunit;
namespace Examples.Integration.Tests;
/// <summary>
/// Test fixture that sets up the gateway and microservices for integration testing.
/// Uses in-memory transport for fast, isolated tests.
/// </summary>
public sealed class GatewayFixture : IAsyncLifetime
{
private readonly InMemoryConnectionRegistry _registry = new();
private WebApplicationFactory<Examples.Gateway.Program>? _gatewayFactory;
private IHost? _billingHost;
private IHost? _inventoryHost;
public HttpClient GatewayClient { get; private set; } = null!;
public async Task InitializeAsync()
{
// Start the gateway
_gatewayFactory = new WebApplicationFactory<Examples.Gateway.Program>()
.WithWebHostBuilder(builder =>
{
builder.UseEnvironment("Testing");
builder.ConfigureServices(services =>
{
services.RemoveAll<InMemoryConnectionRegistry>();
services.AddSingleton(_registry);
});
});
GatewayClient = _gatewayFactory.CreateClient();
// Start billing microservice
var billingBuilder = Host.CreateApplicationBuilder();
billingBuilder.Services.AddStellaMicroservice(options =>
{
options.ServiceName = "billing";
options.Version = "1.0.0";
options.Region = "test";
options.InstanceId = "billing-test";
options.Routers =
[
new RouterEndpointConfig
{
Host = "localhost",
Port = 5100,
TransportType = TransportType.InMemory
}
];
});
billingBuilder.Services.AddScoped<CreateInvoiceEndpoint>();
billingBuilder.Services.AddScoped<GetInvoiceEndpoint>();
billingBuilder.Services.AddScoped<UploadAttachmentEndpoint>();
billingBuilder.Services.AddSingleton(_registry);
billingBuilder.Services.AddInMemoryTransportClient();
_billingHost = billingBuilder.Build();
await _billingHost.StartAsync();
// Start inventory microservice
var inventoryBuilder = Host.CreateApplicationBuilder();
inventoryBuilder.Services.AddStellaMicroservice(options =>
{
options.ServiceName = "inventory";
options.Version = "1.0.0";
options.Region = "test";
options.InstanceId = "inventory-test";
options.Routers =
[
new RouterEndpointConfig
{
Host = "localhost",
Port = 5100,
TransportType = TransportType.InMemory
}
];
});
inventoryBuilder.Services.AddScoped<ListItemsEndpoint>();
inventoryBuilder.Services.AddScoped<GetItemEndpoint>();
inventoryBuilder.Services.AddSingleton(_registry);
inventoryBuilder.Services.AddInMemoryTransportClient();
_inventoryHost = inventoryBuilder.Build();
await _inventoryHost.StartAsync();
await WaitForGatewayReadyAsync(TimeSpan.FromSeconds(5));
}
public async Task DisposeAsync()
{
GatewayClient.Dispose();
if (_billingHost is not null)
{
await _billingHost.StopAsync();
_billingHost.Dispose();
}
if (_inventoryHost is not null)
{
await _inventoryHost.StopAsync();
_inventoryHost.Dispose();
}
_gatewayFactory?.Dispose();
}
private async Task WaitForGatewayReadyAsync(TimeSpan timeout)
{
if (_gatewayFactory is null)
{
throw new InvalidOperationException("Gateway factory not initialized.");
}
var routingState = _gatewayFactory.Services.GetRequiredService<IGlobalRoutingState>();
var deadline = DateTimeOffset.UtcNow.Add(timeout);
while (DateTimeOffset.UtcNow < deadline)
{
var connections = routingState.GetAllConnections();
if (connections.Count >= 2 &&
routingState.ResolveEndpoint("GET", "/items") is not null &&
routingState.ResolveEndpoint("POST", "/invoices") is not null)
{
return;
}
await Task.Delay(50);
}
var currentConnections = routingState.GetAllConnections();
throw new TimeoutException(
$"Gateway routing state not ready after {timeout}. Connections={currentConnections.Count}.");
}
}