using ChatBot.Models.Configuration; using FluentAssertions; namespace ChatBot.Tests.Models; public class AISettingsTests { [Fact] public void Constructor_ShouldInitializePropertiesWithDefaultValues() { // Arrange & Act var settings = new AISettings(); // Assert settings.Temperature.Should().Be(0.7); settings.SystemPromptPath.Should().Be("Prompts/system-prompt.txt"); settings.SystemPrompt.Should().Be(string.Empty); settings.MaxRetryAttempts.Should().Be(3); settings.RetryDelayMs.Should().Be(1000); settings.RequestTimeoutSeconds.Should().Be(60); settings.EnableHistoryCompression.Should().BeTrue(); settings.CompressionThreshold.Should().Be(20); settings.CompressionTarget.Should().Be(10); settings.MinMessageLengthForSummarization.Should().Be(50); settings.MaxSummarizedMessageLength.Should().Be(200); settings.EnableExponentialBackoff.Should().BeTrue(); settings.MaxRetryDelayMs.Should().Be(30000); settings.CompressionTimeoutSeconds.Should().Be(30); settings.StatusCheckTimeoutSeconds.Should().Be(10); } [Fact] public void Temperature_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedTemperature = 1.5; // Act settings.Temperature = expectedTemperature; // Assert settings.Temperature.Should().Be(expectedTemperature); } [Fact] public void SystemPromptPath_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedPath = "Custom/prompt.txt"; // Act settings.SystemPromptPath = expectedPath; // Assert settings.SystemPromptPath.Should().Be(expectedPath); } [Fact] public void SystemPrompt_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedPrompt = "You are a helpful assistant."; // Act settings.SystemPrompt = expectedPrompt; // Assert settings.SystemPrompt.Should().Be(expectedPrompt); } [Fact] public void MaxRetryAttempts_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedAttempts = 5; // Act settings.MaxRetryAttempts = expectedAttempts; // Assert settings.MaxRetryAttempts.Should().Be(expectedAttempts); } [Fact] public void RetryDelayMs_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedDelay = 2000; // Act settings.RetryDelayMs = expectedDelay; // Assert settings.RetryDelayMs.Should().Be(expectedDelay); } [Fact] public void RequestTimeoutSeconds_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedTimeout = 120; // Act settings.RequestTimeoutSeconds = expectedTimeout; // Assert settings.RequestTimeoutSeconds.Should().Be(expectedTimeout); } [Fact] public void EnableHistoryCompression_ShouldBeSettable() { // Arrange var settings = new AISettings(); // Act settings.EnableHistoryCompression = false; // Assert settings.EnableHistoryCompression.Should().BeFalse(); } [Fact] public void CompressionThreshold_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedThreshold = 50; // Act settings.CompressionThreshold = expectedThreshold; // Assert settings.CompressionThreshold.Should().Be(expectedThreshold); } [Fact] public void CompressionTarget_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedTarget = 15; // Act settings.CompressionTarget = expectedTarget; // Assert settings.CompressionTarget.Should().Be(expectedTarget); } [Fact] public void MinMessageLengthForSummarization_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedLength = 100; // Act settings.MinMessageLengthForSummarization = expectedLength; // Assert settings.MinMessageLengthForSummarization.Should().Be(expectedLength); } [Fact] public void MaxSummarizedMessageLength_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedLength = 300; // Act settings.MaxSummarizedMessageLength = expectedLength; // Assert settings.MaxSummarizedMessageLength.Should().Be(expectedLength); } [Fact] public void EnableExponentialBackoff_ShouldBeSettable() { // Arrange var settings = new AISettings(); // Act settings.EnableExponentialBackoff = false; // Assert settings.EnableExponentialBackoff.Should().BeFalse(); } [Fact] public void MaxRetryDelayMs_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedDelay = 60000; // Act settings.MaxRetryDelayMs = expectedDelay; // Assert settings.MaxRetryDelayMs.Should().Be(expectedDelay); } [Fact] public void CompressionTimeoutSeconds_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedTimeout = 60; // Act settings.CompressionTimeoutSeconds = expectedTimeout; // Assert settings.CompressionTimeoutSeconds.Should().Be(expectedTimeout); } [Fact] public void StatusCheckTimeoutSeconds_ShouldBeSettable() { // Arrange var settings = new AISettings(); var expectedTimeout = 20; // Act settings.StatusCheckTimeoutSeconds = expectedTimeout; // Assert settings.StatusCheckTimeoutSeconds.Should().Be(expectedTimeout); } [Theory] [InlineData(0.0)] [InlineData(0.5)] [InlineData(1.0)] [InlineData(1.5)] [InlineData(2.0)] public void Temperature_ShouldAcceptValidRange(double temperature) { // Arrange var settings = new AISettings(); // Act settings.Temperature = temperature; // Assert settings.Temperature.Should().Be(temperature); } [Theory] [InlineData(-1.0)] [InlineData(2.5)] [InlineData(10.0)] public void Temperature_ShouldAcceptOutOfRangeValues(double temperature) { // Arrange var settings = new AISettings(); // Act settings.Temperature = temperature; // Assert settings.Temperature.Should().Be(temperature); } [Theory] [InlineData("")] [InlineData("prompt.txt")] [InlineData("Custom/path/prompt.txt")] [InlineData("C:\\Windows\\System32\\prompt.txt")] [InlineData("/usr/local/bin/prompt.txt")] public void SystemPromptPath_ShouldAcceptVariousPaths(string path) { // Arrange var settings = new AISettings(); // Act settings.SystemPromptPath = path; // Assert settings.SystemPromptPath.Should().Be(path); } [Theory] [InlineData("")] [InlineData("Short prompt")] [InlineData( "A very long system prompt that contains detailed instructions for the AI assistant on how to behave and respond to user queries in a helpful and informative manner." )] public void SystemPrompt_ShouldAcceptVariousContent(string prompt) { // Arrange var settings = new AISettings(); // Act settings.SystemPrompt = prompt; // Assert settings.SystemPrompt.Should().Be(prompt); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(5)] [InlineData(10)] [InlineData(int.MaxValue)] public void MaxRetryAttempts_ShouldAcceptVariousValues(int attempts) { // Arrange var settings = new AISettings(); // Act settings.MaxRetryAttempts = attempts; // Assert settings.MaxRetryAttempts.Should().Be(attempts); } [Theory] [InlineData(0)] [InlineData(100)] [InlineData(1000)] [InlineData(5000)] [InlineData(int.MaxValue)] public void RetryDelayMs_ShouldAcceptVariousValues(int delay) { // Arrange var settings = new AISettings(); // Act settings.RetryDelayMs = delay; // Assert settings.RetryDelayMs.Should().Be(delay); } [Theory] [InlineData(1)] [InlineData(30)] [InlineData(60)] [InlineData(300)] [InlineData(int.MaxValue)] public void RequestTimeoutSeconds_ShouldAcceptVariousValues(int timeout) { // Arrange var settings = new AISettings(); // Act settings.RequestTimeoutSeconds = timeout; // Assert settings.RequestTimeoutSeconds.Should().Be(timeout); } [Theory] [InlineData(true)] [InlineData(false)] public void EnableHistoryCompression_ShouldAcceptBooleanValues(bool enabled) { // Arrange var settings = new AISettings(); // Act settings.EnableHistoryCompression = enabled; // Assert settings.EnableHistoryCompression.Should().Be(enabled); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(10)] [InlineData(50)] [InlineData(100)] [InlineData(int.MaxValue)] public void CompressionThreshold_ShouldAcceptVariousValues(int threshold) { // Arrange var settings = new AISettings(); // Act settings.CompressionThreshold = threshold; // Assert settings.CompressionThreshold.Should().Be(threshold); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(5)] [InlineData(20)] [InlineData(100)] [InlineData(int.MaxValue)] public void CompressionTarget_ShouldAcceptVariousValues(int target) { // Arrange var settings = new AISettings(); // Act settings.CompressionTarget = target; // Assert settings.CompressionTarget.Should().Be(target); } [Theory] [InlineData(0)] [InlineData(10)] [InlineData(50)] [InlineData(100)] [InlineData(1000)] [InlineData(int.MaxValue)] public void MinMessageLengthForSummarization_ShouldAcceptVariousValues(int length) { // Arrange var settings = new AISettings(); // Act settings.MinMessageLengthForSummarization = length; // Assert settings.MinMessageLengthForSummarization.Should().Be(length); } [Theory] [InlineData(0)] [InlineData(50)] [InlineData(200)] [InlineData(500)] [InlineData(1000)] [InlineData(int.MaxValue)] public void MaxSummarizedMessageLength_ShouldAcceptVariousValues(int length) { // Arrange var settings = new AISettings(); // Act settings.MaxSummarizedMessageLength = length; // Assert settings.MaxSummarizedMessageLength.Should().Be(length); } [Theory] [InlineData(true)] [InlineData(false)] public void EnableExponentialBackoff_ShouldAcceptBooleanValues(bool enabled) { // Arrange var settings = new AISettings(); // Act settings.EnableExponentialBackoff = enabled; // Assert settings.EnableExponentialBackoff.Should().Be(enabled); } [Theory] [InlineData(0)] [InlineData(1000)] [InlineData(30000)] [InlineData(60000)] [InlineData(int.MaxValue)] public void MaxRetryDelayMs_ShouldAcceptVariousValues(int delay) { // Arrange var settings = new AISettings(); // Act settings.MaxRetryDelayMs = delay; // Assert settings.MaxRetryDelayMs.Should().Be(delay); } [Theory] [InlineData(1)] [InlineData(10)] [InlineData(30)] [InlineData(60)] [InlineData(300)] [InlineData(int.MaxValue)] public void CompressionTimeoutSeconds_ShouldAcceptVariousValues(int timeout) { // Arrange var settings = new AISettings(); // Act settings.CompressionTimeoutSeconds = timeout; // Assert settings.CompressionTimeoutSeconds.Should().Be(timeout); } [Theory] [InlineData(1)] [InlineData(5)] [InlineData(10)] [InlineData(30)] [InlineData(60)] [InlineData(int.MaxValue)] public void StatusCheckTimeoutSeconds_ShouldAcceptVariousValues(int timeout) { // Arrange var settings = new AISettings(); // Act settings.StatusCheckTimeoutSeconds = timeout; // Assert settings.StatusCheckTimeoutSeconds.Should().Be(timeout); } [Fact] public void AllProperties_ShouldBeMutable() { // Arrange var settings = new AISettings(); // Act settings.Temperature = 1.2; settings.SystemPromptPath = "custom/prompt.txt"; settings.SystemPrompt = "Custom system prompt"; settings.MaxRetryAttempts = 5; settings.RetryDelayMs = 2000; settings.RequestTimeoutSeconds = 120; settings.EnableHistoryCompression = false; settings.CompressionThreshold = 50; settings.CompressionTarget = 15; settings.MinMessageLengthForSummarization = 100; settings.MaxSummarizedMessageLength = 300; settings.EnableExponentialBackoff = false; settings.MaxRetryDelayMs = 60000; settings.CompressionTimeoutSeconds = 60; settings.StatusCheckTimeoutSeconds = 20; // Assert settings.Temperature.Should().Be(1.2); settings.SystemPromptPath.Should().Be("custom/prompt.txt"); settings.SystemPrompt.Should().Be("Custom system prompt"); settings.MaxRetryAttempts.Should().Be(5); settings.RetryDelayMs.Should().Be(2000); settings.RequestTimeoutSeconds.Should().Be(120); settings.EnableHistoryCompression.Should().BeFalse(); settings.CompressionThreshold.Should().Be(50); settings.CompressionTarget.Should().Be(15); settings.MinMessageLengthForSummarization.Should().Be(100); settings.MaxSummarizedMessageLength.Should().Be(300); settings.EnableExponentialBackoff.Should().BeFalse(); settings.MaxRetryDelayMs.Should().Be(60000); settings.CompressionTimeoutSeconds.Should().Be(60); settings.StatusCheckTimeoutSeconds.Should().Be(20); } [Fact] public void Settings_ShouldSupportHighTemperature() { // Arrange var settings = new AISettings(); // Act settings.Temperature = 2.0; // Assert settings.Temperature.Should().Be(2.0); } [Fact] public void Settings_ShouldSupportLowTemperature() { // Arrange var settings = new AISettings(); // Act settings.Temperature = 0.0; // Assert settings.Temperature.Should().Be(0.0); } [Fact] public void Settings_ShouldSupportDisabledCompression() { // Arrange var settings = new AISettings(); // Act settings.EnableHistoryCompression = false; // Assert settings.EnableHistoryCompression.Should().BeFalse(); } [Fact] public void Settings_ShouldSupportDisabledExponentialBackoff() { // Arrange var settings = new AISettings(); // Act settings.EnableExponentialBackoff = false; // Assert settings.EnableExponentialBackoff.Should().BeFalse(); } [Fact] public void Settings_ShouldSupportZeroRetryAttempts() { // Arrange var settings = new AISettings(); // Act settings.MaxRetryAttempts = 0; // Assert settings.MaxRetryAttempts.Should().Be(0); } [Fact] public void Settings_ShouldSupportZeroDelays() { // Arrange var settings = new AISettings(); // Act settings.RetryDelayMs = 0; settings.MaxRetryDelayMs = 0; // Assert settings.RetryDelayMs.Should().Be(0); settings.MaxRetryDelayMs.Should().Be(0); } [Fact] public void Settings_ShouldSupportZeroThresholds() { // Arrange var settings = new AISettings(); // Act settings.CompressionThreshold = 0; settings.CompressionTarget = 0; // Assert settings.CompressionThreshold.Should().Be(0); settings.CompressionTarget.Should().Be(0); } [Fact] public void Settings_ShouldSupportZeroLengths() { // Arrange var settings = new AISettings(); // Act settings.MinMessageLengthForSummarization = 0; settings.MaxSummarizedMessageLength = 0; // Assert settings.MinMessageLengthForSummarization.Should().Be(0); settings.MaxSummarizedMessageLength.Should().Be(0); } [Fact] public void Settings_ShouldSupportZeroTimeouts() { // Arrange var settings = new AISettings(); // Act settings.RequestTimeoutSeconds = 0; settings.CompressionTimeoutSeconds = 0; settings.StatusCheckTimeoutSeconds = 0; // Assert settings.RequestTimeoutSeconds.Should().Be(0); settings.CompressionTimeoutSeconds.Should().Be(0); settings.StatusCheckTimeoutSeconds.Should().Be(0); } }