namespace ZB.MOM.WW.MxGateway.Client.Tests; public sealed class MxGatewayClientOptionsTests { /// /// The safe-unary budget covers every attempt's deadline plus the backoff between them, so a /// first attempt that hits its deadline does not consume the retry's time (#197). /// [Fact] public void SafeUnaryBudget_CoversEveryAttemptAndBackoff() { var options = new MxGatewayClientOptions { Endpoint = new Uri("http://localhost:5000"), ApiKey = "test-api-key", DefaultCallTimeout = TimeSpan.FromSeconds(30), Retry = new MxGatewayClientRetryOptions { MaxAttempts = 3, MaxDelay = TimeSpan.FromSeconds(2) }, }; Assert.Equal(TimeSpan.FromSeconds(94), MxGatewayClientRetryPolicy.SafeUnaryBudget(options)); } /// A budget beyond what a cancellation timer accepts means no outer cap rather than a throw. [Fact] public void SafeUnaryBudget_WhenTooLargeForATimer_ReturnsNull() { var options = new MxGatewayClientOptions { Endpoint = new Uri("http://localhost:5000"), ApiKey = "test-api-key", DefaultCallTimeout = TimeSpan.FromDays(40), Retry = new MxGatewayClientRetryOptions { MaxAttempts = 2 }, }; Assert.Null(MxGatewayClientRetryPolicy.SafeUnaryBudget(options)); } /// Verifies that options with valid endpoint and API key pass validation. [Fact] public void Validate_WithAbsoluteEndpointAndApiKey_Succeeds() { var options = new MxGatewayClientOptions { Endpoint = new Uri("http://localhost:5000"), ApiKey = "test-api-key", }; options.Validate(); } /// Verifies that empty API key causes validation to fail. [Fact] public void Validate_WithEmptyApiKey_Throws() { var options = new MxGatewayClientOptions { Endpoint = new Uri("http://localhost:5000"), ApiKey = "", }; Assert.Throws(options.Validate); } /// Verifies that invalid retry options cause validation to fail. [Fact] public void Validate_WithInvalidRetryOptions_Throws() { var options = new MxGatewayClientOptions { Endpoint = new Uri("http://localhost:5000"), ApiKey = "test-api-key", Retry = new MxGatewayClientRetryOptions { MaxAttempts = 0 }, }; Assert.Throws(options.Validate); } }