using ChatBot.Models.Configuration; using ChatBot.Models.Configuration.Validators; using FluentAssertions; using Microsoft.Extensions.Options; namespace ChatBot.Tests.Configuration.Validators; public class OllamaSettingsValidatorTests { private readonly OllamaSettingsValidator _validator; public OllamaSettingsValidatorTests() { _validator = new OllamaSettingsValidator(); } [Fact] public void Validate_WithValidSettings_ShouldReturnSuccess() { // Arrange var settings = CreateValidOllamaSettings(); // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeTrue(); result.Failed.Should().BeFalse(); result.FailureMessage.Should().BeNullOrEmpty(); } [Fact] public void Validate_WithEmptyUrl_ShouldReturnFailure() { // Arrange var settings = CreateValidOllamaSettings(); settings.Url = string.Empty; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().Contain("Ollama URL is required"); } [Fact] public void Validate_WithNullUrl_ShouldReturnFailure() { // Arrange var settings = CreateValidOllamaSettings(); settings.Url = null!; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().Contain("Ollama URL is required"); } [Fact] public void Validate_WithWhitespaceUrl_ShouldReturnFailure() { // Arrange var settings = CreateValidOllamaSettings(); settings.Url = " "; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().Contain("Ollama URL is required"); } [Theory] [InlineData("invalid-url")] [InlineData("not-a-url")] [InlineData("://invalid")] [InlineData("http://")] [InlineData("https://")] public void Validate_WithInvalidUrlFormat_ShouldReturnFailure(string invalidUrl) { // Arrange var settings = CreateValidOllamaSettings(); settings.Url = invalidUrl; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().Contain($"Invalid Ollama URL format: {invalidUrl}"); } [Theory] [InlineData("http://localhost:11434")] [InlineData("https://localhost:11434")] [InlineData("http://127.0.0.1:11434")] [InlineData("https://ollama.example.com")] [InlineData("http://192.168.1.100:11434")] [InlineData("https://api.ollama.com")] public void Validate_WithValidUrlFormat_ShouldReturnSuccess(string validUrl) { // Arrange var settings = CreateValidOllamaSettings(); settings.Url = validUrl; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeTrue(); result.Failed.Should().BeFalse(); result.FailureMessage.Should().BeNullOrEmpty(); } [Fact] public void Validate_WithEmptyDefaultModel_ShouldReturnFailure() { // Arrange var settings = CreateValidOllamaSettings(); settings.DefaultModel = string.Empty; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().Contain("DefaultModel is required"); } [Fact] public void Validate_WithNullDefaultModel_ShouldReturnFailure() { // Arrange var settings = CreateValidOllamaSettings(); settings.DefaultModel = null!; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().Contain("DefaultModel is required"); } [Fact] public void Validate_WithWhitespaceDefaultModel_ShouldReturnFailure() { // Arrange var settings = CreateValidOllamaSettings(); settings.DefaultModel = " "; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().Contain("DefaultModel is required"); } [Theory] [InlineData("llama3")] [InlineData("llama3.1")] [InlineData("llama3.2")] [InlineData("codellama")] [InlineData("mistral")] [InlineData("phi3")] [InlineData("gemma")] [InlineData("qwen")] public void Validate_WithValidDefaultModel_ShouldReturnSuccess(string validModel) { // Arrange var settings = CreateValidOllamaSettings(); settings.DefaultModel = validModel; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeTrue(); result.Failed.Should().BeFalse(); result.FailureMessage.Should().BeNullOrEmpty(); } [Fact] public void Validate_WithMultipleValidationErrors_ShouldReturnAllErrors() { // Arrange var settings = new OllamaSettings { Url = "invalid-url", // Invalid DefaultModel = string.Empty, // Invalid }; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().Contain("Invalid Ollama URL format: invalid-url"); result.FailureMessage.Should().Contain("DefaultModel is required"); } [Fact] public void Validate_WithNullSettings_ShouldThrowException() { // Arrange & Act & Assert var act = () => _validator.Validate(null, null!); act.Should().Throw(); } [Fact] public void ValidateOptionsResult_Success_ShouldHaveCorrectProperties() { // Arrange var settings = CreateValidOllamaSettings(); // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeTrue(); result.Failed.Should().BeFalse(); result.FailureMessage.Should().BeNullOrEmpty(); } [Fact] public void ValidateOptionsResult_Failure_ShouldHaveCorrectProperties() { // Arrange var settings = new OllamaSettings { Url = "invalid-url", DefaultModel = string.Empty }; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().NotBeNullOrEmpty(); result.FailureMessage.Should().Contain("Invalid Ollama URL format: invalid-url"); result.FailureMessage.Should().Contain("DefaultModel is required"); } [Fact] public void Validator_ShouldImplementIValidateOptions() { // Arrange & Act var validator = new OllamaSettingsValidator(); // Assert validator.Should().BeAssignableTo>(); } [Theory] [InlineData("http://localhost")] [InlineData("https://localhost")] [InlineData("http://localhost:8080")] [InlineData("https://localhost:8080")] [InlineData("http://example.com")] [InlineData("https://example.com")] [InlineData("http://192.168.1.1")] [InlineData("https://192.168.1.1")] [InlineData("http://10.0.0.1:11434")] [InlineData("https://10.0.0.1:11434")] public void Validate_WithVariousValidUrls_ShouldReturnSuccess(string validUrl) { // Arrange var settings = CreateValidOllamaSettings(); settings.Url = validUrl; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeTrue(); result.Failed.Should().BeFalse(); result.FailureMessage.Should().BeNullOrEmpty(); } [Theory] [InlineData("")] [InlineData(" ")] [InlineData("\t")] [InlineData("\n")] [InlineData("\r\n")] public void Validate_WithVariousEmptyStrings_ShouldReturnFailure(string emptyString) { // Arrange var settings = CreateValidOllamaSettings(); settings.Url = emptyString; settings.DefaultModel = emptyString; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failed.Should().BeTrue(); result.FailureMessage.Should().Contain("Ollama URL is required"); result.FailureMessage.Should().Contain("DefaultModel is required"); } [Fact] public void Validate_WithVeryLongValidUrl_ShouldReturnSuccess() { // Arrange var settings = CreateValidOllamaSettings(); settings.Url = "https://very-long-subdomain-name.example.com:11434/api/v1/ollama"; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeTrue(); result.Failed.Should().BeFalse(); result.FailureMessage.Should().BeNullOrEmpty(); } [Fact] public void Validate_WithVeryLongValidModel_ShouldReturnSuccess() { // Arrange var settings = CreateValidOllamaSettings(); settings.DefaultModel = "very-long-model-name-with-many-parts-and-version-numbers"; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeTrue(); result.Failed.Should().BeFalse(); result.FailureMessage.Should().BeNullOrEmpty(); } private static OllamaSettings CreateValidOllamaSettings() { return new OllamaSettings { Url = "http://localhost:11434", DefaultModel = "llama3" }; } }