diff --git a/docs/getting-started/core-concepts.md b/docs/getting-started/core-concepts.md index 25998bd2..522efddc 100644 --- a/docs/getting-started/core-concepts.md +++ b/docs/getting-started/core-concepts.md @@ -85,6 +85,17 @@ lambda.OnShutdown(async ( }); ``` +### Lifecycle Context Access + +Both OnInit and OnShutdown handlers support rich dependency injection patterns: + +- **Inject services directly**: `(ICache cache, ILogger logger, CancellationToken ct)` – Recommended for most scenarios +- **Access AWS metadata**: `(ILambdaLifecycleContext context)` – When you need environment information like function name, region, memory size, or initialization type +- **Combine both**: `(ILambdaLifecycleContext context, ICache cache)` – Mix context access with direct service injection +- **Use keyed services**: `([FromKeyedServices("key")] IService service)` – Resolve services registered with specific keys + +The `ILambdaLifecycleContext` interface provides AWS environment metadata, a `Properties` dictionary for sharing state between handlers, and access to the scoped `ServiceProvider`. See [Lifecycle Management](../guides/lifecycle-management.md) for detailed patterns and examples. + ### Lifecycle Timeline ```mermaid diff --git a/docs/guides/dependency-injection.md b/docs/guides/dependency-injection.md index 0366fa98..c8b5bfe8 100644 --- a/docs/guides/dependency-injection.md +++ b/docs/guides/dependency-injection.md @@ -74,23 +74,63 @@ If your handler doesn't need the Lambda payload, omit the `[FromEvent]` paramete remaining time when creating the token. - Always pass it down to outbound SDK calls and database queries so you can stop work cleanly. -## Middleware and Lifecycle Hooks +## Middleware and Lifecycle Hooks: Source-Generated DI - Middleware receives the invocation scope via the `ILambdaHostContext` argument. Resolve services with `context.ServiceProvider` or create reusable middleware classes with constructor injection. -- `OnInit` and `OnShutdown` handlers run outside the normal invocation scope but each one executes - inside its own scoped service provider so you can warm caches, seed connections, or flush telemetry - without leaking per-invocation services. +- `OnInit` and `OnShutdown` handlers now use the same source-generated dependency injection as your main + handlers. Each executes inside its own scoped service provider so you can warm caches, seed connections, + or flush telemetry without leaking per-invocation services. -```csharp title="OnInit" -lambda.OnInit(async (services, ct) => +OnInit and OnShutdown handlers support multiple dependency injection patterns: + +```csharp title="Pattern 1: Direct DI (Recommended)" +lambda.OnInit(async (ICache cache, ILogger logger, CancellationToken ct) => { - var cache = services.GetRequiredService(); + logger.LogInformation("Warming cache during cold start"); await cache.WarmUpAsync(ct); return true; }); ``` +Each handler runs in its own scoped service provider, so you can safely resolve scoped services even +outside the invocation pipeline. + +```csharp title="Pattern 2: Using ILambdaLifecycleContext" +lambda.OnInit(async (ILambdaLifecycleContext context, ICache cache) => +{ + var logger = context.ServiceProvider.GetRequiredService>(); + logger.LogInformation( + "Init type: {Type}, Function: {Name}, Memory: {MB}MB", + context.InitializationType, + context.FunctionName, + context.FunctionMemorySize + ); + + await cache.WarmUpAsync(context.CancellationToken); + return true; +}); +``` + +Use `ILambdaLifecycleContext` when you need AWS environment metadata (region, function name, memory size, +initialization type) or want to share data between handlers via the `Properties` dictionary. + +```csharp title="Pattern 3: Keyed Services" +builder.Services.AddKeyedSingleton("redis"); +builder.Services.AddKeyedSingleton("memory"); + +lambda.OnInit(async ( + [FromKeyedServices("redis")] ICache primaryCache, + [FromKeyedServices("memory")] ICache fallbackCache, + CancellationToken ct +) => +{ + await primaryCache.WarmUpAsync(ct); + await fallbackCache.WarmUpAsync(ct); + return true; +}); +``` + ## Configuration and Options Use the standard options pattern for configuration: diff --git a/docs/guides/lifecycle-management.md b/docs/guides/lifecycle-management.md index 719bb10a..5ddb808b 100644 --- a/docs/guides/lifecycle-management.md +++ b/docs/guides/lifecycle-management.md @@ -132,22 +132,112 @@ Both handlers are awaited simultaneously. Keep shutdown work small—only the re OnInit and OnShutdown handlers support the same source-generated dependency injection experience as middleware and handlers: -- Request only what you need. The generated delegate resolves typed parameters (services, keyed services, `ILambdaHostContext`, `CancellationToken`, etc.). +- Request only what you need. The generated delegate resolves typed parameters (services, keyed services, `ILambdaLifecycleContext`, `CancellationToken`, etc.). - `MinimalLambda` creates a new `IServiceScope` for every handler invocation, ensuring scoped services (database units of work, caches) are isolated even though you are outside the invocation pipeline. -- The `IServiceProvider` parameter gives you direct access to the scope for manual resolution when needed. +- Inject `ILambdaLifecycleContext` when you need AWS environment metadata or want to share state via the `Properties` dictionary. For simple scenarios, inject services directly. + +```csharp title="Program.cs - Keyed Services" +builder.Services.AddKeyedSingleton("primary"); +builder.Services.AddKeyedSingleton("secondary"); -```csharp title="Program.cs" lambda.OnInit(async ( - IServiceProvider scope, - KeyedService("primary"), + [FromKeyedServices("primary")] IMyClient primaryClient, + [FromKeyedServices("secondary")] IMyClient secondaryClient, CancellationToken ct ) => { - await MyWarmupAsync(scope, MyClient, ct); + await primaryClient.WarmupAsync(ct); + await secondaryClient.WarmupAsync(ct); + return true; +}); +``` + +## Accessing AWS Environment Information + +When you need AWS environment metadata during initialization or shutdown, inject `ILambdaLifecycleContext`. This interface provides rich context information about the Lambda execution environment beyond what's available in the standard invocation pipeline. + +### Using ILambdaLifecycleContext + +```csharp title="Program.cs - AWS Environment Metadata" +lambda.OnInit(async (ILambdaLifecycleContext context, ILogger logger) => +{ + logger.LogInformation( + "Initializing {FunctionName} v{Version} in {Region}", + context.FunctionName, + context.FunctionVersion, + context.Region + ); + + logger.LogInformation( + "Memory: {Memory}MB, Init type: {InitType}, Elapsed: {Elapsed}ms", + context.FunctionMemorySize, + context.InitializationType, + context.ElapsedTime.TotalMilliseconds + ); + return true; }); ``` +### Sharing State via Properties Dictionary + +The `Properties` dictionary lets you share data between OnInit handlers or pass information from initialization to your invocation handlers. + +```csharp title="Program.cs - State Sharing" +lambda.OnInit(async (ILambdaLifecycleContext context) => +{ + var initStartTime = DateTimeOffset.UtcNow; + context.Properties["InitStartTime"] = initStartTime; + context.Properties["EnvironmentType"] = context.InitializationType; + + return true; +}); + +lambda.OnInit(async (ILambdaLifecycleContext context, ILogger logger) => +{ + if (context.Properties.TryGetValue("InitStartTime", out var startTime)) + { + logger.LogInformation("First handler started at {Time}", startTime); + } + + return true; +}); +``` + +The `Properties` dictionary is backed by a thread-safe `ConcurrentDictionary` and is shared across all OnInit handlers. Properties set during OnInit are also available to invocation handlers via `ILambdaHostContext.Properties`. + +### Available Context Properties + +`ILambdaLifecycleContext` exposes the following properties: + +| Property | Type | Description | +|----------|------|-------------| +| `CancellationToken` | `CancellationToken` | Signals cancellation when `InitTimeout` (OnInit) or `ShutdownDuration - ShutdownDurationBuffer` (OnShutdown) elapses, or when SIGTERM is received | +| `ServiceProvider` | `IServiceProvider` | The scoped service container for this handler invocation. Use for manual service resolution when direct injection isn't sufficient | +| `Properties` | `IDictionary` | Thread-safe dictionary for sharing data between handlers or from OnInit to invocation handlers | +| `ElapsedTime` | `TimeSpan` | Time elapsed since the Lambda execution environment started | +| `Region` | `string?` | AWS region where the function is running (from `AWS_REGION` env var) | +| `ExecutionEnvironment` | `string?` | Runtime identifier like `AWS_Lambda_dotnet8` (from `AWS_EXECUTION_ENV` env var) | +| `FunctionName` | `string?` | Name of the Lambda function (from `AWS_LAMBDA_FUNCTION_NAME` env var) | +| `FunctionMemorySize` | `int?` | Memory allocated to the function in MB (from `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` env var) | +| `FunctionVersion` | `string?` | Version of the function being executed (from `AWS_LAMBDA_FUNCTION_VERSION` env var) | +| `InitializationType` | `string?` | Type of initialization: `on-demand`, `provisioned-concurrency`, `snap-start`, or `lambda-managed-instances` (from `AWS_LAMBDA_INITIALIZATION_TYPE` env var) | +| `LogGroupName` | `string?` | CloudWatch Logs group name (from `AWS_LAMBDA_LOG_GROUP_NAME` env var, not available in SnapStart) | +| `LogStreamName` | `string?` | CloudWatch Logs stream name (from `AWS_LAMBDA_LOG_STREAM_NAME` env var, not available in SnapStart) | +| `TaskRoot` | `string?` | Path to the Lambda function code (from `LAMBDA_TASK_ROOT` env var) | + +All AWS environment properties are nullable because they depend on environment variables set by the Lambda runtime. Most are available during normal execution, but some (like `LogGroupName` and `LogStreamName`) are unavailable in SnapStart functions. + +### When to Use ILambdaLifecycleContext + +Use `ILambdaLifecycleContext` when you need: + +- **AWS environment metadata** – Access region, function name, memory size, or initialization type for logging, metrics, or conditional logic based on the execution environment +- **State sharing** – Pass data between OnInit handlers or from OnInit to invocation handlers via the `Properties` dictionary +- **Manual service resolution** – Access `ServiceProvider` directly for advanced scenarios where parameter injection isn't sufficient + +For simple dependency injection scenarios, prefer injecting services directly as parameters instead of using `ILambdaLifecycleContext.ServiceProvider`. + ## Configuring Lifecycle Behavior Use `ConfigureLambdaHostOptions` to shape lifecycle behavior centrally or bind the same settings from configuration: diff --git a/examples/MinimalLambda.Example.Lifecycle/Program.cs b/examples/MinimalLambda.Example.Lifecycle/Program.cs index 3692dabc..139497cf 100644 --- a/examples/MinimalLambda.Example.Lifecycle/Program.cs +++ b/examples/MinimalLambda.Example.Lifecycle/Program.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using MinimalLambda.Builder; var builder = LambdaApplication.CreateBuilder(); @@ -20,22 +21,21 @@ lambda.UseClearLambdaOutputFormatting(); -lambda.OnInit( - Task (IServiceCollection services, CancellationToken cancellationToken) => - { - Console.WriteLine("Initializing..."); - return Task.FromResult(true); - } -); +lambda.OnInit(() => +{ + Console.WriteLine("Initializing..."); + return Task.FromResult(true); +}); lambda.OnInit( - async Task (IServiceCollection services, CancellationToken cancellationToken) => + async Task (ILogger logger, CancellationToken cancellationToken) => { var stopwatch = Stopwatch.StartNew(); while (!cancellationToken.IsCancellationRequested) { - Console.WriteLine( - $"Waiting for init to timeout. {stopwatch.ElapsedMilliseconds}ms elapsed" + logger.LogInformation( + "Waiting for init to timeout. {ElapsedMilliseconds}ms elapsed", + stopwatch.ElapsedMilliseconds ); try { @@ -58,7 +58,7 @@ async Task (IServiceCollection services, CancellationToken cancellationTok }); lambda.OnShutdown( - (IServiceCollection services, CancellationToken token) => + (CancellationToken token) => { Console.WriteLine("Shutting down..."); return Task.CompletedTask; diff --git a/examples/MinimalLambda.Example.Lifecycle/Properties/launchSettings.json b/examples/MinimalLambda.Example.Lifecycle/Properties/launchSettings.json index a348821c..0059dfcb 100644 --- a/examples/MinimalLambda.Example.Lifecycle/Properties/launchSettings.json +++ b/examples/MinimalLambda.Example.Lifecycle/Properties/launchSettings.json @@ -7,7 +7,8 @@ "AWS_LAMBDA_RUNTIME_API": "localhost:5050", "DOTNET_ENVIRONMENT": "Development", "AWS_LAMBDA_LOG_FORMAT": "JSON", - "AWS_LAMBDA_LOG_LEVEL": "DEBUG" + "AWS_LAMBDA_LOG_LEVEL": "DEBUG", + "AWS_LAMBDA_FUNCTION_NAME": "MinimalLambda.Example.Lifecycle" } } } diff --git a/src/MinimalLambda.Abstractions/Builders/ILambdaOnInitBuilder.cs b/src/MinimalLambda.Abstractions/Builders/ILambdaOnInitBuilder.cs index f86f1e70..4343d8fb 100644 --- a/src/MinimalLambda.Abstractions/Builders/ILambdaOnInitBuilder.cs +++ b/src/MinimalLambda.Abstractions/Builders/ILambdaOnInitBuilder.cs @@ -1,3 +1,5 @@ +using System.Collections.Concurrent; + namespace MinimalLambda.Builder; /// Builder for composing Lambda init handlers that execute during the Init phase. @@ -18,6 +20,9 @@ public interface ILambdaOnInitBuilder /// Gets the read-only list of registered Init handlers. IReadOnlyList InitHandlers { get; } + /// Gets a dictionary for storing state that is shared between handlers. + ConcurrentDictionary Properties { get; } + /// Gets the service provider for dependency injection. IServiceProvider Services { get; } @@ -39,5 +44,5 @@ public interface ILambdaOnInitBuilder /// A function that accepts a and executes all registered /// handlers concurrently. Ready for the Lambda Init phase. /// - Func> Build(); + Func>? Build(); } diff --git a/src/MinimalLambda.Abstractions/Builders/ILambdaOnShutdownBuilder.cs b/src/MinimalLambda.Abstractions/Builders/ILambdaOnShutdownBuilder.cs index 736c6b53..2a3dc4c9 100644 --- a/src/MinimalLambda.Abstractions/Builders/ILambdaOnShutdownBuilder.cs +++ b/src/MinimalLambda.Abstractions/Builders/ILambdaOnShutdownBuilder.cs @@ -1,3 +1,5 @@ +using System.Collections.Concurrent; + namespace MinimalLambda.Builder; /// Builder for composing Lambda shutdown handlers that execute during the Shutdown phase. @@ -17,6 +19,9 @@ public interface ILambdaOnShutdownBuilder /// Gets the service provider for dependency injection. IServiceProvider Services { get; } + /// Gets a dictionary for storing state that is shared between handlers. + ConcurrentDictionary Properties { get; } + /// Gets the read-only list of registered shutdown handlers. IReadOnlyList ShutdownHandlers { get; } diff --git a/src/MinimalLambda.Abstractions/Core/ILambdaLifecycleContext.cs b/src/MinimalLambda.Abstractions/Core/ILambdaLifecycleContext.cs new file mode 100644 index 00000000..eb935f5d --- /dev/null +++ b/src/MinimalLambda.Abstractions/Core/ILambdaLifecycleContext.cs @@ -0,0 +1,106 @@ +namespace MinimalLambda; + +/// +/// Encapsulates the information available during Lambda lifecycle events such as +/// initialization and shutdown. +/// +public interface ILambdaLifecycleContext +{ + /// + /// Gets the that signals the Lambda lifecycle event is being + /// canceled. + /// + /// + /// The cancellation token will also be cancelled if a SIGTERM signal is received, indicting + /// that the Lambda runtime is being terminated. + /// + CancellationToken CancellationToken { get; } + + /// Gets or sets a key/value collection that can be used to share data between handlers. + IDictionary Properties { get; } + + /// + /// Gets or sets the that provides access to the invocation's + /// service container. + /// + IServiceProvider ServiceProvider { get; } + + /// Gets the elapsed time since the Lambda execution environment was started. + TimeSpan ElapsedTime { get; } + + /// Gets the AWS region where the Lambda function is running, or null if not set. + /// + /// This value is read from the AWS_REGION environment variable. If both + /// AWS_REGION and AWS_DEFAULT_REGION are set, AWS_REGION takes precedence. + /// + string? Region { get; } + + /// Gets the runtime identifier, or null if not set. + /// + /// This value is read from the AWS_EXECUTION_ENV environment variable, which is + /// prefixed by AWS_Lambda_ (for example, AWS_Lambda_dotnet8). This environment + /// variable is not defined for OS-only runtimes. + /// + string? ExecutionEnvironment { get; } + + /// Gets the name of the Lambda function, or null if not set. + /// + /// This value is read from the AWS_LAMBDA_FUNCTION_NAME environment variable set by + /// AWS Lambda at cold start. + /// + string? FunctionName { get; } + + /// + /// Gets the amount of memory available to the function in MB, or null if not set or + /// cannot be parsed. + /// + /// + /// This value is read from the AWS_LAMBDA_FUNCTION_MEMORY_SIZE environment variable + /// set by AWS Lambda at cold start. + /// + int? FunctionMemorySize { get; } + + /// Gets the version of the function being executed, or null if not set. + /// + /// This value is read from the AWS_LAMBDA_FUNCTION_VERSION environment variable set by + /// AWS Lambda at cold start. + /// + string? FunctionVersion { get; } + + /// Gets the initialization type of the function, or null if not set. + /// + /// This value is read from the AWS_LAMBDA_INITIALIZATION_TYPE environment variable. + /// Possible values include: on-demand, provisioned-concurrency, snap-start, + /// or lambda-managed-instances. + /// + string? InitializationType { get; } + + /// + /// Gets the name of the Amazon CloudWatch Logs group for the function, or null if not + /// set. + /// + /// + /// This value is read from the AWS_LAMBDA_LOG_GROUP_NAME environment variable set by + /// AWS Lambda at cold start. This environment variable is not available in Lambda SnapStart + /// functions. + /// + string? LogGroupName { get; } + + /// + /// Gets the name of the Amazon CloudWatch Logs stream for the function, or null if not + /// set. + /// + /// + /// This value is read from the AWS_LAMBDA_LOG_STREAM_NAME environment variable set by + /// AWS Lambda at cold start. This environment variable is not available in Lambda SnapStart + /// functions. + /// + string? LogStreamName { get; } + + /// Gets the path to the Lambda function code, or null if not set. + /// + /// This value is read from the LAMBDA_TASK_ROOT environment variable set by AWS Lambda + /// at cold start. + /// + string? TaskRoot { get; } +} diff --git a/src/MinimalLambda.Abstractions/Delegates/LambdaInitDelegate.cs b/src/MinimalLambda.Abstractions/Delegates/LambdaInitDelegate.cs index 8f55cd8a..0165123d 100644 --- a/src/MinimalLambda.Abstractions/Delegates/LambdaInitDelegate.cs +++ b/src/MinimalLambda.Abstractions/Delegates/LambdaInitDelegate.cs @@ -4,15 +4,14 @@ namespace MinimalLambda; /// A callback delegate invoked during the AWS Lambda Function Init phase, before any handler /// invocation. /// -/// A scoped for resolving dependencies. -/// Signals the handler to stop during the Function Init phase. +/// +/// The providing access to the scoped +/// and for the Function Init phase. +/// /// /// A that completes with true to allow the Function Init /// phase to continue, or false to abort the Function Init phase. Exceptions thrown are /// collected and rethrown after all delegates complete. /// /// -public delegate Task LambdaInitDelegate( - IServiceProvider services, - CancellationToken cancellationToken -); +public delegate Task LambdaInitDelegate(ILambdaLifecycleContext context); diff --git a/src/MinimalLambda.Abstractions/Delegates/LambdaShutdownDelegate.cs b/src/MinimalLambda.Abstractions/Delegates/LambdaShutdownDelegate.cs index 881215aa..65b64a32 100644 --- a/src/MinimalLambda.Abstractions/Delegates/LambdaShutdownDelegate.cs +++ b/src/MinimalLambda.Abstractions/Delegates/LambdaShutdownDelegate.cs @@ -1,14 +1,10 @@ namespace MinimalLambda; /// A callback delegate invoked during the AWS Lambda Function Shutdown phase. -/// A scoped for resolving dependencies. -/// -/// Signals the handler to stop. Expires before the Lambda runtime's -/// hard timeout. +/// +/// The providing access to the scoped +/// and for the Function Shutdown phase. /// /// A representing the shutdown operation. /// -public delegate Task LambdaShutdownDelegate( - IServiceProvider services, - CancellationToken cancellationToken -); +public delegate Task LambdaShutdownDelegate(ILambdaLifecycleContext context); diff --git a/src/MinimalLambda.OpenTelemetry/MinimalLambda.OpenTelemetry.csproj b/src/MinimalLambda.OpenTelemetry/MinimalLambda.OpenTelemetry.csproj index a34277e2..24c2b1ea 100644 --- a/src/MinimalLambda.OpenTelemetry/MinimalLambda.OpenTelemetry.csproj +++ b/src/MinimalLambda.OpenTelemetry/MinimalLambda.OpenTelemetry.csproj @@ -11,9 +11,16 @@ MinimalLambda.OpenTelemetry OpenTelemetry integration for MinimalLambda README.md + $(InterceptorsNamespaces);MinimalLambda.Generated + + diff --git a/src/MinimalLambda.OpenTelemetry/OnShutdownOpenTelemetryExtensions.cs b/src/MinimalLambda.OpenTelemetry/OnShutdownOpenTelemetryExtensions.cs index 3ce38533..f97d8fd2 100644 --- a/src/MinimalLambda.OpenTelemetry/OnShutdownOpenTelemetryExtensions.cs +++ b/src/MinimalLambda.OpenTelemetry/OnShutdownOpenTelemetryExtensions.cs @@ -79,7 +79,7 @@ public ILambdaOnShutdownBuilder OnShutdownFlushTracer( ?? NullLogger.Instance; application.OnShutdown( - (_, cancellationToken) => + (CancellationToken cancellationToken) => RunForceFlush( "tracer", tracerProvider.ForceFlush, @@ -123,7 +123,7 @@ public ILambdaOnShutdownBuilder OnShutdownFlushMeter( ?? NullLogger.Instance; application.OnShutdown( - (_, cancellationToken) => + (CancellationToken cancellationToken) => RunForceFlush( "meter", meterProvider.ForceFlush, diff --git a/src/MinimalLambda.SourceGenerators/Extensions/DelegateInfoExtensions.cs b/src/MinimalLambda.SourceGenerators/Extensions/DelegateInfoExtensions.cs index 62c2d14b..b2355feb 100644 --- a/src/MinimalLambda.SourceGenerators/Extensions/DelegateInfoExtensions.cs +++ b/src/MinimalLambda.SourceGenerators/Extensions/DelegateInfoExtensions.cs @@ -44,4 +44,33 @@ internal static string BuildHandlerSignature(this DelegateInfo delegateInfo) return handlerSignature; } + + extension(DelegateInfo delegateInfo) + { + internal string BuildHandlerCastCall() + { + var signatureBuilder = new StringBuilder(); + signatureBuilder.Append("Cast(handler, "); + + signatureBuilder.Append(delegateInfo.ReturnTypeInfo.FullyQualifiedType); + + signatureBuilder.Append(" ("); + + signatureBuilder.Append( + string.Join( + ", ", + delegateInfo.Parameters.Select( + (p, i) => + $"{p.TypeInfo.FullyQualifiedType} arg{i}{(p.IsOptional ? " = default" : "")}" + ) + ) + ); + + signatureBuilder.Append(") => throw null!)"); + + var handlerSignature = signatureBuilder.ToString(); + + return handlerSignature; + } + } } diff --git a/src/MinimalLambda.SourceGenerators/GeneratorConstants.cs b/src/MinimalLambda.SourceGenerators/GeneratorConstants.cs index 0ab2717f..92219875 100644 --- a/src/MinimalLambda.SourceGenerators/GeneratorConstants.cs +++ b/src/MinimalLambda.SourceGenerators/GeneratorConstants.cs @@ -7,6 +7,8 @@ internal static class TypeConstants internal const string ILambdaHostContext = "global::MinimalLambda.ILambdaHostContext"; + internal const string ILambdaLifecycleContext = "global::MinimalLambda.ILambdaLifecycleContext"; + internal const string CancellationToken = "global::System.Threading.CancellationToken"; internal const string Task = "global::System.Threading.Tasks.Task"; diff --git a/src/MinimalLambda.SourceGenerators/Models/ParameterInfo.cs b/src/MinimalLambda.SourceGenerators/Models/ParameterInfo.cs index 50ad63e1..f2290859 100644 --- a/src/MinimalLambda.SourceGenerators/Models/ParameterInfo.cs +++ b/src/MinimalLambda.SourceGenerators/Models/ParameterInfo.cs @@ -69,8 +69,9 @@ private static ( return type switch { TypeConstants.CancellationToken => (ParameterSource.CancellationToken, null), - TypeConstants.ILambdaContext => (ParameterSource.Context, null), - TypeConstants.ILambdaHostContext => (ParameterSource.Context, null), + TypeConstants.ILambdaContext => (ParameterSource.HostContext, null), + TypeConstants.ILambdaHostContext => (ParameterSource.HostContext, null), + TypeConstants.ILambdaLifecycleContext => (ParameterSource.LifecycleContext, null), _ => (ParameterSource.Service, null), }; } diff --git a/src/MinimalLambda.SourceGenerators/Models/ParameterSource.cs b/src/MinimalLambda.SourceGenerators/Models/ParameterSource.cs index 1aad9519..61315319 100644 --- a/src/MinimalLambda.SourceGenerators/Models/ParameterSource.cs +++ b/src/MinimalLambda.SourceGenerators/Models/ParameterSource.cs @@ -5,6 +5,7 @@ internal enum ParameterSource Event, KeyedService, CancellationToken, - Context, + HostContext, + LifecycleContext, Service, } diff --git a/src/MinimalLambda.SourceGenerators/OutputGenerators/GenericHandlerSources.cs b/src/MinimalLambda.SourceGenerators/OutputGenerators/GenericHandlerSources.cs index cb78475f..a14df034 100644 --- a/src/MinimalLambda.SourceGenerators/OutputGenerators/GenericHandlerSources.cs +++ b/src/MinimalLambda.SourceGenerators/OutputGenerators/GenericHandlerSources.cs @@ -40,7 +40,7 @@ string generatedCodeAttribute .Select(higherOrderMethodInfo => { // build handler function signature - var handlerSignature = higherOrderMethodInfo.DelegateInfo.BuildHandlerSignature(); + var handlerSignature = higherOrderMethodInfo.DelegateInfo.BuildHandlerCastCall(); // get arguments for handler var handlerArgs = @@ -129,22 +129,26 @@ private static HandlerArg[] BuildHandlerParameterAssignment(this DelegateInfo de Assignment = param.Source switch { // CancellationToken -> get directly from arguments - ParameterSource.CancellationToken => "cancellationToken", + ParameterSource.CancellationToken => "context.CancellationToken", + + // ILambdaLifecycleContext -> get directly from arguments + ParameterSource.LifecycleContext => "context", // inject keyed service from the DI container - required ParameterSource.KeyedService when param.IsRequired => - $"serviceProvider.GetRequiredKeyedService<{param.TypeInfo.FullyQualifiedType}>({param.KeyedServiceKey?.DisplayValue})", + $"context.ServiceProvider.GetRequiredKeyedService<{param.TypeInfo.FullyQualifiedType}>({param.KeyedServiceKey?.DisplayValue})", // inject keyed service from the DI container - optional ParameterSource.KeyedService => - $"serviceProvider.GetKeyedService<{param.TypeInfo.FullyQualifiedType}>({param.KeyedServiceKey?.DisplayValue})", + $"context.ServiceProvider.GetKeyedService<{param.TypeInfo.FullyQualifiedType}>({param.KeyedServiceKey?.DisplayValue})", // default: inject service from the DI container - required _ when param.IsRequired => - $"serviceProvider.GetRequiredService<{param.TypeInfo.FullyQualifiedType}>()", + $"context.ServiceProvider.GetRequiredService<{param.TypeInfo.FullyQualifiedType}>()", // default: inject service from the DI container - optional - _ => $"serviceProvider.GetService<{param.TypeInfo.FullyQualifiedType}>()", + _ => + $"context.ServiceProvider.GetService<{param.TypeInfo.FullyQualifiedType}>()", }, }) .ToArray(); diff --git a/src/MinimalLambda.SourceGenerators/OutputGenerators/MapHandlerSources.cs b/src/MinimalLambda.SourceGenerators/OutputGenerators/MapHandlerSources.cs index 323461f3..5a0cf96e 100644 --- a/src/MinimalLambda.SourceGenerators/OutputGenerators/MapHandlerSources.cs +++ b/src/MinimalLambda.SourceGenerators/OutputGenerators/MapHandlerSources.cs @@ -91,7 +91,7 @@ private static HandlerArg[] BuildHandlerParameterAssignment(this DelegateInfo de $"context.GetRequiredEvent<{param.TypeInfo.FullyQualifiedType}>()", // ILambdaContext OR ILambdaHostContext -> use context directly - ParameterSource.Context => "context", + ParameterSource.HostContext => "context", // CancellationToken -> get from context ParameterSource.CancellationToken => "context.CancellationToken", diff --git a/src/MinimalLambda.SourceGenerators/SyntaxProviders/OnInitSyntaxProvider.cs b/src/MinimalLambda.SourceGenerators/SyntaxProviders/OnInitSyntaxProvider.cs index c15e97ad..c94bcced 100644 --- a/src/MinimalLambda.SourceGenerators/SyntaxProviders/OnInitSyntaxProvider.cs +++ b/src/MinimalLambda.SourceGenerators/SyntaxProviders/OnInitSyntaxProvider.cs @@ -22,8 +22,7 @@ private static bool IsBaseOnShutdownCall(this DelegateInfo delegateInfo) => is { ReturnTypeInfo.FullyQualifiedType: TypeConstants.TaskBool, Parameters: [ - { TypeInfo.FullyQualifiedType: TypeConstants.IServiceProvider }, - { TypeInfo.FullyQualifiedType: TypeConstants.CancellationToken }, + { TypeInfo.FullyQualifiedType: TypeConstants.ILambdaLifecycleContext }, ], }; } diff --git a/src/MinimalLambda.SourceGenerators/SyntaxProviders/OnShutdownSyntaxProvider.cs b/src/MinimalLambda.SourceGenerators/SyntaxProviders/OnShutdownSyntaxProvider.cs index b96bf94b..142643ea 100644 --- a/src/MinimalLambda.SourceGenerators/SyntaxProviders/OnShutdownSyntaxProvider.cs +++ b/src/MinimalLambda.SourceGenerators/SyntaxProviders/OnShutdownSyntaxProvider.cs @@ -22,8 +22,7 @@ private static bool IsBaseOnShutdownCall(this DelegateInfo delegateInfo) => is { ReturnTypeInfo.FullyQualifiedType: TypeConstants.Task, Parameters: [ - { TypeInfo.FullyQualifiedType: TypeConstants.IServiceProvider }, - { TypeInfo.FullyQualifiedType: TypeConstants.CancellationToken }, + { TypeInfo.FullyQualifiedType: TypeConstants.ILambdaLifecycleContext }, ], }; } diff --git a/src/MinimalLambda.SourceGenerators/Templates/GenericHandler.scriban b/src/MinimalLambda.SourceGenerators/Templates/GenericHandler.scriban index acfbb6f0..6773aac6 100644 --- a/src/MinimalLambda.SourceGenerators/Templates/GenericHandler.scriban +++ b/src/MinimalLambda.SourceGenerators/Templates/GenericHandler.scriban @@ -12,21 +12,20 @@ namespace MinimalLambda.Generated file static class GeneratedLambda{{ name }}BuilderExtensions { {{~ for call in calls ~}} - // Location: {{ call.location.display_location }} [InterceptsLocation({{ call.location.version }}, "{{ call.location.data }}")] internal static {{ call.target_type }} {{ name }}Interceptor{{ for.index }}{{ call.generic_parameters }}( this {{ call.target_type }} application, Delegate handler ) { - var castHandler = ({{ call.handler_signature }})handler; + var castHandler = {{ call.handler_signature }}; return application.{{ name }}({{ name }}); - {{ if call.should_await ~}} async {{ end ~}}{{ call.wrapper_return_type }} {{ name }}(IServiceProvider serviceProvider, CancellationToken cancellationToken) + {{ if call.should_await ~}} async {{ end ~}}{{ call.wrapper_return_type }} {{ name }}(ILambdaLifecycleContext context) { {{~ if call.has_any_keyed_service_parameter ~}} - if (serviceProvider.GetService() is not IServiceProviderIsKeyedService) + if (context.ServiceProvider.GetService() is not IServiceProviderIsKeyedService) { throw new InvalidOperationException($"Unable to resolve service referenced by {nameof(FromKeyedServicesAttribute)}. The service provider doesn't support keyed services."); } @@ -51,5 +50,7 @@ namespace MinimalLambda.Generated {{~ end ~}} {{~ end ~}} + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/src/MinimalLambda.SourceGenerators/Templates/MapHandler.scriban b/src/MinimalLambda.SourceGenerators/Templates/MapHandler.scriban index 4d829209..3861e045 100644 --- a/src/MinimalLambda.SourceGenerators/Templates/MapHandler.scriban +++ b/src/MinimalLambda.SourceGenerators/Templates/MapHandler.scriban @@ -15,7 +15,6 @@ namespace MinimalLambda.Generated private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; {{~ for call in map_handler_calls ~}} - // Location: {{ call.location.display_location }} [InterceptsLocation({{ call.location.version }}, "{{ call.location.data }}")] internal static ILambdaInvocationBuilder MapHandlerInterceptor{{ for.index }}( this ILambdaInvocationBuilder application, diff --git a/src/MinimalLambda/Builder/DefaultLambdaOnInitBuilderFactory.cs b/src/MinimalLambda/Builder/DefaultLambdaOnInitBuilderFactory.cs index bde176c7..7e73887f 100644 --- a/src/MinimalLambda/Builder/DefaultLambdaOnInitBuilderFactory.cs +++ b/src/MinimalLambda/Builder/DefaultLambdaOnInitBuilderFactory.cs @@ -6,9 +6,10 @@ namespace MinimalLambda.Builder; internal class DefaultLambdaOnInitBuilderFactory( IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) : ILambdaOnInitBuilderFactory { public ILambdaOnInitBuilder CreateBuilder() => - new LambdaOnInitBuilder(serviceProvider, scopeFactory, options); + new LambdaOnInitBuilder(serviceProvider, scopeFactory, options, contextFactory); } diff --git a/src/MinimalLambda/Builder/DefaultLambdaOnShutdownBuilderFactory.cs b/src/MinimalLambda/Builder/DefaultLambdaOnShutdownBuilderFactory.cs index a9038709..cf001441 100644 --- a/src/MinimalLambda/Builder/DefaultLambdaOnShutdownBuilderFactory.cs +++ b/src/MinimalLambda/Builder/DefaultLambdaOnShutdownBuilderFactory.cs @@ -4,9 +4,10 @@ namespace MinimalLambda.Builder; internal class DefaultLambdaOnShutdownBuilderFactory( IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory + IServiceScopeFactory scopeFactory, + ILambdaLifecycleContextFactory contextFactory ) : ILambdaOnShutdownBuilderFactory { public ILambdaOnShutdownBuilder CreateBuilder() => - new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); + new LambdaOnShutdownBuilder(serviceProvider, scopeFactory, contextFactory); } diff --git a/src/MinimalLambda/Builder/Extensions/ServiceCollectionExtensions.cs b/src/MinimalLambda/Builder/Extensions/ServiceCollectionExtensions.cs index ec5fa000..3d555b2b 100644 --- a/src/MinimalLambda/Builder/Extensions/ServiceCollectionExtensions.cs +++ b/src/MinimalLambda/Builder/Extensions/ServiceCollectionExtensions.cs @@ -29,6 +29,7 @@ public IServiceCollection AddLambdaHostCoreServices() >(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); // Register internal Lambda execution components diff --git a/src/MinimalLambda/Builder/LambdaApplication.cs b/src/MinimalLambda/Builder/LambdaApplication.cs index 9f3f22e9..497f7af3 100644 --- a/src/MinimalLambda/Builder/LambdaApplication.cs +++ b/src/MinimalLambda/Builder/LambdaApplication.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -113,6 +114,10 @@ Func middleware /// public IReadOnlyList InitHandlers => _onInitBuilder.InitHandlers; + /// + ConcurrentDictionary ILambdaOnInitBuilder.Properties => + _onInitBuilder.Properties; + /// public ILambdaOnInitBuilder OnInit(LambdaInitDelegate handler) { @@ -121,7 +126,7 @@ public ILambdaOnInitBuilder OnInit(LambdaInitDelegate handler) } /// - Func> ILambdaOnInitBuilder.Build() => _onInitBuilder.Build(); + Func>? ILambdaOnInitBuilder.Build() => _onInitBuilder.Build(); // ┌──────────────────────────────────────────────────────────┐ // │ ILambdaOnShutdownBuilder │ @@ -131,6 +136,10 @@ public ILambdaOnInitBuilder OnInit(LambdaInitDelegate handler) public IReadOnlyList ShutdownHandlers => _onShutdownBuilder.ShutdownHandlers; + /// + ConcurrentDictionary ILambdaOnShutdownBuilder.Properties => + _onInitBuilder.Properties; + /// public ILambdaOnShutdownBuilder OnShutdown(LambdaShutdownDelegate handler) { diff --git a/src/MinimalLambda/Builder/LambdaApplicationBuilder.cs b/src/MinimalLambda/Builder/LambdaApplicationBuilder.cs index f8405bfd..5f296a5f 100644 --- a/src/MinimalLambda/Builder/LambdaApplicationBuilder.cs +++ b/src/MinimalLambda/Builder/LambdaApplicationBuilder.cs @@ -46,6 +46,8 @@ public sealed class LambdaApplicationBuilder : IHostApplicationBuilder /// Main internal constructor. internal LambdaApplicationBuilder(LambdaApplicationOptions? settings) { + var lifetimeStopwatch = new LifetimeStopwatch(); + settings ??= new LambdaApplicationOptions(); if (!settings.DisableDefaults) @@ -97,6 +99,7 @@ internal LambdaApplicationBuilder(LambdaApplicationOptions? settings) // Register core services that are required for Lambda Host to run Services.AddLambdaHostCoreServices(); + Services.AddSingleton(lifetimeStopwatch); } /// @@ -307,6 +310,9 @@ private void ConfigureOnInitBuilder(ILambdaOnInitBuilder builder) foreach (var handlers in _builtApplication.InitHandlers) builder.OnInit(handlers); + + foreach (var property in ((ILambdaOnInitBuilder)_builtApplication).Properties) + builder.Properties[property.Key] = property.Value; } private void ConfigureOnShutdownBuilder(ILambdaOnShutdownBuilder builder) @@ -316,5 +322,8 @@ private void ConfigureOnShutdownBuilder(ILambdaOnShutdownBuilder builder) foreach (var handlers in _builtApplication.ShutdownHandlers) builder.OnShutdown(handlers); + + foreach (var property in ((ILambdaOnShutdownBuilder)_builtApplication).Properties) + builder.Properties[property.Key] = property.Value; } } diff --git a/src/MinimalLambda/Builder/LambdaOnInitBuilder.cs b/src/MinimalLambda/Builder/LambdaOnInitBuilder.cs index 50a94ebd..1bc1dceb 100644 --- a/src/MinimalLambda/Builder/LambdaOnInitBuilder.cs +++ b/src/MinimalLambda/Builder/LambdaOnInitBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -8,24 +9,30 @@ internal class LambdaOnInitBuilder : ILambdaOnInitBuilder private readonly IList _handlers = []; private readonly LambdaHostOptions _options; private readonly IServiceScopeFactory _scopeFactory; + private readonly ILambdaLifecycleContextFactory _contextFactory; public LambdaOnInitBuilder( IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { ArgumentNullException.ThrowIfNull(serviceProvider); ArgumentNullException.ThrowIfNull(scopeFactory); ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(contextFactory); Services = serviceProvider; _scopeFactory = scopeFactory; _options = options.Value; + _contextFactory = contextFactory; } public IServiceProvider Services { get; } + public ConcurrentDictionary Properties { get; } = new(); + public IReadOnlyList InitHandlers => _handlers.AsReadOnly(); public ILambdaOnInitBuilder OnInit(LambdaInitDelegate handler) @@ -36,9 +43,9 @@ public ILambdaOnInitBuilder OnInit(LambdaInitDelegate handler) return this; } - public Func> Build() => + public Func>? Build() => _handlers.Count == 0 - ? _ => Task.FromResult(true) + ? null : async Task (stoppingToken) => { using var cts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken); @@ -46,7 +53,17 @@ public Func> Build() => var tasks = _handlers.Select(h => RunInitHandler(h, cts.Token)); - var results = await Task.WhenAll(tasks).ConfigureAwait(false); + (Exception? Error, bool ShouldContinue)[] results; + try + { + results = await Task.WhenAll(tasks).WaitAsync(cts.Token).ConfigureAwait(false); + } + catch (TaskCanceledException) when (cts.Token.IsCancellationRequested) + { + throw new OperationCanceledException( + "Running OnInit handlers did not complete within the allocated timeout period." + ); + } var (errors, shouldContinue) = results.Aggregate( (errors: new List(), shouldContinue: true), @@ -77,10 +94,14 @@ CancellationToken cancellationToken { try { - using var scope = _scopeFactory.CreateScope(); - var result = await handler(scope.ServiceProvider, cancellationToken) - .ConfigureAwait(false); - return (null, result); + var context = _contextFactory.Create(Properties, cancellationToken); + + await using (context as IAsyncDisposable) + { + using var scope = _scopeFactory.CreateScope(); + var result = await handler(context).ConfigureAwait(false); + return (null, result); + } } catch (Exception ex) { diff --git a/src/MinimalLambda/Builder/LambdaOnShutdownBuilder.cs b/src/MinimalLambda/Builder/LambdaOnShutdownBuilder.cs index be9080f4..2b11a0bd 100644 --- a/src/MinimalLambda/Builder/LambdaOnShutdownBuilder.cs +++ b/src/MinimalLambda/Builder/LambdaOnShutdownBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using Microsoft.Extensions.DependencyInjection; namespace MinimalLambda.Builder; @@ -6,20 +7,27 @@ internal class LambdaOnShutdownBuilder : ILambdaOnShutdownBuilder { private readonly IList _handlers = []; private readonly IServiceScopeFactory _scopeFactory; + private readonly ILambdaLifecycleContextFactory _contextFactory; public LambdaOnShutdownBuilder( IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory + IServiceScopeFactory scopeFactory, + ILambdaLifecycleContextFactory contextFactory ) { ArgumentNullException.ThrowIfNull(serviceProvider); ArgumentNullException.ThrowIfNull(scopeFactory); + ArgumentNullException.ThrowIfNull(contextFactory); Services = serviceProvider; _scopeFactory = scopeFactory; + _contextFactory = contextFactory; } public IServiceProvider Services { get; } + + public ConcurrentDictionary Properties { get; } = new(); + public IReadOnlyList ShutdownHandlers => _handlers.AsReadOnly(); public ILambdaOnShutdownBuilder OnShutdown(LambdaShutdownDelegate handler) @@ -55,9 +63,14 @@ CancellationToken cancellationToken { try { - using var scope = _scopeFactory.CreateScope(); - await handler(scope.ServiceProvider, cancellationToken).ConfigureAwait(false); - return null; + var context = _contextFactory.Create(Properties, cancellationToken); + + await using (context as IAsyncDisposable) + { + using var scope = _scopeFactory.CreateScope(); + await handler(context).ConfigureAwait(false); + return null; + } } catch (Exception ex) { diff --git a/src/MinimalLambda/Builder/OnInit/OutputFormattingLambdaApplicationExtensions.cs b/src/MinimalLambda/Builder/OnInit/OutputFormattingLambdaApplicationExtensions.cs index 5e6c6ad1..58ade079 100644 --- a/src/MinimalLambda/Builder/OnInit/OutputFormattingLambdaApplicationExtensions.cs +++ b/src/MinimalLambda/Builder/OnInit/OutputFormattingLambdaApplicationExtensions.cs @@ -1,4 +1,3 @@ -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace MinimalLambda.Builder; @@ -21,10 +20,8 @@ this ILambdaOnInitBuilder application ArgumentNullException.ThrowIfNull(application); application.OnInit( - Task (services, _) => + (ILogger? logger = null) => { - var logger = services.GetService>(); - // This will clear the output formatting set by the Lambda runtime. Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true }); diff --git a/src/MinimalLambda/Core/Context/ILambdaLifecycleContextFactory.cs b/src/MinimalLambda/Core/Context/ILambdaLifecycleContextFactory.cs new file mode 100644 index 00000000..5e1de4dd --- /dev/null +++ b/src/MinimalLambda/Core/Context/ILambdaLifecycleContextFactory.cs @@ -0,0 +1,9 @@ +namespace MinimalLambda; + +internal interface ILambdaLifecycleContextFactory +{ + ILambdaLifecycleContext Create( + IDictionary properties, + CancellationToken cancellationToken + ); +} diff --git a/src/MinimalLambda/Core/Context/ILifetimeStopwatch.cs b/src/MinimalLambda/Core/Context/ILifetimeStopwatch.cs new file mode 100644 index 00000000..7d5262a4 --- /dev/null +++ b/src/MinimalLambda/Core/Context/ILifetimeStopwatch.cs @@ -0,0 +1,6 @@ +namespace MinimalLambda; + +internal interface ILifetimeStopwatch +{ + TimeSpan Elapsed { get; } +} diff --git a/src/MinimalLambda/Core/Context/LambdaLifecycleContext.cs b/src/MinimalLambda/Core/Context/LambdaLifecycleContext.cs new file mode 100644 index 00000000..3b532ffc --- /dev/null +++ b/src/MinimalLambda/Core/Context/LambdaLifecycleContext.cs @@ -0,0 +1,67 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace MinimalLambda; + +internal class LambdaLifecycleContext( + LambdaLifecycleContext.Core contextCore, + IServiceScopeFactory scopeFactory, + IDictionary properties, + CancellationToken cancellationToken +) : ILambdaLifecycleContext, IAsyncDisposable +{ + private IServiceScope? _instanceServicesScope; + + public CancellationToken CancellationToken { get; } = cancellationToken; + + public IServiceProvider ServiceProvider + { + get + { + if (field is null) + { + _instanceServicesScope = scopeFactory.CreateScope(); + field = _instanceServicesScope.ServiceProvider; + } + + return field; + } + private set; + } + + public IDictionary Properties { get; } = properties; + + public TimeSpan ElapsedTime => contextCore.Stopwatch.Elapsed; + public string? Region => contextCore.Region; + public string? ExecutionEnvironment => contextCore.ExecutionEnvironment; + public string? FunctionName => contextCore.FunctionName; + public int? FunctionMemorySize => contextCore.FunctionMemorySize; + public string? FunctionVersion => contextCore.FunctionVersion; + public string? InitializationType => contextCore.InitializationType; + public string? LogGroupName => contextCore.LogGroupName; + public string? LogStreamName => contextCore.LogStreamName; + public string? TaskRoot => contextCore.TaskRoot; + + public async ValueTask DisposeAsync() + { + if (_instanceServicesScope is IAsyncDisposable instanceServicesScopeAsyncDisposable) + await instanceServicesScopeAsyncDisposable.DisposeAsync(); + + _instanceServicesScope?.Dispose(); + ServiceProvider = null!; + _instanceServicesScope = null; + } + + internal class Core + { + internal required ILifetimeStopwatch Stopwatch { get; init; } + internal string? Region { get; init; } + internal string? ExecutionEnvironment { get; init; } + internal string? FunctionName { get; init; } + internal int? FunctionMemorySize { get; init; } + internal string? FunctionVersion { get; init; } + internal string? InitializationType { get; init; } + internal string? LogGroupName { get; init; } + internal string? LogStreamName { get; init; } + internal string? TaskRoot { get; init; } + } +} diff --git a/src/MinimalLambda/Core/Context/LambdaLifecycleContextFactory.cs b/src/MinimalLambda/Core/Context/LambdaLifecycleContextFactory.cs new file mode 100644 index 00000000..247f6aa8 --- /dev/null +++ b/src/MinimalLambda/Core/Context/LambdaLifecycleContextFactory.cs @@ -0,0 +1,45 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace MinimalLambda; + +internal class LambdaLifecycleContextFactory( + IServiceScopeFactory scopeFactory, + ILifetimeStopwatch stopwatch, + IConfiguration configuration +) : ILambdaLifecycleContextFactory +{ + private LambdaLifecycleContext.Core? _contextCore; + + public ILambdaLifecycleContext Create( + IDictionary properties, + CancellationToken cancellationToken + ) + { + _contextCore ??= new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + Region = configuration["AWS_REGION"] ?? configuration["AWS_DEFAULT_REGION"], + ExecutionEnvironment = configuration["AWS_EXECUTION_ENV"], + FunctionName = configuration["AWS_LAMBDA_FUNCTION_NAME"], + FunctionMemorySize = int.TryParse( + configuration["AWS_LAMBDA_FUNCTION_MEMORY_SIZE"], + out var memorySize + ) + ? memorySize + : null, + FunctionVersion = configuration["AWS_LAMBDA_FUNCTION_VERSION"], + InitializationType = configuration["AWS_LAMBDA_INITIALIZATION_TYPE"], + LogGroupName = configuration["AWS_LAMBDA_LOG_GROUP_NAME"], + LogStreamName = configuration["AWS_LAMBDA_LOG_STREAM_NAME"], + TaskRoot = configuration["LAMBDA_TASK_ROOT"], + }; + + return new LambdaLifecycleContext( + _contextCore, + scopeFactory, + properties, + cancellationToken + ); + } +} diff --git a/src/MinimalLambda/Core/Context/LifetimeStopwatch.cs b/src/MinimalLambda/Core/Context/LifetimeStopwatch.cs new file mode 100644 index 00000000..4634884e --- /dev/null +++ b/src/MinimalLambda/Core/Context/LifetimeStopwatch.cs @@ -0,0 +1,17 @@ +using System.Diagnostics; + +namespace MinimalLambda; + +internal sealed class LifetimeStopwatch : ILifetimeStopwatch +{ + private readonly Stopwatch _stopwatch = Stopwatch.StartNew(); + + public TimeSpan Elapsed + { + get + { + Thread.MemoryBarrier(); + return _stopwatch.Elapsed; + } + } +} diff --git a/src/MinimalLambda/MinimalLambda.csproj b/src/MinimalLambda/MinimalLambda.csproj index 4c1e3202..8e40ee54 100644 --- a/src/MinimalLambda/MinimalLambda.csproj +++ b/src/MinimalLambda/MinimalLambda.csproj @@ -11,6 +11,7 @@ MinimalLambda Minimal API-style framework for AWS Lambda functions README.md + $(InterceptorsNamespaces);MinimalLambda.Generated @@ -37,6 +38,7 @@ diff --git a/src/MinimalLambda/Runtime/LambdaHostedService.cs b/src/MinimalLambda/Runtime/LambdaHostedService.cs index c1ccd572..a15fef62 100644 --- a/src/MinimalLambda/Runtime/LambdaHostedService.cs +++ b/src/MinimalLambda/Runtime/LambdaHostedService.cs @@ -153,7 +153,7 @@ public async Task StopAsync(CancellationToken cancellationToken) /// Executes the Lambda hosting environment startup sequence. private async Task ExecuteAsync( Func> handler, - Func> initializer, + Func>? initializer, CancellationToken stoppingToken ) { diff --git a/tests/MinimalLambda.OpenTelemetry.UnitTests/OnShutdownOpenTelemetryExtensionsTests.cs b/tests/MinimalLambda.OpenTelemetry.UnitTests/OnShutdownOpenTelemetryExtensionsTests.cs index 4640433a..b5b66bb1 100644 --- a/tests/MinimalLambda.OpenTelemetry.UnitTests/OnShutdownOpenTelemetryExtensionsTests.cs +++ b/tests/MinimalLambda.OpenTelemetry.UnitTests/OnShutdownOpenTelemetryExtensionsTests.cs @@ -71,13 +71,13 @@ public async Task OnShutdownFlushTracer_RegistersShutdownHandler_AndSuccessfully LambdaShutdownDelegate? capturedShutdownAction = null; var mockApp = CreateMockApp(a => capturedShutdownAction = a); - var mockServiceProvider = Substitute.For(); + var mockContext = Substitute.For(); // Act var result = mockApp.OnShutdownFlushTracer(); capturedShutdownAction.Should().NotBeNull(); - await capturedShutdownAction.Invoke(mockServiceProvider, CancellationToken.None); + await capturedShutdownAction.Invoke(mockContext); // Assert result.Should().Be(mockApp); @@ -106,13 +106,13 @@ public async Task OnShutdownFlushTracer_RegistersShutdownHandler_AndFailedFlushe options => options.TracerShouldSucceed = false ); - var mockServiceProvider = Substitute.For(); + var mockContext = Substitute.For(); // Act var result = mockApp.OnShutdownFlushTracer(); capturedShutdownAction.Should().NotBeNull(); - await capturedShutdownAction.Invoke(mockServiceProvider, CancellationToken.None); + await capturedShutdownAction.Invoke(mockContext); // Assert result.Should().Be(mockApp); @@ -141,13 +141,14 @@ public async Task OnShutdownFlushTracer_RegistersShutdownHandler_AndCanceledFlus options => options.TracerDelay = TimeSpan.FromMilliseconds(10) ); - var mockServiceProvider = Substitute.For(); + var mockContext = Substitute.For(); + mockContext.CancellationToken.Returns(new CancellationToken(true)); // Act var result = mockApp.OnShutdownFlushTracer(); capturedShutdownAction.Should().NotBeNull(); - await capturedShutdownAction.Invoke(mockServiceProvider, new CancellationToken(true)); + await capturedShutdownAction.Invoke(mockContext); // Assert result.Should().Be(mockApp); @@ -229,13 +230,13 @@ public async Task OnShutdownFlushMeter_RegistersShutdownHandler_AndSuccessfullyF LambdaShutdownDelegate? capturedShutdownAction = null; var mockApp = CreateMockApp(a => capturedShutdownAction = a); - var mockServiceProvider = Substitute.For(); + var mockContext = Substitute.For(); // Act var result = mockApp.OnShutdownFlushMeter(); capturedShutdownAction.Should().NotBeNull(); - await capturedShutdownAction.Invoke(mockServiceProvider, CancellationToken.None); + await capturedShutdownAction.Invoke(mockContext); // Assert result.Should().Be(mockApp); @@ -264,13 +265,12 @@ public async Task OnShutdownFlushMeter_RegistersShutdownHandler_AndFailedFlushes options => options.MeterShouldSucceed = false ); - var mockServiceProvider = Substitute.For(); - + var mockContext = Substitute.For(); // Act var result = mockApp.OnShutdownFlushMeter(); capturedShutdownAction.Should().NotBeNull(); - await capturedShutdownAction.Invoke(mockServiceProvider, CancellationToken.None); + await capturedShutdownAction.Invoke(mockContext); // Assert result.Should().Be(mockApp); @@ -299,13 +299,14 @@ public async Task OnShutdownFlushMeter_RegistersShutdownHandler_AndCanceledFlush options => options.MeterDelay = TimeSpan.FromMilliseconds(10) ); - var mockServiceProvider = Substitute.For(); + var mockContext = Substitute.For(); + mockContext.CancellationToken.Returns(new CancellationToken(true)); // Act var result = mockApp.OnShutdownFlushMeter(); capturedShutdownAction.Should().NotBeNull(); - await capturedShutdownAction.Invoke(mockServiceProvider, new CancellationToken(true)); + await capturedShutdownAction.Invoke(mockContext); // Assert result.Should().Be(mockApp); @@ -389,14 +390,14 @@ public async Task OnShutdownFlushOpenTelemetry_BothFlushesBothSucceed() var shutdownActions = new List(); var mockApp = CreateMockApp(a => shutdownActions.Add(a)); - var mockServiceProvider = Substitute.For(); + var mockContext = Substitute.For(); // Act var result = mockApp.OnShutdownFlushOpenTelemetry(); shutdownActions.Should().HaveCount(2); - await shutdownActions[0].Invoke(mockServiceProvider, CancellationToken.None); - await shutdownActions[1].Invoke(mockServiceProvider, CancellationToken.None); + await shutdownActions[0].Invoke(mockContext); + await shutdownActions[1].Invoke(mockContext); // Assert result.Should().Be(mockApp); @@ -432,14 +433,14 @@ public async Task OnShutdownFlushOpenTelemetry_TracerFailsButMeterSucceeds() options => options.TracerShouldSucceed = false ); - var mockServiceProvider = Substitute.For(); + var mockContext = Substitute.For(); // Act var result = mockApp.OnShutdownFlushOpenTelemetry(); shutdownActions.Should().HaveCount(2); - await shutdownActions[0].Invoke(mockServiceProvider, CancellationToken.None); - await shutdownActions[1].Invoke(mockServiceProvider, CancellationToken.None); + await shutdownActions[0].Invoke(mockContext); + await shutdownActions[1].Invoke(mockContext); // Assert result.Should().Be(mockApp); @@ -475,14 +476,14 @@ public async Task OnShutdownFlushOpenTelemetry_MeterFailsButTracerSucceeds() options => options.MeterShouldSucceed = false ); - var mockServiceProvider = Substitute.For(); + var mockContext = Substitute.For(); // Act var result = mockApp.OnShutdownFlushOpenTelemetry(); shutdownActions.Should().HaveCount(2); - await shutdownActions[0].Invoke(mockServiceProvider, CancellationToken.None); - await shutdownActions[1].Invoke(mockServiceProvider, CancellationToken.None); + await shutdownActions[0].Invoke(mockContext); + await shutdownActions[1].Invoke(mockContext); // Assert result.Should().Be(mockApp); @@ -522,15 +523,15 @@ public async Task OnShutdownFlushOpenTelemetry_BothFlushesTimeout() } ); - var mockServiceProvider = Substitute.For(); - var cancellationToken = new CancellationToken(true); + var mockContext = Substitute.For(); + mockContext.CancellationToken.Returns(new CancellationToken(true)); // Act var result = mockApp.OnShutdownFlushOpenTelemetry(); shutdownActions.Should().HaveCount(2); - await shutdownActions[0].Invoke(mockServiceProvider, cancellationToken); - await shutdownActions[1].Invoke(mockServiceProvider, cancellationToken); + await shutdownActions[0].Invoke(mockContext); + await shutdownActions[1].Invoke(mockContext); // Assert result.Should().Be(mockApp); diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_AllInputSources#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_AllInputSources#LambdaHandler.g.verified.cs index 8216dce2..8865e8ab 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_AllInputSources#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_AllInputSources#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(14,8) [InterceptsLocation(1, "Tx1x72WT0aa+xpOr41o/dzsBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, @@ -68,7 +67,7 @@ Task InvocationDelegate(ILambdaHostContext context) } // ParameterInfo { Type = string, Name = request, Source = Event, IsNullable = False, IsOptional = False} var arg0 = context.GetRequiredEvent(); - // ParameterInfo { Type = global::Amazon.Lambda.Core.ILambdaContext, Name = context, Source = Context, IsNullable = False, IsOptional = False} + // ParameterInfo { Type = global::Amazon.Lambda.Core.ILambdaContext, Name = context, Source = HostContext, IsNullable = False, IsOptional = False} var arg1 = context; // ParameterInfo { Type = global::System.Threading.CancellationToken, Name = cancellationToken, Source = CancellationToken, IsNullable = False, IsOptional = False} var arg2 = context.CancellationToken; diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_Async_ReturnTaskString_TypeCast#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_Async_ReturnTaskString_TypeCast#LambdaHandler.g.verified.cs index 766b7934..1d67804f 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_Async_ReturnTaskString_TypeCast#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_Async_ReturnTaskString_TypeCast#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "RRgc5MNn+AL4pWTKQhrXsLYAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_NoReturn_TypeCast#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_NoReturn_TypeCast#LambdaHandler.g.verified.cs index d675980b..0e826285 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_NoReturn_TypeCast#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_NoReturn_TypeCast#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "x0XA1nde6vAUjFMeY2ZDTdoAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_NoTypeInfo_TypeCast#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_NoTypeInfo_TypeCast#LambdaHandler.g.verified.cs index a84f597d..179c0121 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_NoTypeInfo_TypeCast#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_NoTypeInfo_TypeCast#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "uvqLvSSclxUXzwz2YmfzRrwAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnExplicitType#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnExplicitType#LambdaHandler.g.verified.cs index 341b6b4b..acfd56a5 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnExplicitType#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnExplicitType#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "nm5FtUI+NJquLXB1CZ0sIswAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnImplicitNullable#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnImplicitNullable#LambdaHandler.g.verified.cs index 6e4fdd97..a993341e 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnImplicitNullable#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnImplicitNullable#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(8,8) [InterceptsLocation(1, "utXmh7WLuYyG7VwRDFaLbq4AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnString#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnString#LambdaHandler.g.verified.cs index e85d05a1..250a9a86 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnString#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnString#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(8,8) [InterceptsLocation(1, "YyltEHxaNav+M48OGFvSga4AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnTaskString#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnTaskString#LambdaHandler.g.verified.cs index bafd7788..bbe64432 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnTaskString#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnTaskString#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(12,8) [InterceptsLocation(1, "o/ULBbkPcz16o9tbQ0tOEPcAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnsTask_TypeCast#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnsTask_TypeCast#LambdaHandler.g.verified.cs index 0816cbf6..0150e0e3 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnsTask_TypeCast#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_ReturnsTask_TypeCast#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "2aTdwJdHl473WaMveiNuirYAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_StreamResponse#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_StreamResponse#LambdaHandler.g.verified.cs index d814c365..2c471368 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_StreamResponse#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_StreamResponse#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "jPT53Ewh7xx9P9yb1DeyM8AAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_TypeCast#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_TypeCast#LambdaHandler.g.verified.cs index b5b5f3b8..bdd18c50 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_TypeCast#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_TypeCast#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "SZ39GgPCyw+sAyqV7Y0MlLwAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_TypeCast_InputFromKeyedServices#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_TypeCast_InputFromKeyedServices#LambdaHandler.g.verified.cs index d331ced7..73239331 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_TypeCast_InputFromKeyedServices#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/BlockLambdaVerifyTests.Test_BlockLambda_TypeCast_InputFromKeyedServices#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(11,8) [InterceptsLocation(1, "2G3T5x4NjDpOFGweblm35AoBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationToken#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationToken#LambdaHandler.g.verified.cs index 5556169d..c3cd6db9 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationToken#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationToken#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "uuDt15jObMe1Qq8s3gllzMYAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationTokenAndLambdaContext#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationTokenAndLambdaContext#LambdaHandler.g.verified.cs index b5a09837..9441ab08 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationTokenAndLambdaContext#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationTokenAndLambdaContext#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "E0m79hZz+OhoP5DYhe70YeAAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, @@ -64,7 +63,7 @@ Task InvocationDelegate(ILambdaHostContext context) { // ParameterInfo { Type = global::System.Threading.CancellationToken, Name = ct, Source = CancellationToken, IsNullable = False, IsOptional = False} var arg0 = context.CancellationToken; - // ParameterInfo { Type = global::Amazon.Lambda.Core.ILambdaContext, Name = ctx, Source = Context, IsNullable = False, IsOptional = False} + // ParameterInfo { Type = global::Amazon.Lambda.Core.ILambdaContext, Name = ctx, Source = HostContext, IsNullable = False, IsOptional = False} var arg1 = context; var response = castHandler.Invoke(arg0, arg1); if (context.Features.Get() is not IResponseFeature responseFeature) diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationTokenAndLambdaHostContext#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationTokenAndLambdaHostContext#LambdaHandler.g.verified.cs index 9dcd01b5..d8b5ec2f 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationTokenAndLambdaHostContext#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_AsksForCancellationTokenAndLambdaHostContext#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "FpwfFi8HLWXcIbdaQfstO+AAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, @@ -64,7 +63,7 @@ Task InvocationDelegate(ILambdaHostContext context) { // ParameterInfo { Type = global::System.Threading.CancellationToken, Name = ct, Source = CancellationToken, IsNullable = False, IsOptional = False} var arg0 = context.CancellationToken; - // ParameterInfo { Type = global::MinimalLambda.ILambdaHostContext, Name = ctx, Source = Context, IsNullable = False, IsOptional = False} + // ParameterInfo { Type = global::MinimalLambda.ILambdaHostContext, Name = ctx, Source = HostContext, IsNullable = False, IsOptional = False} var arg1 = context; var response = castHandler.Invoke(arg0, arg1); if (context.Features.Get() is not IResponseFeature responseFeature) diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_Async_ReturnExplicitTask#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_Async_ReturnExplicitTask#LambdaHandler.g.verified.cs index 11082dca..14919bb0 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_Async_ReturnExplicitTask#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_Async_ReturnExplicitTask#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "cT3iuq87IWiCDKzjFXbX3swAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ComplexInput_ComplexOutput#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ComplexInput_ComplexOutput#LambdaHandler.g.verified.cs index 375863a3..707a0438 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ComplexInput_ComplexOutput#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ComplexInput_ComplexOutput#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "k8jU1POB8TXl/XtywGzhweYAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, @@ -71,7 +70,7 @@ async Task InvocationDelegate(ILambdaHostContext context) var arg0 = context.GetRequiredEvent(); // ParameterInfo { Type = global::IService, Name = service, Source = Service, IsNullable = False, IsOptional = False} var arg1 = context.ServiceProvider.GetRequiredService(); - // ParameterInfo { Type = global::Amazon.Lambda.Core.ILambdaContext, Name = context, Source = Context, IsNullable = False, IsOptional = False} + // ParameterInfo { Type = global::Amazon.Lambda.Core.ILambdaContext, Name = context, Source = HostContext, IsNullable = False, IsOptional = False} var arg2 = context; var response = await castHandler.Invoke(arg0, arg1, arg2); if (context.Features.Get() is not IResponseFeature responseFeature) diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ExplicitVoid#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ExplicitVoid#LambdaHandler.g.verified.cs index 2f19755a..268fc544 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ExplicitVoid#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ExplicitVoid#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(11,8) [InterceptsLocation(1, "mCw0TmMoKLslRA4zotAzTtkAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_Async#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_Async#LambdaHandler.g.verified.cs index c9a53e08..904e85dc 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_Async#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_Async#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "RYU1ACjUCJAF6VKP6xz4f68AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_AsyncAndAwait#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_AsyncAndAwait#LambdaHandler.g.verified.cs index 67fc5e20..d24fe6b0 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_AsyncAndAwait#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_AsyncAndAwait#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "YAxktVM2tLACcLf16mEVcc0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_AsyncAndAwait_EventAndResponseDifferentNamespace#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_AsyncAndAwait_EventAndResponseDifferentNamespace#LambdaHandler.g.verified.cs index 31044848..0d0e02e5 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_AsyncAndAwait_EventAndResponseDifferentNamespace#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputDi_AsyncAndAwait_EventAndResponseDifferentNamespace#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(11,8) [InterceptsLocation(1, "g8LHgWNG7I4SppTaP2NXcuAAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputStream#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputStream#LambdaHandler.g.verified.cs index 4a559981..65008b0d 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputStream#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_InputStream#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "j1cZzS1JRw4YpXVdsmK4icAAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_NoOutput#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_NoOutput#LambdaHandler.g.verified.cs index fc457c5e..89a04736 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_NoOutput#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_NoOutput#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "3CWFbmqnBB4YxhpsZbBulq8AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnGenericObject#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnGenericObject#LambdaHandler.g.verified.cs index ec9235fe..83e02a44 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnGenericObject#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnGenericObject#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(8,8) [InterceptsLocation(1, "G4Om3+ihXcYexFMvnSQvJ64AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnNullablePrimitive#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnNullablePrimitive#LambdaHandler.g.verified.cs index 05be05e2..97726f06 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnNullablePrimitive#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnNullablePrimitive#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(8,8) [InterceptsLocation(1, "JhcPD8PsJIdWe6XLFN10+a4AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnString#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnString#LambdaHandler.g.verified.cs index a5f9ac70..aed9f2fd 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnString#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NoInput_ReturnString#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "in+uvLWWJ/AtKXn3ATT2fa8AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NullableInput_ReturnExplicitNullable#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NullableInput_ReturnExplicitNullable#LambdaHandler.g.verified.cs index 41ec5ba6..17b19dd9 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NullableInput_ReturnExplicitNullable#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NullableInput_ReturnExplicitNullable#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(8,8) [InterceptsLocation(1, "GzrEvlSIcRHrVreaVlX6r64AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NullableInput_ReturnImplicitNullable#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NullableInput_ReturnImplicitNullable#LambdaHandler.g.verified.cs index df57ea28..d13f96a0 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NullableInput_ReturnImplicitNullable#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_NullableInput_ReturnImplicitNullable#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(8,8) [InterceptsLocation(1, "FyRpi+O01Le5sodA43elIa4AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ReturnExplicitTask#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ReturnExplicitTask#LambdaHandler.g.verified.cs index 3a6e8de8..8472525b 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ReturnExplicitTask#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ReturnExplicitTask#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "KJD4PMoAebDtIgB60tZNgswAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ReturnExplicitType#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ReturnExplicitType#LambdaHandler.g.verified.cs index dd0d0ee4..3104180d 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ReturnExplicitType#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/ExpressionLambdaVerifyTests.Test_ExpressionLambda_ReturnExplicitType#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "Omlg4OEyk26g8wXWjLDFPcwAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_FloatingPointTypes#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_FloatingPointTypes#LambdaHandler.g.verified.cs index a6929d4c..1d366b09 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_FloatingPointTypes#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_FloatingPointTypes#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(12,8) [InterceptsLocation(1, "oOoX2Z8lm6heONKgRuSEMVoBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_IntAndLongKeys#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_IntAndLongKeys#LambdaHandler.g.verified.cs index 84c351ac..46164809 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_IntAndLongKeys#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_IntAndLongKeys#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(12,8) [InterceptsLocation(1, "UQNgECJiz6f37Kqrohi6T1YBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_OtherTypes#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_OtherTypes#LambdaHandler.g.verified.cs index af67de00..7c3a39d8 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_OtherTypes#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_OtherTypes#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(14,8) [InterceptsLocation(1, "hmegcgWk2t+EeA09rekjfN0BAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_SmallIntegerTypes#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_SmallIntegerTypes#LambdaHandler.g.verified.cs index db0706ec..9deaac58 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_SmallIntegerTypes#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_SmallIntegerTypes#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(13,8) [InterceptsLocation(1, "hw5rLqU36tq+UKKZjsYo+6QBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_StringAndEnumKeys#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_StringAndEnumKeys#LambdaHandler.g.verified.cs index 9e245e3c..c02e79a2 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_StringAndEnumKeys#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_StringAndEnumKeys#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(13,8) [InterceptsLocation(1, "+h6TuNWWRrZ6456NGR3gY68BAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_UnsignedIntegerTypes#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_UnsignedIntegerTypes#LambdaHandler.g.verified.cs index 8243d625..2004666c 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_UnsignedIntegerTypes#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/KeyedServiceVerifyTests.Test_KeyedService_UnsignedIntegerTypes#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(13,8) [InterceptsLocation(1, "AxgJhn/c6EE+EjInktbZjJsBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_AsyncVoid#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_AsyncVoid#LambdaHandler.g.verified.cs index c4c248b5..c1ce7060 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_AsyncVoid#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_AsyncVoid#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "KboCfbbG13nfDrp0SLg8M7wAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_Async_ReturnTaskString#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_Async_ReturnTaskString#LambdaHandler.g.verified.cs index 92ed4fe2..513a1e18 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_Async_ReturnTaskString#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_Async_ReturnTaskString#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "ZkrKvKVefW15Q5g1yuxuRcwAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_InputDiKeyedServices#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_InputDiKeyedServices#LambdaHandler.g.verified.cs index 6fd88e89..1ff128c3 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_InputDiKeyedServices#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_InputDiKeyedServices#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(11,8) [InterceptsLocation(1, "WvA1V6ThyZ94LdZnpGUzR/kAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, @@ -73,7 +72,7 @@ Task InvocationDelegate(ILambdaHostContext context) } // ParameterInfo { Type = string, Name = input, Source = Event, IsNullable = False, IsOptional = False} var arg0 = context.GetRequiredEvent(); - // ParameterInfo { Type = global::Amazon.Lambda.Core.ILambdaContext, Name = context, Source = Context, IsNullable = False, IsOptional = False} + // ParameterInfo { Type = global::Amazon.Lambda.Core.ILambdaContext, Name = context, Source = HostContext, IsNullable = False, IsOptional = False} var arg1 = context; // ParameterInfo { Type = global::IService, Name = service, Source = KeyedService, IsNullable = False, IsOptional = False, KeyedServiceKeyInfo { DisplayValue = "key", Type = string, BaseType = object } } var arg2 = context.ServiceProvider.GetRequiredKeyedService("key"); diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_TypeCast#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_TypeCast#LambdaHandler.g.verified.cs index 2cfd58fe..c5be4fbf 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_TypeCast#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_TypeCast#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "9iVXmQzdmOJRzQb10S6vbbwAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_TypeCast_Static#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_TypeCast_Static#LambdaHandler.g.verified.cs index a36b2475..dd8a90b8 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_TypeCast_Static#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_BlockBody_TypeCast_Static#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "WkNvIuTbAdwaZik4NmqZnLwAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_NoInput_NoOutput#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_NoInput_NoOutput#LambdaHandler.g.verified.cs index 0711fa78..444d7326 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_NoInput_NoOutput#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_NoInput_NoOutput#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "+Lz+jm6gwTdwCiVkSNzQ87wAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_ReturnTask#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_ReturnTask#LambdaHandler.g.verified.cs index 95f7b33b..531f67fb 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_ReturnTask#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_ReturnTask#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "JJAuncCVlvzsQmF1nMYHRMwAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_ReturnTaskString#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_ReturnTaskString#LambdaHandler.g.verified.cs index 529a3a25..bb083dac 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_ReturnTaskString#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_ReturnTaskString#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "/Yux3FXySiMlCW6XCvraq8wAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_TypeCast_ExtraParentheses#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_TypeCast_ExtraParentheses#LambdaHandler.g.verified.cs index 2b862a26..6cc62825 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_TypeCast_ExtraParentheses#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/MethodHandlerVerifyTests.Test_MethodHandler_TypeCast_ExtraParentheses#LambdaHandler.g.verified.cs @@ -42,7 +42,6 @@ file static class GeneratedLambdaInvocationBuilderExtensions private const string EventFeatureProviderKey = "__EventFeatureProvider"; private const string ResponseFeatureProviderKey = "__ResponseFeatureProvider"; - // Location: InputFile.cs(9,8) [InterceptsLocation(1, "B3NwPy0yR+xRbgA9x8f/e7wAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaInvocationBuilder MapHandlerInterceptor0( this ILambdaInvocationBuilder application, diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_ExplicitReturnTypeAsync#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_ExplicitReturnTypeAsync#LambdaHandler.g.verified.cs index c40732b9..3916e9aa 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_ExplicitReturnTypeAsync#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_ExplicitReturnTypeAsync#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "q1uiaF3q8+xYajQEZyxaiM0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { var response = castHandler.Invoke(); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_AsyncAndDi#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_AsyncAndDi#LambdaHandler.g.verified.cs index e470c3e7..e02e2153 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_AsyncAndDi#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_AsyncAndDi#LambdaHandler.g.verified.cs @@ -39,24 +39,25 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "GvWtmkGvhj2sJm4/rXiUGc0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (global::IService arg0) => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { // ParameterInfo { Type = global::IService, Name = service, Source = Service, IsNullable = False, IsOptional = False} - var arg0 = serviceProvider.GetRequiredService(); + var arg0 = context.ServiceProvider.GetRequiredService(); var response = castHandler.Invoke(arg0); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_AsyncAndDiAndReturnUnexpectedType#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_AsyncAndDiAndReturnUnexpectedType#LambdaHandler.g.verified.cs index 0645999b..6b3c3800 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_AsyncAndDiAndReturnUnexpectedType#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_AsyncAndDiAndReturnUnexpectedType#LambdaHandler.g.verified.cs @@ -39,24 +39,25 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "8o56Zwu2oVW8FXpGxJSFvc0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (global::IService arg0) => throw null!); return application.OnInit(OnInit); - async Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + async Task OnInit(ILambdaLifecycleContext context) { // ParameterInfo { Type = global::IService, Name = service, Source = Service, IsNullable = False, IsOptional = False} - var arg0 = serviceProvider.GetRequiredService(); + var arg0 = context.ServiceProvider.GetRequiredService(); await castHandler.Invoke(arg0); return true; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_NoDi#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_NoDi#LambdaHandler.g.verified.cs index 0cbeee79..059d0efa 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_NoDi#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MethodHandler_NoDi#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(12,8) [InterceptsLocation(1, "3ivf5JplhmGDGF7iXdWVSucAAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { var response = castHandler.Invoke(); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MultipleCalls#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MultipleCalls#LambdaHandler.g.verified.cs index 56bbbaac..88ccff0f 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MultipleCalls#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_MultipleCalls#LambdaHandler.g.verified.cs @@ -39,66 +39,65 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "gOjUxL7brRqHQuY3oQ1zfc0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { var response = castHandler.Invoke(); return response; } } - // Location: InputFile.cs(15,8) [InterceptsLocation(1, "gOjUxL7brRqHQuY3oQ1zfRUBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor1( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (string? arg0, global::IService? arg1) => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { // ParameterInfo { Type = string?, Name = x, Source = Service, IsNullable = True, IsOptional = False} - var arg0 = serviceProvider.GetService(); + var arg0 = context.ServiceProvider.GetService(); // ParameterInfo { Type = global::IService?, Name = y, Source = Service, IsNullable = True, IsOptional = False} - var arg1 = serviceProvider.GetService(); + var arg1 = context.ServiceProvider.GetService(); var response = castHandler.Invoke(arg0, arg1); return response; } } - // Location: InputFile.cs(22,8) [InterceptsLocation(1, "gOjUxL7brRqHQuY3oQ1zfXoBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor2( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (string arg0, int arg1) => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { // ParameterInfo { Type = string, Name = x, Source = Service, IsNullable = False, IsOptional = False} - var arg0 = serviceProvider.GetRequiredService(); + var arg0 = context.ServiceProvider.GetRequiredService(); // ParameterInfo { Type = int, Name = y, Source = Service, IsNullable = False, IsOptional = False} - var arg1 = serviceProvider.GetRequiredService(); + var arg1 = context.ServiceProvider.GetRequiredService(); var response = castHandler.Invoke(arg0, arg1); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_NoOutput#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_NoOutput#LambdaHandler.g.verified.cs index 6c745345..5d5f90b4 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_NoOutput#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_NoOutput#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "muLM5AWLiyZcBDFwDjSMbc0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Action)handler; + var castHandler = Cast(handler, void () => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { castHandler.Invoke(); return Task.FromResult(true); } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnAsyncBool#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnAsyncBool#LambdaHandler.g.verified.cs index e10e3849..160a2e50 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnAsyncBool#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnAsyncBool#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "itVOIXgsd2/a5q0mYhXydM0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { var response = castHandler.Invoke(); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnBool#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnBool#LambdaHandler.g.verified.cs index c188896d..bad28be5 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnBool#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnBool#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "dCq2ERewPXxHvi/4iSh/m80AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, bool () => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { var response = castHandler.Invoke(); return Task.FromResult(response); } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedType#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedType#LambdaHandler.g.verified.cs index 3b79131d..b518ceb4 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedType#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedType#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "7+o+H0MkQG+24GOQUPBdDs0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, string () => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { castHandler.Invoke(); return Task.FromResult(true); } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedTypeAsync#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedTypeAsync#LambdaHandler.g.verified.cs index 6f5180f3..9264f56b 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedTypeAsync#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedTypeAsync#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "pi9PolKCGMrmFvoC3ft/Oc0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnInit(OnInit); - async Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + async Task OnInit(ILambdaLifecycleContext context) { await castHandler.Invoke(); return true; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedTypeTask#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedTypeTask#LambdaHandler.g.verified.cs index f5f0bdca..eb832568 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedTypeTask#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnNotExpectedTypeTask#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "Vg2L2eBzhOCM6KRY6cER2c0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnInit(OnInit); - async Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + async Task OnInit(ILambdaLifecycleContext context) { await castHandler.Invoke(); return true; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnTaskBool#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnTaskBool#LambdaHandler.g.verified.cs index f49bbb7e..38cfdad4 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnTaskBool#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NoInput_ReturnTaskBool#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "cTRqoX+dJLMMKMOCOmOufs0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { var response = castHandler.Invoke(); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NullableValueAndReferenceInputs#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NullableValueAndReferenceInputs#LambdaHandler.g.verified.cs index 4d54b558..ff69dd98 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NullableValueAndReferenceInputs#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_NullableValueAndReferenceInputs#LambdaHandler.g.verified.cs @@ -39,26 +39,27 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) - [InterceptsLocation(1, "dsRnyqNCGlvINFkBECwmUs0AAABJbnB1dEZpbGUuY3M=")] + [InterceptsLocation(1, "dITS7/hnxk7n1XWH1BHx4s0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (string? arg0, global::IService? arg1 = default) => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { // ParameterInfo { Type = string?, Name = x, Source = Service, IsNullable = True, IsOptional = False} - var arg0 = serviceProvider.GetService(); - // ParameterInfo { Type = global::IService?, Name = y, Source = Service, IsNullable = True, IsOptional = False} - var arg1 = serviceProvider.GetService(); + var arg0 = context.ServiceProvider.GetService(); + // ParameterInfo { Type = global::IService?, Name = y, Source = Service, IsNullable = True, IsOptional = True} + var arg1 = context.ServiceProvider.GetService(); var response = castHandler.Invoke(arg0, arg1); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_OneOfEachPossibleKindOfInput#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_OneOfEachPossibleKindOfInput#LambdaHandler.g.verified.cs index 5039e172..d46fb21d 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_OneOfEachPossibleKindOfInput#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_OneOfEachPossibleKindOfInput#LambdaHandler.g.verified.cs @@ -39,36 +39,37 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(12,8) [InterceptsLocation(1, "s9lx/eNP9F4h61w7TOvQPRUBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (global::System.Threading.CancellationToken arg0, global::IService arg1, global::IService? arg2, global::IService arg3, global::IService? arg4) => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { - if (serviceProvider.GetService() is not IServiceProviderIsKeyedService) + if (context.ServiceProvider.GetService() is not IServiceProviderIsKeyedService) { throw new InvalidOperationException($"Unable to resolve service referenced by {nameof(FromKeyedServicesAttribute)}. The service provider doesn't support keyed services."); } // ParameterInfo { Type = global::System.Threading.CancellationToken, Name = token, Source = CancellationToken, IsNullable = False, IsOptional = False} - var arg0 = cancellationToken; + var arg0 = context.CancellationToken; // ParameterInfo { Type = global::IService, Name = service1, Source = KeyedService, IsNullable = False, IsOptional = False, KeyedServiceKeyInfo { DisplayValue = "key1", Type = string, BaseType = object } } - var arg1 = serviceProvider.GetRequiredKeyedService("key1"); + var arg1 = context.ServiceProvider.GetRequiredKeyedService("key1"); // ParameterInfo { Type = global::IService?, Name = service2, Source = KeyedService, IsNullable = True, IsOptional = False, KeyedServiceKeyInfo { DisplayValue = "key2", Type = string, BaseType = object } } - var arg2 = serviceProvider.GetKeyedService("key2"); + var arg2 = context.ServiceProvider.GetKeyedService("key2"); // ParameterInfo { Type = global::IService, Name = service3, Source = Service, IsNullable = False, IsOptional = False} - var arg3 = serviceProvider.GetRequiredService(); + var arg3 = context.ServiceProvider.GetRequiredService(); // ParameterInfo { Type = global::IService?, Name = service4, Source = Service, IsNullable = True, IsOptional = False} - var arg4 = serviceProvider.GetService(); + var arg4 = context.ServiceProvider.GetService(); var response = castHandler.Invoke(arg0, arg1, arg2, arg3, arg4); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_PrimitiveInput#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_PrimitiveInput#LambdaHandler.g.verified.cs index c78843c8..4cfbb8af 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_PrimitiveInput#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnInitVerifyTests.Test_OnInit_PrimitiveInput#LambdaHandler.g.verified.cs @@ -39,26 +39,27 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnInitBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "8J01folJ0MDOTLxLNRx4fs0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnInitBuilder OnInitInterceptor0( this ILambdaOnInitBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (string arg0, int arg1) => throw null!); return application.OnInit(OnInit); - Task OnInit(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnInit(ILambdaLifecycleContext context) { // ParameterInfo { Type = string, Name = x, Source = Service, IsNullable = False, IsOptional = False} - var arg0 = serviceProvider.GetRequiredService(); + var arg0 = context.ServiceProvider.GetRequiredService(); // ParameterInfo { Type = int, Name = y, Source = Service, IsNullable = False, IsOptional = False} - var arg1 = serviceProvider.GetRequiredService(); + var arg1 = context.ServiceProvider.GetRequiredService(); var response = castHandler.Invoke(arg0, arg1); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_BlockLambda_ReturnsImplicitVoid#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_BlockLambda_ReturnsImplicitVoid#LambdaHandler.g.verified.cs index 8d336389..e1ca9637 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_BlockLambda_ReturnsImplicitVoid#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_BlockLambda_ReturnsImplicitVoid#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnShutdownBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "lPDnfssMibsxhX79gLd2lL0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor0( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Action)handler; + var castHandler = Cast(handler, void () => throw null!); return application.OnShutdown(OnShutdown); - Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnShutdown(ILambdaLifecycleContext context) { castHandler.Invoke(); return Task.CompletedTask; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_MultipleCalls#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_MultipleCalls#LambdaHandler.g.verified.cs index 44543c55..43510c7f 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_MultipleCalls#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_MultipleCalls#LambdaHandler.g.verified.cs @@ -39,66 +39,65 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnShutdownBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "W852isYQO43ObWn6kxnU5s0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor0( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnShutdown(OnShutdown); - Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnShutdown(ILambdaLifecycleContext context) { var response = castHandler.Invoke(); return response; } } - // Location: InputFile.cs(15,8) [InterceptsLocation(1, "W852isYQO43ObWn6kxnU5hABAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor1( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (string? arg0, global::IService? arg1) => throw null!); return application.OnShutdown(OnShutdown); - Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnShutdown(ILambdaLifecycleContext context) { // ParameterInfo { Type = string?, Name = x, Source = Service, IsNullable = True, IsOptional = False} - var arg0 = serviceProvider.GetService(); + var arg0 = context.ServiceProvider.GetService(); // ParameterInfo { Type = global::IService?, Name = y, Source = Service, IsNullable = True, IsOptional = False} - var arg1 = serviceProvider.GetService(); + var arg1 = context.ServiceProvider.GetService(); var response = castHandler.Invoke(arg0, arg1); return response; } } - // Location: InputFile.cs(22,8) [InterceptsLocation(1, "W852isYQO43ObWn6kxnU5nsBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor2( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (string arg0, int arg1) => throw null!); return application.OnShutdown(OnShutdown); - Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnShutdown(ILambdaLifecycleContext context) { // ParameterInfo { Type = string, Name = x, Source = Service, IsNullable = False, IsOptional = False} - var arg0 = serviceProvider.GetRequiredService(); + var arg0 = context.ServiceProvider.GetRequiredService(); // ParameterInfo { Type = int, Name = y, Source = Service, IsNullable = False, IsOptional = False} - var arg1 = serviceProvider.GetRequiredService(); + var arg1 = context.ServiceProvider.GetRequiredService(); var response = castHandler.Invoke(arg0, arg1); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput#LambdaHandler.g.verified.cs index c41f0702..c432fdb9 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnShutdownBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "F/zSODBMGX3Xez9u/iwpl80AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor0( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnShutdown(OnShutdown); - Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnShutdown(ILambdaLifecycleContext context) { var response = castHandler.Invoke(); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedType#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedType#LambdaHandler.g.verified.cs index f463885d..63388d28 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedType#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedType#LambdaHandler.g.verified.cs @@ -39,22 +39,23 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnShutdownBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "Cr7Neg3slUnAi5SjcvJU580AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor0( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, string () => throw null!); return application.OnShutdown(OnShutdown); - Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnShutdown(ILambdaLifecycleContext context) { castHandler.Invoke(); return Task.CompletedTask; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedTypeAsync#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedTypeAsync#LambdaHandler.g.verified.cs index 6c047447..25554d6a 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedTypeAsync#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedTypeAsync#LambdaHandler.g.verified.cs @@ -39,21 +39,22 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnShutdownBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "YWaX0vtU1wLdNqf9cuGdFM0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor0( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnShutdown(OnShutdown); - async Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + async Task OnShutdown(ILambdaLifecycleContext context) { await castHandler.Invoke(); } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedTypeTask#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedTypeTask#LambdaHandler.g.verified.cs index 08fc3161..8b42a3b8 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedTypeTask#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NoInput_ReturnUnexpectedTypeTask#LambdaHandler.g.verified.cs @@ -39,21 +39,22 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnShutdownBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "12DeS9LwHN3iO8NwFisQBs0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor0( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func>)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task () => throw null!); return application.OnShutdown(OnShutdown); - async Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + async Task OnShutdown(ILambdaLifecycleContext context) { await castHandler.Invoke(); } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NullableValueAndReferenceInputs#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NullableValueAndReferenceInputs#LambdaHandler.g.verified.cs index 9c14af0f..a73d512a 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NullableValueAndReferenceInputs#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_NullableValueAndReferenceInputs#LambdaHandler.g.verified.cs @@ -39,26 +39,27 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnShutdownBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "BGCXXs9bVPwLCAUaU8Kkds0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor0( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (string? arg0, global::IService? arg1) => throw null!); return application.OnShutdown(OnShutdown); - Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnShutdown(ILambdaLifecycleContext context) { // ParameterInfo { Type = string?, Name = x, Source = Service, IsNullable = True, IsOptional = False} - var arg0 = serviceProvider.GetService(); + var arg0 = context.ServiceProvider.GetService(); // ParameterInfo { Type = global::IService?, Name = y, Source = Service, IsNullable = True, IsOptional = False} - var arg1 = serviceProvider.GetService(); + var arg1 = context.ServiceProvider.GetService(); var response = castHandler.Invoke(arg0, arg1); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_OneOfEachPossibleKindOfInput#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_OneOfEachPossibleKindOfInput#LambdaHandler.g.verified.cs index cf2fff7a..ad12af6c 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_OneOfEachPossibleKindOfInput#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_OneOfEachPossibleKindOfInput#LambdaHandler.g.verified.cs @@ -39,36 +39,37 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnShutdownBuilderExtensions { - // Location: InputFile.cs(12,8) [InterceptsLocation(1, "ZhdnggwSuJq0NpRZew7QhhUBAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor0( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (global::System.Threading.CancellationToken arg0, global::IService arg1, global::IService? arg2, global::IService arg3, global::IService? arg4) => throw null!); return application.OnShutdown(OnShutdown); - Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnShutdown(ILambdaLifecycleContext context) { - if (serviceProvider.GetService() is not IServiceProviderIsKeyedService) + if (context.ServiceProvider.GetService() is not IServiceProviderIsKeyedService) { throw new InvalidOperationException($"Unable to resolve service referenced by {nameof(FromKeyedServicesAttribute)}. The service provider doesn't support keyed services."); } // ParameterInfo { Type = global::System.Threading.CancellationToken, Name = token, Source = CancellationToken, IsNullable = False, IsOptional = False} - var arg0 = cancellationToken; + var arg0 = context.CancellationToken; // ParameterInfo { Type = global::IService, Name = service1, Source = KeyedService, IsNullable = False, IsOptional = False, KeyedServiceKeyInfo { DisplayValue = "key1", Type = string, BaseType = object } } - var arg1 = serviceProvider.GetRequiredKeyedService("key1"); + var arg1 = context.ServiceProvider.GetRequiredKeyedService("key1"); // ParameterInfo { Type = global::IService?, Name = service2, Source = KeyedService, IsNullable = True, IsOptional = False, KeyedServiceKeyInfo { DisplayValue = "key2", Type = string, BaseType = object } } - var arg2 = serviceProvider.GetKeyedService("key2"); + var arg2 = context.ServiceProvider.GetKeyedService("key2"); // ParameterInfo { Type = global::IService, Name = service3, Source = Service, IsNullable = False, IsOptional = False} - var arg3 = serviceProvider.GetRequiredService(); + var arg3 = context.ServiceProvider.GetRequiredService(); // ParameterInfo { Type = global::IService?, Name = service4, Source = Service, IsNullable = True, IsOptional = False} - var arg4 = serviceProvider.GetService(); + var arg4 = context.ServiceProvider.GetService(); var response = castHandler.Invoke(arg0, arg1, arg2, arg3, arg4); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_PrimitiveInput#LambdaHandler.g.verified.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_PrimitiveInput#LambdaHandler.g.verified.cs index c3617add..c50d3b1c 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_PrimitiveInput#LambdaHandler.g.verified.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/Snapshots/OnShutdownVerifyTests.Test_OnShutdown_PrimitiveInput#LambdaHandler.g.verified.cs @@ -39,26 +39,27 @@ namespace MinimalLambda.Generated [GeneratedCode("MinimalLambda.SourceGenerators", "0.0.0")] file static class GeneratedLambdaOnShutdownBuilderExtensions { - // Location: InputFile.cs(10,8) [InterceptsLocation(1, "cuXlRiXWvhKK6Ao4rCbyic0AAABJbnB1dEZpbGUuY3M=")] internal static ILambdaOnShutdownBuilder OnShutdownInterceptor0( this ILambdaOnShutdownBuilder application, Delegate handler ) { - var castHandler = (global::System.Func)handler; + var castHandler = Cast(handler, global::System.Threading.Tasks.Task (string arg0, int arg1) => throw null!); return application.OnShutdown(OnShutdown); - Task OnShutdown(IServiceProvider serviceProvider, CancellationToken cancellationToken) + Task OnShutdown(ILambdaLifecycleContext context) { // ParameterInfo { Type = string, Name = x, Source = Service, IsNullable = False, IsOptional = False} - var arg0 = serviceProvider.GetRequiredService(); + var arg0 = context.ServiceProvider.GetRequiredService(); // ParameterInfo { Type = int, Name = y, Source = Service, IsNullable = False, IsOptional = False} - var arg1 = serviceProvider.GetRequiredService(); + var arg1 = context.ServiceProvider.GetRequiredService(); var response = castHandler.Invoke(arg0, arg1); return response; } } + + private static T Cast(Delegate d, T _) where T : Delegate => (T)d; } } \ No newline at end of file diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/VerifyTests/OnInitVerifyTests.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/VerifyTests/OnInitVerifyTests.cs index f4ba93ca..90d7e8f9 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/VerifyTests/OnInitVerifyTests.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/VerifyTests/OnInitVerifyTests.cs @@ -15,7 +15,7 @@ await GeneratorTestHelpers.Verify( var lambda = builder.Build(); lambda.OnInit( - async (services, token) => + async (context) => { return true; } @@ -218,7 +218,7 @@ await GeneratorTestHelpers.Verify( var lambda = builder.Build(); lambda.OnInit( - Task (string? x, IService? y) => + Task (string? x, IService? y = null) => { return Task.FromResult(true); } diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/VerifyTests/OnShutdownVerifyTests.cs b/tests/MinimalLambda.SourceGenerators.UnitTests/VerifyTests/OnShutdownVerifyTests.cs index 98a0e8ef..9332452b 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/VerifyTests/OnShutdownVerifyTests.cs +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/VerifyTests/OnShutdownVerifyTests.cs @@ -15,7 +15,7 @@ await GeneratorTestHelpers.Verify( var lambda = builder.Build(); lambda.OnShutdown( - async (services, token) => + async (context) => { return; } diff --git a/tests/MinimalLambda.UnitTests/Builder/DefaultLambdaOnInitBuilderFactoryTests.cs b/tests/MinimalLambda.UnitTests/Builder/DefaultLambdaOnInitBuilderFactoryTests.cs index d58a0a29..8a4a664d 100644 --- a/tests/MinimalLambda.UnitTests/Builder/DefaultLambdaOnInitBuilderFactoryTests.cs +++ b/tests/MinimalLambda.UnitTests/Builder/DefaultLambdaOnInitBuilderFactoryTests.cs @@ -12,21 +12,27 @@ public class DefaultLambdaOnInitBuilderFactoryTests private readonly IServiceScopeFactory _scopeFactory = Substitute.For(); private readonly IServiceProvider _serviceProvider = Substitute.For(); + private readonly ILambdaLifecycleContextFactory _contextFactory = + Substitute.For(); + [Theory] [InlineData(0)] // ServiceProvider [InlineData(1)] // ScopeFactory [InlineData(2)] // Options + [InlineData(3)] // ContextFactory public void CreateBuilder_WithNullParameter_ThrowsArgumentNullException(int parameterIndex) { // Arrange var serviceProvider = parameterIndex == 0 ? null : _serviceProvider; var scopeFactory = parameterIndex == 1 ? null : _scopeFactory; var options = parameterIndex == 2 ? null : _options; + var contextFactory = parameterIndex == 3 ? null : _contextFactory; var factory = new DefaultLambdaOnInitBuilderFactory( serviceProvider!, scopeFactory!, - options! + options!, + contextFactory! ); // Act & Assert - validation happens in LambdaOnInitBuilder constructor @@ -41,7 +47,8 @@ public void Constructor_WithValidParameters_SuccessfullyConstructs() var factory = new DefaultLambdaOnInitBuilderFactory( _serviceProvider, _scopeFactory, - _options + _options, + _contextFactory ); // Assert @@ -55,7 +62,8 @@ public void CreateBuilder_ReturnsLambdaOnInitBuilder() var factory = new DefaultLambdaOnInitBuilderFactory( _serviceProvider, _scopeFactory, - _options + _options, + _contextFactory ); // Act @@ -73,7 +81,8 @@ public void CreateBuilder_PassesServiceProviderToBuilder() var factory = new DefaultLambdaOnInitBuilderFactory( _serviceProvider, _scopeFactory, - _options + _options, + _contextFactory ); // Act @@ -90,7 +99,8 @@ public void CreateBuilder_CreatesNewInstanceEachCall() var factory = new DefaultLambdaOnInitBuilderFactory( _serviceProvider, _scopeFactory, - _options + _options, + _contextFactory ); // Act diff --git a/tests/MinimalLambda.UnitTests/Builder/DefaultLambdaOnShutdownBuilderFactoryTests.cs b/tests/MinimalLambda.UnitTests/Builder/DefaultLambdaOnShutdownBuilderFactoryTests.cs index 0f3d6db5..f3a53837 100644 --- a/tests/MinimalLambda.UnitTests/Builder/DefaultLambdaOnShutdownBuilderFactoryTests.cs +++ b/tests/MinimalLambda.UnitTests/Builder/DefaultLambdaOnShutdownBuilderFactoryTests.cs @@ -8,16 +8,25 @@ public class DefaultLambdaOnShutdownBuilderFactoryTests private readonly IServiceScopeFactory _scopeFactory = Substitute.For(); private readonly IServiceProvider _serviceProvider = Substitute.For(); + private readonly ILambdaLifecycleContextFactory _contextFactory = + Substitute.For(); + [Theory] [InlineData(0)] // ServiceProvider [InlineData(1)] // ScopeFactory + [InlineData(2)] // ContextFactory public void CreateBuilder_WithNullParameter_ThrowsArgumentNullException(int parameterIndex) { // Arrange var serviceProvider = parameterIndex == 0 ? null : _serviceProvider; var scopeFactory = parameterIndex == 1 ? null : _scopeFactory; + var contextFactory = parameterIndex == 2 ? null : _contextFactory; - var factory = new DefaultLambdaOnShutdownBuilderFactory(serviceProvider!, scopeFactory!); + var factory = new DefaultLambdaOnShutdownBuilderFactory( + serviceProvider!, + scopeFactory!, + contextFactory! + ); // Act & Assert - validation happens in LambdaOnShutdownBuilder constructor var act = () => factory.CreateBuilder(); @@ -28,7 +37,11 @@ public void CreateBuilder_WithNullParameter_ThrowsArgumentNullException(int para public void Constructor_WithValidParameters_SuccessfullyConstructs() { // Act - var factory = new DefaultLambdaOnShutdownBuilderFactory(_serviceProvider, _scopeFactory); + var factory = new DefaultLambdaOnShutdownBuilderFactory( + _serviceProvider, + _scopeFactory, + _contextFactory + ); // Assert factory.Should().NotBeNull(); @@ -38,7 +51,11 @@ public void Constructor_WithValidParameters_SuccessfullyConstructs() public void CreateBuilder_ReturnsLambdaOnShutdownBuilder() { // Arrange - var factory = new DefaultLambdaOnShutdownBuilderFactory(_serviceProvider, _scopeFactory); + var factory = new DefaultLambdaOnShutdownBuilderFactory( + _serviceProvider, + _scopeFactory, + _contextFactory + ); // Act var builder = factory.CreateBuilder(); @@ -52,7 +69,11 @@ public void CreateBuilder_ReturnsLambdaOnShutdownBuilder() public void CreateBuilder_PassesServiceProviderToBuilder() { // Arrange - var factory = new DefaultLambdaOnShutdownBuilderFactory(_serviceProvider, _scopeFactory); + var factory = new DefaultLambdaOnShutdownBuilderFactory( + _serviceProvider, + _scopeFactory, + _contextFactory + ); // Act var builder = factory.CreateBuilder(); @@ -65,7 +86,11 @@ public void CreateBuilder_PassesServiceProviderToBuilder() public void CreateBuilder_CreatesNewInstanceEachCall() { // Arrange - var factory = new DefaultLambdaOnShutdownBuilderFactory(_serviceProvider, _scopeFactory); + var factory = new DefaultLambdaOnShutdownBuilderFactory( + _serviceProvider, + _scopeFactory, + _contextFactory + ); // Act var builder1 = factory.CreateBuilder(); diff --git a/tests/MinimalLambda.UnitTests/Builder/Extensions/MiddlewareLambdaApplicationExtensionsTests.cs b/tests/MinimalLambda.UnitTests/Builder/Extensions/MiddlewareLambdaApplicationExtensionsTests.cs index b886bc25..7bfcec70 100644 --- a/tests/MinimalLambda.UnitTests/Builder/Extensions/MiddlewareLambdaApplicationExtensionsTests.cs +++ b/tests/MinimalLambda.UnitTests/Builder/Extensions/MiddlewareLambdaApplicationExtensionsTests.cs @@ -1,4 +1,3 @@ -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace MinimalLambda.UnitTests.Application.Extensions; @@ -6,18 +5,8 @@ namespace MinimalLambda.UnitTests.Application.Extensions; [TestSubject(typeof(MiddlewareLambdaApplicationExtensions))] public class MiddlewareLambdaApplicationExtensionsTests { - private static IHost CreateHostWithServices() - { - var builder = Host.CreateDefaultBuilder(); - builder.ConfigureServices(services => - { - services.ConfigureLambdaHostOptions(_ => { }); - services.AddLambdaHostCoreServices(); - services.TryAddLambdaHostDefaultServices(); - }); - - return builder.Build(); - } + private static IHost CreateHostWithServices() => + new LambdaApplicationBuilder(new LambdaApplicationOptions()).Build(); [Fact] public void UseMiddleware_WithNullApplication_ThrowsArgumentNullException() diff --git a/tests/MinimalLambda.UnitTests/Builder/Extensions/ServiceCollectionExtensionsTests.cs b/tests/MinimalLambda.UnitTests/Builder/Extensions/ServiceCollectionExtensionsTests.cs index f38be37c..a8760cbe 100644 --- a/tests/MinimalLambda.UnitTests/Builder/Extensions/ServiceCollectionExtensionsTests.cs +++ b/tests/MinimalLambda.UnitTests/Builder/Extensions/ServiceCollectionExtensionsTests.cs @@ -31,7 +31,7 @@ public void AddLambdaHostCoreServices_WithValidServiceCollection_ReturnsServiceC } [Theory] - [InlineData(13)] + [InlineData(14)] public void AddLambdaHostCoreServices_RegistersExactlyNServices(int servicesCount) { // Arrange diff --git a/tests/MinimalLambda.UnitTests/Builder/LambdaApplicationBuilderTests.cs b/tests/MinimalLambda.UnitTests/Builder/LambdaApplicationBuilderTests.cs index d43642b6..ae08d734 100644 --- a/tests/MinimalLambda.UnitTests/Builder/LambdaApplicationBuilderTests.cs +++ b/tests/MinimalLambda.UnitTests/Builder/LambdaApplicationBuilderTests.cs @@ -297,8 +297,8 @@ public void Build_ConfigureOnInitBuilderCallback_AppliesInitHandlers() var app = builder.Build(); // Register init handlers on the app - LambdaInitDelegate handler1 = (_, _) => Task.FromResult(true); - LambdaInitDelegate handler2 = (_, _) => Task.FromResult(false); + LambdaInitDelegate handler1 = _ => Task.FromResult(true); + LambdaInitDelegate handler2 = _ => Task.FromResult(false); app.OnInit(handler1); app.OnInit(handler2); @@ -387,8 +387,8 @@ public void Build_ConfigureOnShutdownBuilderCallback_AppliesShutdownHandlers() var app = builder.Build(); // Register shutdown handlers on the app - LambdaShutdownDelegate handler1 = (_, _) => Task.CompletedTask; - LambdaShutdownDelegate handler2 = (_, _) => Task.CompletedTask; + LambdaShutdownDelegate handler1 = _ => Task.CompletedTask; + LambdaShutdownDelegate handler2 = _ => Task.CompletedTask; app.OnShutdown(handler1); app.OnShutdown(handler2); @@ -436,9 +436,9 @@ public void Build_ConfigureOnShutdownBuilderCallback_WithMultipleHandlers() var app = builder.Build(); // Register multiple shutdown handlers - LambdaShutdownDelegate handler1 = (_, _) => Task.CompletedTask; - LambdaShutdownDelegate handler2 = (_, _) => Task.CompletedTask; - LambdaShutdownDelegate handler3 = (_, _) => Task.CompletedTask; + LambdaShutdownDelegate handler1 = _ => Task.CompletedTask; + LambdaShutdownDelegate handler2 = _ => Task.CompletedTask; + LambdaShutdownDelegate handler3 = _ => Task.CompletedTask; app.OnShutdown(handler1); app.OnShutdown(handler2); app.OnShutdown(handler3); @@ -513,7 +513,7 @@ public void Build_ImplementsILambdaOnInitBuilder_OnInitMethod() // Arrange var builder = LambdaApplication.CreateBuilder(); var app = builder.Build(); - LambdaInitDelegate handler = (_, _) => Task.FromResult(true); + LambdaInitDelegate handler = _ => Task.FromResult(true); // Act var result = app.OnInit(handler); @@ -529,8 +529,8 @@ public void Build_ImplementsILambdaOnInitBuilder_MultipleHandlers() // Arrange var builder = LambdaApplication.CreateBuilder(); var app = builder.Build(); - LambdaInitDelegate handler1 = (_, _) => Task.FromResult(true); - LambdaInitDelegate handler2 = (_, _) => Task.FromResult(false); + LambdaInitDelegate handler1 = _ => Task.FromResult(true); + LambdaInitDelegate handler2 = _ => Task.FromResult(false); // Act app.OnInit(handler1); @@ -548,7 +548,7 @@ public void Build_ImplementsILambdaOnShutdownBuilder_OnShutdownMethod() // Arrange var builder = LambdaApplication.CreateBuilder(); var app = builder.Build(); - LambdaShutdownDelegate handler = (_, _) => Task.CompletedTask; + LambdaShutdownDelegate handler = _ => Task.CompletedTask; // Act var result = app.OnShutdown(handler); @@ -564,8 +564,8 @@ public void Build_ImplementsILambdaOnShutdownBuilder_MultipleHandlers() // Arrange var builder = LambdaApplication.CreateBuilder(); var app = builder.Build(); - LambdaShutdownDelegate handler1 = (_, _) => Task.CompletedTask; - LambdaShutdownDelegate handler2 = (_, _) => Task.CompletedTask; + LambdaShutdownDelegate handler1 = _ => Task.CompletedTask; + LambdaShutdownDelegate handler2 = _ => Task.CompletedTask; // Act app.OnShutdown(handler1); diff --git a/tests/MinimalLambda.UnitTests/Builder/LambdaApplicationTests.cs b/tests/MinimalLambda.UnitTests/Builder/LambdaApplicationTests.cs index 6a5a5805..9e32ad3a 100644 --- a/tests/MinimalLambda.UnitTests/Builder/LambdaApplicationTests.cs +++ b/tests/MinimalLambda.UnitTests/Builder/LambdaApplicationTests.cs @@ -1,4 +1,3 @@ -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace MinimalLambda.UnitTests.Application; @@ -6,18 +5,8 @@ namespace MinimalLambda.UnitTests.Application; [TestSubject(typeof(LambdaApplication))] public class LambdaApplicationTests { - private static IHost CreateHostWithServices() - { - var builder = Host.CreateDefaultBuilder(); - builder.ConfigureServices(services => - { - services.ConfigureLambdaHostOptions(_ => { }); - services.AddLambdaHostCoreServices(); - services.TryAddLambdaHostDefaultServices(); - }); - - return builder.Build(); - } + private static IHost CreateHostWithServices() => + new LambdaApplicationBuilder(new LambdaApplicationOptions()).Build(); [Fact] public void Constructor_WithNullHost_ThrowsArgumentNullException() @@ -526,7 +515,7 @@ public void OnInit_WithValidHandler_AddsHandler() // Arrange var host = CreateHostWithServices(); var app = new LambdaApplication(host); - LambdaInitDelegate handler = async (_, _) => true; + LambdaInitDelegate handler = async _ => true; // Act app.OnInit(handler); @@ -541,7 +530,7 @@ public void OnInit_ReturnsBuilder() // Arrange var host = CreateHostWithServices(); var app = new LambdaApplication(host); - LambdaInitDelegate handler = async (_, _) => true; + LambdaInitDelegate handler = async _ => true; // Act var result = app.OnInit(handler); @@ -556,7 +545,7 @@ public void OnInit_EnablesMethodChaining() // Arrange var host = CreateHostWithServices(); var app = new LambdaApplication(host); - LambdaInitDelegate handler = async (_, _) => true; + LambdaInitDelegate handler = async _ => true; // Act var result = app.OnInit(handler).OnInit(handler); @@ -572,7 +561,7 @@ public async Task OnInit_Build_ReturnsCallable() // Arrange var host = CreateHostWithServices(); var app = new LambdaApplication(host); - LambdaInitDelegate handler = async (_, _) => true; + LambdaInitDelegate handler = async _ => true; app.OnInit(handler); // Act @@ -634,7 +623,7 @@ public void OnShutdown_WithValidHandler_AddsHandler() // Arrange var host = CreateHostWithServices(); var app = new LambdaApplication(host); - LambdaShutdownDelegate handler = async (_, _) => await Task.CompletedTask; + LambdaShutdownDelegate handler = async _ => await Task.CompletedTask; // Act app.OnShutdown(handler); @@ -649,7 +638,7 @@ public void OnShutdown_ReturnsBuilder() // Arrange var host = CreateHostWithServices(); var app = new LambdaApplication(host); - LambdaShutdownDelegate handler = async (_, _) => await Task.CompletedTask; + LambdaShutdownDelegate handler = async _ => await Task.CompletedTask; // Act var result = app.OnShutdown(handler); @@ -664,7 +653,7 @@ public void OnShutdown_EnablesMethodChaining() // Arrange var host = CreateHostWithServices(); var app = new LambdaApplication(host); - LambdaShutdownDelegate handler = async (_, _) => await Task.CompletedTask; + LambdaShutdownDelegate handler = async _ => await Task.CompletedTask; // Act var result = app.OnShutdown(handler).OnShutdown(handler); @@ -680,7 +669,7 @@ public async Task OnShutdown_Build_ReturnsCallable() // Arrange var host = CreateHostWithServices(); var app = new LambdaApplication(host); - LambdaShutdownDelegate handler = async (_, _) => await Task.CompletedTask; + LambdaShutdownDelegate handler = async _ => await Task.CompletedTask; app.OnShutdown(handler); // Act @@ -699,8 +688,8 @@ public void AllBuilders_CanBeChainedTogether() var host = CreateHostWithServices(); var app = new LambdaApplication(host); LambdaInvocationDelegate invocationHandler = async _ => await Task.CompletedTask; - LambdaInitDelegate initHandler = async (_, _) => true; - LambdaShutdownDelegate shutdownHandler = async (_, _) => await Task.CompletedTask; + LambdaInitDelegate initHandler = async _ => true; + LambdaShutdownDelegate shutdownHandler = async _ => await Task.CompletedTask; // Act app.Handle(invocationHandler); diff --git a/tests/MinimalLambda.UnitTests/Builder/LambdaOnInitBuilderTests.cs b/tests/MinimalLambda.UnitTests/Builder/LambdaOnInitBuilderTests.cs index e2204422..e642fccb 100644 --- a/tests/MinimalLambda.UnitTests/Builder/LambdaOnInitBuilderTests.cs +++ b/tests/MinimalLambda.UnitTests/Builder/LambdaOnInitBuilderTests.cs @@ -8,13 +8,14 @@ public class LambdaOnInitBuilderTests { [Theory] [AutoNSubstituteData] - public void Constructor_WithNullServiceProvider_ThrowsArgumentNullException( + internal void Constructor_WithNullServiceProvider_ThrowsArgumentNullException( IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { // Act - var act = () => new LambdaOnInitBuilder(null!, scopeFactory, options); + var act = () => new LambdaOnInitBuilder(null!, scopeFactory, options, contextFactory); // Assert act.Should().ThrowExactly().WithParameterName("serviceProvider"); @@ -22,13 +23,14 @@ IOptions options [Theory] [AutoNSubstituteData] - public void Constructor_WithNullScopeFactory_ThrowsArgumentNullException( + internal void Constructor_WithNullScopeFactory_ThrowsArgumentNullException( IServiceProvider serviceProvider, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { // Act - var act = () => new LambdaOnInitBuilder(serviceProvider, null!, options); + var act = () => new LambdaOnInitBuilder(serviceProvider, null!, options, contextFactory); // Assert act.Should().ThrowExactly().WithParameterName("scopeFactory"); @@ -36,13 +38,15 @@ IOptions options [Theory] [AutoNSubstituteData] - public void Constructor_WithNullOptions_ThrowsArgumentNullException( + internal void Constructor_WithNullOptions_ThrowsArgumentNullException( IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory + IServiceScopeFactory scopeFactory, + ILambdaLifecycleContextFactory contextFactory ) { // Act - var act = () => new LambdaOnInitBuilder(serviceProvider, scopeFactory, null!); + var act = () => + new LambdaOnInitBuilder(serviceProvider, scopeFactory, null!, contextFactory); // Assert act.Should().ThrowExactly().WithParameterName("options"); @@ -50,14 +54,20 @@ IServiceScopeFactory scopeFactory [Theory] [AutoNSubstituteData] - public void Constructor_WithValidParameters_Succeeds( + internal void Constructor_WithValidParameters_Succeeds( IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { // Act - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, options); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + options, + contextFactory + ); // Assert builder.Should().NotBeNull(); @@ -66,14 +76,20 @@ IOptions options [Theory] [AutoNSubstituteData] - public void Services_ReturnsServiceProvider( + internal void Services_ReturnsServiceProvider( IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { // Arrange - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, options); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + options, + contextFactory + ); // Act var result = builder.Services; @@ -84,14 +100,20 @@ IOptions options [Theory] [AutoNSubstituteData] - public void InitHandlers_ReturnsReadOnlyList( + internal void InitHandlers_ReturnsReadOnlyList( IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { // Arrange - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, options); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + options, + contextFactory + ); // Act var handlers = builder.InitHandlers; @@ -104,14 +126,20 @@ IOptions options [Theory] [AutoNSubstituteData] - public void OnInit_WithNullHandler_ThrowsArgumentNullException( + internal void OnInit_WithNullHandler_ThrowsArgumentNullException( IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { // Arrange - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, options); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + options, + contextFactory + ); // Act var act = () => builder.OnInit(null!); @@ -122,15 +150,21 @@ IOptions options [Theory] [AutoNSubstituteData] - public void OnInit_WithValidHandler_AddsHandlerAndReturnsBuilder( + internal void OnInit_WithValidHandler_AddsHandlerAndReturnsBuilder( IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { // Arrange - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, options); - LambdaInitDelegate handler = (_, _) => Task.FromResult(true); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + options, + contextFactory + ); + LambdaInitDelegate handler = _ => Task.FromResult(true); // Act var result = builder.OnInit(handler); @@ -142,17 +176,23 @@ IOptions options [Theory] [AutoNSubstituteData] - public void OnInit_MultipleHandlers_AllAdded( + internal void OnInit_MultipleHandlers_AllAdded( IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { // Arrange - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, options); - LambdaInitDelegate handler1 = (_, _) => Task.FromResult(true); - LambdaInitDelegate handler2 = (_, _) => Task.FromResult(true); - LambdaInitDelegate handler3 = (_, _) => Task.FromResult(true); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + options, + contextFactory + ); + LambdaInitDelegate handler1 = _ => Task.FromResult(true); + LambdaInitDelegate handler2 = _ => Task.FromResult(true); + LambdaInitDelegate handler3 = _ => Task.FromResult(true); // Act builder.OnInit(handler1); @@ -166,21 +206,26 @@ IOptions options [Theory] [AutoNSubstituteData] - public async Task Build_WithoutHandlers_ReturnsAlwaysTrueFunction( + internal async Task Build_WithoutHandlers_ReturnsNull( IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, - IOptions options + IOptions options, + ILambdaLifecycleContextFactory contextFactory ) { // Arrange - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, options); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + options, + contextFactory + ); // Act var buildFunc = builder.Build(); - var result = await buildFunc(CancellationToken.None); // Assert - result.Should().BeTrue(); + buildFunc.Should().BeNull(); } [Fact] @@ -192,10 +237,16 @@ public async Task Build_WithSingleSuccessfulHandler_ReturnsTrue() var lambdaHostOptions = Microsoft.Extensions.Options.Options.Create( new LambdaHostOptions() ); - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, lambdaHostOptions); + var contextFactory = Substitute.For(); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + lambdaHostOptions, + contextFactory + ); var handlerCalled = false; - LambdaInitDelegate handler = (_, _) => + LambdaInitDelegate handler = _ => { handlerCalled = true; return Task.FromResult(true); @@ -205,6 +256,7 @@ public async Task Build_WithSingleSuccessfulHandler_ReturnsTrue() // Act var buildFunc = builder.Build(); + buildFunc.Should().NotBeNull(); var result = await buildFunc(CancellationToken.None); // Assert @@ -221,9 +273,15 @@ public async Task Build_WithHandlerReturnsFalse_ReturnsFalse() var lambdaHostOptions = Microsoft.Extensions.Options.Options.Create( new LambdaHostOptions() ); - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, lambdaHostOptions); + var contextFactory = Substitute.For(); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + lambdaHostOptions, + contextFactory + ); - LambdaInitDelegate handler = (_, _) => Task.FromResult(false); + LambdaInitDelegate handler = _ => Task.FromResult(false); builder.OnInit(handler); @@ -244,24 +302,30 @@ public async Task Build_WithMultipleHandlers_AllExecuted() var lambdaHostOptions = Microsoft.Extensions.Options.Options.Create( new LambdaHostOptions() ); - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, lambdaHostOptions); + var contextFactory = Substitute.For(); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + lambdaHostOptions, + contextFactory + ); var handler1Called = false; var handler2Called = false; var handler3Called = false; - LambdaInitDelegate handler1 = (_, _) => + LambdaInitDelegate handler1 = _ => { handler1Called = true; return Task.FromResult(true); }; - LambdaInitDelegate handler2 = (_, _) => + LambdaInitDelegate handler2 = _ => { handler2Called = true; return Task.FromResult(true); }; - LambdaInitDelegate handler3 = (_, _) => + LambdaInitDelegate handler3 = _ => { handler3Called = true; return Task.FromResult(true); @@ -291,11 +355,17 @@ public async Task Build_WithAnyHandlerReturningFalse_ReturnsFalse() var lambdaHostOptions = Microsoft.Extensions.Options.Options.Create( new LambdaHostOptions() ); - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, lambdaHostOptions); + var contextFactory = Substitute.For(); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + lambdaHostOptions, + contextFactory + ); - LambdaInitDelegate handler1 = (_, _) => Task.FromResult(true); - LambdaInitDelegate handler2 = (_, _) => Task.FromResult(false); - LambdaInitDelegate handler3 = (_, _) => Task.FromResult(true); + LambdaInitDelegate handler1 = _ => Task.FromResult(true); + LambdaInitDelegate handler2 = _ => Task.FromResult(false); + LambdaInitDelegate handler3 = _ => Task.FromResult(true); builder.OnInit(handler1); builder.OnInit(handler2); @@ -318,10 +388,16 @@ public async Task Build_WhenHandlerThrowsException_ThrowsAggregateException() var lambdaHostOptions = Microsoft.Extensions.Options.Options.Create( new LambdaHostOptions() ); - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, lambdaHostOptions); + var contextFactory = Substitute.For(); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + lambdaHostOptions, + contextFactory + ); var testException = new InvalidOperationException("Test error"); - LambdaInitDelegate handler = (_, _) => throw testException; + LambdaInitDelegate handler = _ => throw testException; builder.OnInit(handler); @@ -342,13 +418,19 @@ public async Task Build_WithMultipleFailures_AggregatesAllErrors() var lambdaHostOptions = Microsoft.Extensions.Options.Options.Create( new LambdaHostOptions() ); - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, lambdaHostOptions); + var contextFactory = Substitute.For(); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + lambdaHostOptions, + contextFactory + ); var exception1 = new InvalidOperationException("Error 1"); var exception2 = new ArgumentException("Error 2"); - LambdaInitDelegate handler1 = (_, _) => throw exception1; + LambdaInitDelegate handler1 = _ => throw exception1; - LambdaInitDelegate handler2 = (_, _) => throw exception2; + LambdaInitDelegate handler2 = _ => throw exception2; builder.OnInit(handler1); builder.OnInit(handler2); @@ -363,18 +445,26 @@ public async Task Build_WithMultipleFailures_AggregatesAllErrors() [Theory] [AutoNSubstituteData] - public async Task Build_RespectsInitTimeout(IServiceScopeFactory scopeFactory) + internal async Task Build_RespectsInitTimeout( + IServiceScopeFactory scopeFactory, + ILambdaLifecycleContextFactory contextFactory + ) { // Arrange var lambdaHostOptions = Microsoft.Extensions.Options.Options.Create( new LambdaHostOptions { InitTimeout = TimeSpan.FromMilliseconds(50) } ); var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, lambdaHostOptions); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + lambdaHostOptions, + contextFactory + ); - LambdaInitDelegate slowHandler = async (_, cancellationToken) => + LambdaInitDelegate slowHandler = async context => { - await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken); + await Task.Delay(TimeSpan.FromSeconds(10), context.CancellationToken); return true; }; @@ -390,22 +480,28 @@ public async Task Build_RespectsInitTimeout(IServiceScopeFactory scopeFactory) [Theory] [AutoNSubstituteData] - public async Task Build_CreatesServiceScopeForEachHandler( + internal async Task Build_CreatesServiceScopeForEachHandler( IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory + IServiceScopeFactory scopeFactory, + ILambdaLifecycleContextFactory contextFactory ) { // Arrange var lambdaHostOptions = Microsoft.Extensions.Options.Options.Create( new LambdaHostOptions() ); - var builder = new LambdaOnInitBuilder(serviceProvider, scopeFactory, lambdaHostOptions); + var builder = new LambdaOnInitBuilder( + serviceProvider, + scopeFactory, + lambdaHostOptions, + contextFactory + ); var scopeUsed = false; - LambdaInitDelegate handler = (scope, _) => + LambdaInitDelegate handler = context => { - scopeUsed = scope != serviceProvider; + scopeUsed = context.ServiceProvider != serviceProvider; return Task.FromResult(true); }; diff --git a/tests/MinimalLambda.UnitTests/Builder/LambdaOnShutdownBuilderTests.cs b/tests/MinimalLambda.UnitTests/Builder/LambdaOnShutdownBuilderTests.cs index e3483509..1429402c 100644 --- a/tests/MinimalLambda.UnitTests/Builder/LambdaOnShutdownBuilderTests.cs +++ b/tests/MinimalLambda.UnitTests/Builder/LambdaOnShutdownBuilderTests.cs @@ -1,5 +1,3 @@ -using Microsoft.Extensions.DependencyInjection; - namespace MinimalLambda.UnitTests.Builder; [TestSubject(typeof(LambdaOnShutdownBuilder))] @@ -7,72 +5,8 @@ public class LambdaOnShutdownBuilderTests { [Theory] [AutoNSubstituteData] - public void Constructor_WithNullServiceProvider_ThrowsArgumentNullException( - IServiceScopeFactory scopeFactory - ) - { - // Act - var act = () => new LambdaOnShutdownBuilder(null!, scopeFactory); - - // Assert - act.Should().ThrowExactly().WithParameterName("serviceProvider"); - } - - [Theory] - [AutoNSubstituteData] - public void Constructor_WithNullScopeFactory_ThrowsArgumentNullException( - IServiceProvider serviceProvider - ) - { - // Act - var act = () => new LambdaOnShutdownBuilder(serviceProvider, null!); - - // Assert - act.Should().ThrowExactly().WithParameterName("scopeFactory"); - } - - [Theory] - [AutoNSubstituteData] - public void Constructor_WithValidParameters_Succeeds( - IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory - ) + internal void ShutdownHandlers_ReturnsReadOnlyList(LambdaOnShutdownBuilder builder) { - // Act - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - - // Assert - builder.Should().NotBeNull(); - builder.Services.Should().Be(serviceProvider); - } - - [Theory] - [AutoNSubstituteData] - public void Services_ReturnsServiceProvider( - IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory - ) - { - // Arrange - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - - // Act - var result = builder.Services; - - // Assert - result.Should().Be(serviceProvider); - } - - [Theory] - [AutoNSubstituteData] - public void ShutdownHandlers_ReturnsReadOnlyList( - IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory - ) - { - // Arrange - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - // Act var handlers = builder.ShutdownHandlers; @@ -84,14 +18,10 @@ IServiceScopeFactory scopeFactory [Theory] [AutoNSubstituteData] - public void OnShutdown_WithNullHandler_ThrowsArgumentNullException( - IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory + internal void OnShutdown_WithNullHandler_ThrowsArgumentNullException( + LambdaOnShutdownBuilder builder ) { - // Arrange - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - // Act var act = () => builder.OnShutdown(null!); @@ -101,14 +31,12 @@ IServiceScopeFactory scopeFactory [Theory] [AutoNSubstituteData] - public void OnShutdown_WithValidHandler_AddsHandlerAndReturnsBuilder( - IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory + internal void OnShutdown_WithValidHandler_AddsHandlerAndReturnsBuilder( + LambdaOnShutdownBuilder builder ) { // Arrange - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - LambdaShutdownDelegate handler = (_, _) => Task.CompletedTask; + LambdaShutdownDelegate handler = _ => Task.CompletedTask; // Act var result = builder.OnShutdown(handler); @@ -120,16 +48,12 @@ IServiceScopeFactory scopeFactory [Theory] [AutoNSubstituteData] - public void OnShutdown_MultipleHandlers_AllAdded( - IServiceProvider serviceProvider, - IServiceScopeFactory scopeFactory - ) + internal void OnShutdown_MultipleHandlers_AllAdded(LambdaOnShutdownBuilder builder) { // Arrange - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - LambdaShutdownDelegate handler1 = (_, _) => Task.CompletedTask; - LambdaShutdownDelegate handler2 = (_, _) => Task.CompletedTask; - LambdaShutdownDelegate handler3 = (_, _) => Task.CompletedTask; + LambdaShutdownDelegate handler1 = _ => Task.CompletedTask; + LambdaShutdownDelegate handler2 = _ => Task.CompletedTask; + LambdaShutdownDelegate handler3 = _ => Task.CompletedTask; // Act builder.OnShutdown(handler1); @@ -141,14 +65,12 @@ IServiceScopeFactory scopeFactory builder.ShutdownHandlers.Should().Equal(handler1, handler2, handler3); } - [Fact] - public async Task Build_WithoutHandlers_ReturnsCompletedTaskFunction() + [Theory] + [AutoNSubstituteData] + internal async Task Build_WithoutHandlers_ReturnsCompletedTaskFunction( + LambdaOnShutdownBuilder builder + ) { - // Arrange - var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var scopeFactory = serviceProvider.GetRequiredService(); - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - // Act var buildFunc = builder.Build(); var task = buildFunc(CancellationToken.None); @@ -158,16 +80,14 @@ public async Task Build_WithoutHandlers_ReturnsCompletedTaskFunction() task.IsCompletedSuccessfully.Should().BeTrue(); } - [Fact] - public async Task Build_WithSingleHandler_ExecutesHandler() + [Theory] + [AutoNSubstituteData] + internal async Task Build_WithSingleHandler_ExecutesHandler(LambdaOnShutdownBuilder builder) { // Arrange - var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var scopeFactory = serviceProvider.GetRequiredService(); - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); var handlerCalled = false; - LambdaShutdownDelegate handler = (_, _) => + LambdaShutdownDelegate handler = _ => { handlerCalled = true; return Task.CompletedTask; @@ -183,30 +103,28 @@ public async Task Build_WithSingleHandler_ExecutesHandler() handlerCalled.Should().BeTrue(); } - [Fact] - public async Task Build_WithMultipleHandlers_AllExecuted() + [Theory] + [AutoNSubstituteData] + internal async Task Build_WithMultipleHandlers_AllExecuted(LambdaOnShutdownBuilder builder) { // Arrange - var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var scopeFactory = serviceProvider.GetRequiredService(); - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); var handler1Called = false; var handler2Called = false; var handler3Called = false; - LambdaShutdownDelegate handler1 = (_, _) => + LambdaShutdownDelegate handler1 = _ => { handler1Called = true; return Task.CompletedTask; }; - LambdaShutdownDelegate handler2 = (_, _) => + LambdaShutdownDelegate handler2 = _ => { handler2Called = true; return Task.CompletedTask; }; - LambdaShutdownDelegate handler3 = (_, _) => + LambdaShutdownDelegate handler3 = _ => { handler3Called = true; return Task.CompletedTask; @@ -226,16 +144,16 @@ public async Task Build_WithMultipleHandlers_AllExecuted() handler3Called.Should().BeTrue(); } - [Fact] - public async Task Build_WhenHandlerThrowsException_ThrowsAggregateException() + [Theory] + [AutoNSubstituteData] + internal async Task Build_WhenHandlerThrowsException_ThrowsAggregateException( + LambdaOnShutdownBuilder builder + ) { // Arrange - var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var scopeFactory = serviceProvider.GetRequiredService(); - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); var testException = new InvalidOperationException("Test error"); - LambdaShutdownDelegate handler = (_, _) => throw testException; + LambdaShutdownDelegate handler = _ => throw testException; builder.OnShutdown(handler); @@ -247,19 +165,19 @@ public async Task Build_WhenHandlerThrowsException_ThrowsAggregateException() await act.Should().ThrowAsync(); } - [Fact] - public async Task Build_WithMultipleFailures_AggregatesAllErrors() + [Theory] + [AutoNSubstituteData] + internal async Task Build_WithMultipleFailures_AggregatesAllErrors( + LambdaOnShutdownBuilder builder + ) { // Arrange - var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var scopeFactory = serviceProvider.GetRequiredService(); - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); var exception1 = new InvalidOperationException("Error 1"); var exception2 = new ArgumentException("Error 2"); - LambdaShutdownDelegate handler1 = (_, _) => throw exception1; + LambdaShutdownDelegate handler1 = _ => throw exception1; - LambdaShutdownDelegate handler2 = (_, _) => throw exception2; + LambdaShutdownDelegate handler2 = _ => throw exception2; builder.OnShutdown(handler1); builder.OnShutdown(handler2); @@ -272,23 +190,23 @@ public async Task Build_WithMultipleFailures_AggregatesAllErrors() await act.Should().ThrowAsync(); } - [Fact] - public async Task Build_WithMixedSuccessAndFailure_AggregatesOnlyErrors() + [Theory] + [AutoNSubstituteData] + internal async Task Build_WithMixedSuccessAndFailure_AggregatesOnlyErrors( + LambdaOnShutdownBuilder builder + ) { // Arrange - var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var scopeFactory = serviceProvider.GetRequiredService(); - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); var successfulHandlerCalled = false; var testException = new InvalidOperationException("Test error"); - LambdaShutdownDelegate successHandler = (_, _) => + LambdaShutdownDelegate successHandler = _ => { successfulHandlerCalled = true; return Task.CompletedTask; }; - LambdaShutdownDelegate failingHandler = (_, _) => throw testException; + LambdaShutdownDelegate failingHandler = _ => throw testException; builder.OnShutdown(successHandler); builder.OnShutdown(failingHandler); @@ -301,82 +219,4 @@ public async Task Build_WithMixedSuccessAndFailure_AggregatesOnlyErrors() await act.Should().ThrowAsync(); successfulHandlerCalled.Should().BeTrue(); } - - [Fact] - public async Task Build_CreatesServiceScopeForEachHandler() - { - // Arrange - var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var scopeFactory = serviceProvider.GetRequiredService(); - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - - var scopeUsed = false; - - LambdaShutdownDelegate handler = (scope, _) => - { - scopeUsed = scope != serviceProvider; - return Task.CompletedTask; - }; - - builder.OnShutdown(handler); - - // Act - var buildFunc = builder.Build(); - await buildFunc(CancellationToken.None); - - // Assert - scopeUsed.Should().BeTrue(); - } - - [Fact] - public async Task Build_RespectsCancellationToken() - { - // Arrange - var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var scopeFactory = serviceProvider.GetRequiredService(); - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - - var cancellationTokenReceived = false; - - LambdaShutdownDelegate handler = (_, cancellationToken) => - { - cancellationTokenReceived = !cancellationToken.IsCancellationRequested; - return Task.CompletedTask; - }; - - builder.OnShutdown(handler); - - // Act - var buildFunc = builder.Build(); - using var cts = new CancellationTokenSource(); - await buildFunc(cts.Token); - - // Assert - cancellationTokenReceived.Should().BeTrue(); - } - - [Fact] - public async Task Build_WithCancelledToken_RespectsCancellation() - { - // Arrange - var serviceProvider = new ServiceCollection().BuildServiceProvider(); - var scopeFactory = serviceProvider.GetRequiredService(); - var builder = new LambdaOnShutdownBuilder(serviceProvider, scopeFactory); - - LambdaShutdownDelegate handler = async (_, cancellationToken) => - { - await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken); - }; - - builder.OnShutdown(handler); - - // Act - var buildFunc = builder.Build(); - using var cts = new CancellationTokenSource(); - cts.Cancel(); - var act = () => buildFunc(cts.Token); - - // Assert - await act.Should().ThrowAsync(); - } } diff --git a/tests/MinimalLambda.UnitTests/Builder/OnInit/OutputFormattingLambdaApplicationExtensionsTests.cs b/tests/MinimalLambda.UnitTests/Builder/OnInit/OutputFormattingLambdaApplicationExtensionsTests.cs index 7d387a1b..23639c55 100644 --- a/tests/MinimalLambda.UnitTests/Builder/OnInit/OutputFormattingLambdaApplicationExtensionsTests.cs +++ b/tests/MinimalLambda.UnitTests/Builder/OnInit/OutputFormattingLambdaApplicationExtensionsTests.cs @@ -1,4 +1,3 @@ -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace MinimalLambda.UnitTests.Application.Extensions; @@ -6,18 +5,8 @@ namespace MinimalLambda.UnitTests.Application.Extensions; [TestSubject(typeof(OutputFormattingLambdaApplicationExtensions))] public class OutputFormattingLambdaApplicationExtensionsTests { - private static IHost CreateHostWithServices() - { - var builder = Host.CreateDefaultBuilder(); - builder.ConfigureServices(services => - { - services.ConfigureLambdaHostOptions(_ => { }); - services.AddLambdaHostCoreServices(); - services.TryAddLambdaHostDefaultServices(); - }); - - return builder.Build(); - } + private static IHost CreateHostWithServices() => + new LambdaApplicationBuilder(new LambdaApplicationOptions()).Build(); [Fact] public void OnInitClearLambdaOutputFormatting_WithNullApplication_ThrowsArgumentNullException() diff --git a/tests/MinimalLambda.UnitTests/Core/Context/LambdaLifecycleContextFactoryTests.cs b/tests/MinimalLambda.UnitTests/Core/Context/LambdaLifecycleContextFactoryTests.cs new file mode 100644 index 00000000..43a957c4 --- /dev/null +++ b/tests/MinimalLambda.UnitTests/Core/Context/LambdaLifecycleContextFactoryTests.cs @@ -0,0 +1,545 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace MinimalLambda.UnitTests.Core.Context; + +[TestSubject(typeof(LambdaLifecycleContextFactory))] +public class LambdaLifecycleContextFactoryTests +{ + [Theory] + [AutoNSubstituteData] + internal void Constructor_WithValidDependencies_SuccessfullyConstructs( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch, + IConfiguration configuration + ) + { + // Act + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Assert + factory.Should().NotBeNull(); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReturnsLambdaLifecycleContext( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch, + IConfiguration configuration, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(properties, cancellationToken); + + // Assert + result.Should().NotBeNull(); + result.Should().BeAssignableTo(); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_PassesPropertiesAndCancellationTokenToContext( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch, + IConfiguration configuration + ) + { + // Arrange + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + var properties = new Dictionary { { "key", "value" } }; + var cancellationToken = new CancellationToken(); + + // Act + var result = factory.Create(properties, cancellationToken); + + // Assert + result.Properties.Should().BeSameAs(properties); + result.CancellationToken.Should().Be(cancellationToken); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsRegionFromAwsRegionConfiguration( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary { { "AWS_REGION", "us-east-1" } }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.Region.Should().Be("us-east-1"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsRegionFromAwsDefaultRegionWhenAwsRegionNotSet( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_DEFAULT_REGION", "us-west-2" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.Region.Should().Be("us-west-2"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_PrefersAwsRegionOverAwsDefaultRegion( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_REGION", "us-east-1" }, + { "AWS_DEFAULT_REGION", "us-west-2" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.Region.Should().Be("us-east-1"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsExecutionEnvironmentFromConfiguration( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_EXECUTION_ENV", "AWS_Lambda_dotnet8" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.ExecutionEnvironment.Should().Be("AWS_Lambda_dotnet8"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsFunctionNameFromConfiguration( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_LAMBDA_FUNCTION_NAME", "my-lambda-function" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.FunctionName.Should().Be("my-lambda-function"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsFunctionMemorySizeFromConfiguration( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "512" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.FunctionMemorySize.Should().Be(512); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReturnsNullForFunctionMemorySizeWhenNotParseable( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "not-a-number" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.FunctionMemorySize.Should().BeNull(); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsFunctionVersionFromConfiguration( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_LAMBDA_FUNCTION_VERSION", "$LATEST" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.FunctionVersion.Should().Be("$LATEST"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsInitializationTypeFromConfiguration( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_LAMBDA_INITIALIZATION_TYPE", "on-demand" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.InitializationType.Should().Be("on-demand"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsLogGroupNameFromConfiguration( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_LAMBDA_LOG_GROUP_NAME", "/aws/lambda/my-function" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.LogGroupName.Should().Be("/aws/lambda/my-function"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsLogStreamNameFromConfiguration( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_LAMBDA_LOG_STREAM_NAME", "2024/12/16/[$LATEST]abcdef123456" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.LogStreamName.Should().Be("2024/12/16/[$LATEST]abcdef123456"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReadsTaskRootFromConfiguration( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary { { "LAMBDA_TASK_ROOT", "/var/task" } }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.TaskRoot.Should().Be("/var/task"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_UsesStopwatchFromConstructor( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch, + IConfiguration configuration + ) + { + // Arrange + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + (result.ElapsedTime >= TimeSpan.Zero) + .Should() + .BeTrue(); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReusesContextCoreAcrossMultipleCalls( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_REGION", "us-east-1" }, + { "AWS_LAMBDA_FUNCTION_NAME", "my-function" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result1 = factory.Create(new Dictionary(), CancellationToken.None); + var result2 = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result1.Region.Should().Be("us-east-1"); + result2.Region.Should().Be("us-east-1"); + result1.FunctionName.Should().Be("my-function"); + result2.FunctionName.Should().Be("my-function"); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_ReturnsNullForUnconfiguredProperties( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configuration = new ConfigurationBuilder().Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.Region.Should().BeNull(); + result.ExecutionEnvironment.Should().BeNull(); + result.FunctionName.Should().BeNull(); + result.FunctionMemorySize.Should().BeNull(); + result.FunctionVersion.Should().BeNull(); + result.InitializationType.Should().BeNull(); + result.LogGroupName.Should().BeNull(); + result.LogStreamName.Should().BeNull(); + result.TaskRoot.Should().BeNull(); + } + + [Theory] + [AutoNSubstituteData] + internal void Create_WithAllConfigurationValues_PopulatesAllProperties( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch + ) + { + // Arrange + var configValues = new Dictionary + { + { "AWS_REGION", "us-east-1" }, + { "AWS_EXECUTION_ENV", "AWS_Lambda_dotnet8" }, + { "AWS_LAMBDA_FUNCTION_NAME", "my-lambda-function" }, + { "AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "1024" }, + { "AWS_LAMBDA_FUNCTION_VERSION", "$LATEST" }, + { "AWS_LAMBDA_INITIALIZATION_TYPE", "provisioned-concurrency" }, + { "AWS_LAMBDA_LOG_GROUP_NAME", "/aws/lambda/my-function" }, + { "AWS_LAMBDA_LOG_STREAM_NAME", "2024/12/16/[$LATEST]abcdef123456" }, + { "LAMBDA_TASK_ROOT", "/var/task" }, + }; + var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build(); + + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Act + var result = factory.Create(new Dictionary(), CancellationToken.None); + + // Assert + result.Region.Should().Be("us-east-1"); + result.ExecutionEnvironment.Should().Be("AWS_Lambda_dotnet8"); + result.FunctionName.Should().Be("my-lambda-function"); + result.FunctionMemorySize.Should().Be(1024); + result.FunctionVersion.Should().Be("$LATEST"); + result.InitializationType.Should().Be("provisioned-concurrency"); + result.LogGroupName.Should().Be("/aws/lambda/my-function"); + result.LogStreamName.Should().Be("2024/12/16/[$LATEST]abcdef123456"); + result.TaskRoot.Should().Be("/var/task"); + } + + [Theory] + [AutoNSubstituteData] + internal void FactoryImplementsILambdaLifecycleContextFactory( + IServiceScopeFactory serviceScopeFactory, + LifetimeStopwatch stopwatch, + IConfiguration configuration + ) + { + // Act + var factory = new LambdaLifecycleContextFactory( + serviceScopeFactory, + stopwatch, + configuration + ); + + // Assert + factory.Should().BeAssignableTo(); + } +} diff --git a/tests/MinimalLambda.UnitTests/Core/Context/LambdaLifecycleContextTests.cs b/tests/MinimalLambda.UnitTests/Core/Context/LambdaLifecycleContextTests.cs new file mode 100644 index 00000000..7bdb3309 --- /dev/null +++ b/tests/MinimalLambda.UnitTests/Core/Context/LambdaLifecycleContextTests.cs @@ -0,0 +1,685 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace MinimalLambda.UnitTests.Core.Context; + +[TestSubject(typeof(LambdaLifecycleContext))] +public class LambdaLifecycleContextTests +{ + [Theory] + [AutoNSubstituteData] + internal void Constructor_WithValidParameters_SuccessfullyConstructs( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + Region = "us-east-1", + }; + + // Act + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Assert + context.Should().NotBeNull(); + } + + [Theory] + [AutoNSubstituteData] + internal void CancellationToken_ReturnsCancellationTokenPassedToConstructor( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties + ) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + var expectedToken = new CancellationToken(); + + // Act + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + expectedToken + ); + + // Assert + context.CancellationToken.Should().Be(expectedToken); + } + + [Theory] + [AutoNSubstituteData] + internal void Properties_ReturnsPropertiesDictionaryPassedToConstructor( + IServiceScopeFactory serviceScopeFactory, + CancellationToken cancellationToken + ) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + var propertiesDict = new Dictionary + { + { "key1", "value1" }, + { "key2", 42 }, + }; + + // Act + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + propertiesDict, + cancellationToken + ); + + // Assert + context.Properties.Should().BeEquivalentTo(propertiesDict); + context.Properties.Should().BeSameAs(propertiesDict); + } + + [Theory] + [AutoNSubstituteData] + internal void ServiceProvider_IsCreatedOnFirstAccess(IServiceScopeFactory serviceScopeFactory) + { + // Arrange + var mockScope = Substitute.For(); + var mockServiceProvider = Substitute.For(); + mockScope.ServiceProvider.Returns(mockServiceProvider); + serviceScopeFactory.CreateScope().Returns(mockScope); + + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + new Dictionary(), + CancellationToken.None + ); + + // Act + var result = context.ServiceProvider; + + // Assert + result.Should().NotBeNull(); + result.Should().BeSameAs(mockServiceProvider); + serviceScopeFactory.Received(1).CreateScope(); + } + + [Theory] + [AutoNSubstituteData] + internal void ServiceProvider_ReturnsSameScopeOnSubsequentAccess( + IServiceScopeFactory serviceScopeFactory + ) + { + // Arrange + var mockScope = Substitute.For(); + var mockServiceProvider = Substitute.For(); + mockScope.ServiceProvider.Returns(mockServiceProvider); + serviceScopeFactory.CreateScope().Returns(mockScope); + + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + new Dictionary(), + CancellationToken.None + ); + + // Act + var result1 = context.ServiceProvider; + var result2 = context.ServiceProvider; + var result3 = context.ServiceProvider; + + // Assert + result1.Should().BeSameAs(result2); + result2.Should().BeSameAs(result3); + serviceScopeFactory.Received(1).CreateScope(); + } + + [Theory] + [AutoNSubstituteData] + internal void ElapsedTime_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.ElapsedTime; + + // Assert + (result >= TimeSpan.Zero) + .Should() + .BeTrue(); + } + + [Theory] + [AutoNSubstituteData] + internal void Region_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + const string expectedValue = "us-west-2"; + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + Region = expectedValue, + }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.Region; + + // Assert + result.Should().Be(expectedValue); + } + + [Theory] + [AutoNSubstituteData] + internal void ExecutionEnvironment_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + const string expectedValue = "AWS_Lambda_dotnet8"; + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + ExecutionEnvironment = expectedValue, + }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.ExecutionEnvironment; + + // Assert + result.Should().Be(expectedValue); + } + + [Theory] + [AutoNSubstituteData] + internal void FunctionName_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + const string expectedValue = "my-lambda-function"; + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + FunctionName = expectedValue, + }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.FunctionName; + + // Assert + result.Should().Be(expectedValue); + } + + [Theory] + [AutoNSubstituteData] + internal void FunctionMemorySize_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + const int expectedValue = 512; + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + FunctionMemorySize = expectedValue, + }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.FunctionMemorySize; + + // Assert + result.Should().Be(expectedValue); + } + + [Theory] + [AutoNSubstituteData] + internal void FunctionVersion_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + const string expectedValue = "$LATEST"; + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + FunctionVersion = expectedValue, + }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.FunctionVersion; + + // Assert + result.Should().Be(expectedValue); + } + + [Theory] + [AutoNSubstituteData] + internal void InitializationType_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + const string expectedValue = "on-demand"; + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + InitializationType = expectedValue, + }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.InitializationType; + + // Assert + result.Should().Be(expectedValue); + } + + [Theory] + [AutoNSubstituteData] + internal void LogGroupName_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + const string expectedValue = "/aws/lambda/my-function"; + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + LogGroupName = expectedValue, + }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.LogGroupName; + + // Assert + result.Should().Be(expectedValue); + } + + [Theory] + [AutoNSubstituteData] + internal void LogStreamName_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + const string expectedValue = "2024/12/16/[$LATEST]abcdef123456"; + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + LogStreamName = expectedValue, + }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.LogStreamName; + + // Assert + result.Should().Be(expectedValue); + } + + [Theory] + [AutoNSubstituteData] + internal void TaskRoot_ReturnsValueFromContextCore( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + const string expectedValue = "/var/task"; + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + TaskRoot = expectedValue, + }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Act + var result = context.TaskRoot; + + // Assert + result.Should().Be(expectedValue); + } + + [Theory] + [AutoNSubstituteData] + internal async Task DisposeAsync_DisposesServiceScopeWhenAsyncDisposable( + IServiceScopeFactory serviceScopeFactory + ) + { + // Arrange + var asyncDisposableScope = Substitute.For(); + var mockServiceProvider = Substitute.For(); + asyncDisposableScope.ServiceProvider.Returns(mockServiceProvider); + serviceScopeFactory.CreateScope().Returns(asyncDisposableScope); + + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + new Dictionary(), + CancellationToken.None + ); + _ = context.ServiceProvider; // Trigger lazy initialization + + // Act + await context.DisposeAsync(); + + // Assert + await ((IAsyncDisposable)asyncDisposableScope).Received(1).DisposeAsync(); + } + + [Theory] + [AutoNSubstituteData] + internal async Task DisposeAsync_DisposesServiceScopeSynchronouslyWhenNotAsyncDisposable( + IServiceScopeFactory serviceScopeFactory + ) + { + // Arrange + var mockScope = Substitute.For(); + var mockServiceProvider = Substitute.For(); + mockScope.ServiceProvider.Returns(mockServiceProvider); + serviceScopeFactory.CreateScope().Returns(mockScope); + + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + new Dictionary(), + CancellationToken.None + ); + _ = context.ServiceProvider; // Trigger lazy initialization + + // Act + await context.DisposeAsync(); + + // Assert + mockScope.Received(1).Dispose(); + } + + [Theory] + [AutoNSubstituteData] + internal async Task DisposeAsync_DoesNotDisposeIfServiceProviderNeverAccessed( + IServiceScopeFactory serviceScopeFactory + ) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + new Dictionary(), + CancellationToken.None + ); + + // Act + await context.DisposeAsync(); + + // Assert + serviceScopeFactory.DidNotReceive().CreateScope(); + } + + [Theory] + [AutoNSubstituteData] + internal async Task DisposeAsync_CanBeCalledMultipleTimes( + IServiceScopeFactory serviceScopeFactory + ) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + new Dictionary(), + CancellationToken.None + ); + + // Act + var act = async () => + { + await context.DisposeAsync(); + await context.DisposeAsync(); // Should not throw + }; + + // Assert + await act.Should().NotThrowAsync(); + } + + [Theory] + [AutoNSubstituteData] + internal void ContextImplementsIAsyncDisposable(IServiceScopeFactory serviceScopeFactory) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + // Act + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + new Dictionary(), + CancellationToken.None + ); + + // Assert + context.Should().BeAssignableTo(); + } + + [Theory] + [AutoNSubstituteData] + internal void ContextImplementsILambdaLifecycleContext(IServiceScopeFactory serviceScopeFactory) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + // Act + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + new Dictionary(), + CancellationToken.None + ); + + // Assert + context.Should().BeAssignableTo(); + } + + [Theory] + [AutoNSubstituteData] + internal void MultipleContextInstances_AreIndependent(IServiceScopeFactory serviceScopeFactory) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore1 = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + Region = "us-east-1", + }; + var contextCore2 = new LambdaLifecycleContext.Core + { + Stopwatch = stopwatch, + Region = "us-west-2", + }; + + var properties1 = new Dictionary(); + var properties2 = new Dictionary(); + + // Act + var context1 = new LambdaLifecycleContext( + contextCore1, + serviceScopeFactory, + properties1, + CancellationToken.None + ); + var context2 = new LambdaLifecycleContext( + contextCore2, + serviceScopeFactory, + properties2, + CancellationToken.None + ); + + properties1["key"] = "value1"; + properties2["key"] = "value2"; + + // Assert + context1.Properties["key"].Should().Be("value1"); + context2.Properties["key"].Should().Be("value2"); + context1.Region.Should().Be("us-east-1"); + context2.Region.Should().Be("us-west-2"); + } + + [Theory] + [AutoNSubstituteData] + internal void NullableProperties_ReturnNullWhenNotSet( + IServiceScopeFactory serviceScopeFactory, + IDictionary properties, + CancellationToken cancellationToken + ) + { + // Arrange + var stopwatch = new LifetimeStopwatch(); + var contextCore = new LambdaLifecycleContext.Core { Stopwatch = stopwatch }; + + // Act + var context = new LambdaLifecycleContext( + contextCore, + serviceScopeFactory, + properties, + cancellationToken + ); + + // Assert + context.Region.Should().BeNull(); + context.ExecutionEnvironment.Should().BeNull(); + context.FunctionName.Should().BeNull(); + context.FunctionMemorySize.Should().BeNull(); + context.FunctionVersion.Should().BeNull(); + context.InitializationType.Should().BeNull(); + context.LogGroupName.Should().BeNull(); + context.LogStreamName.Should().BeNull(); + context.TaskRoot.Should().BeNull(); + } +}