const std = @import("std"); const testing = std.testing; const src = @import("src"); const Config = src.Config; test "config file validation" { // Test various config file contents const test_configs = [_]struct { content: []const u8, should_be_valid: bool, description: []const u8, }{ .{ .content = \\server: \\ host: "localhost" \\ port: 8080 \\auth: \\ enabled: true \\storage: \\ type: "local" \\ path: "/tmp/ml_experiments" , .should_be_valid = true, .description = "Valid complete config", }, .{ .content = \\server: \\ host: "localhost" \\ port: 8080 , .should_be_valid = true, .description = "Minimal valid config", }, .{ .content = "", .should_be_valid = false, .description = "Empty config", }, .{ .content = \\invalid_yaml: [ \\ missing_closing_bracket , .should_be_valid = false, .description = "Invalid YAML syntax", }, }; for (test_configs) |case| { // For now, just verify the content is readable try testing.expect(case.content.len > 0 or !case.should_be_valid); if (case.should_be_valid) { try testing.expect(std.mem.indexOf(u8, case.content, "server") != null); } } } test "config default values" { const allocator = testing.allocator; // Create minimal config const minimal_config = \\server: \\ host: "localhost" \\ port: 8080 ; // Verify config content is readable const content = try allocator.alloc(u8, minimal_config.len); defer allocator.free(content); @memcpy(content, minimal_config); try testing.expect(std.mem.indexOf(u8, content, "localhost") != null); try testing.expect(std.mem.indexOf(u8, content, "8080") != null); } test "config server settings" { const allocator = testing.allocator; _ = allocator; // Mark as used for future test expansions // Test server configuration validation const server_configs = [_]struct { host: []const u8, port: u16, should_be_valid: bool, }{ .{ .host = "localhost", .port = 8080, .should_be_valid = true }, .{ .host = "127.0.0.1", .port = 8080, .should_be_valid = true }, .{ .host = "example.com", .port = 443, .should_be_valid = true }, .{ .host = "", .port = 8080, .should_be_valid = false }, .{ .host = "localhost", .port = 0, .should_be_valid = false }, .{ .host = "localhost", .port = 65535, .should_be_valid = true }, }; for (server_configs) |config| { if (config.should_be_valid) { try testing.expect(config.host.len > 0); try testing.expect(config.port >= 1 and config.port <= 65535); } else { try testing.expect(config.host.len == 0 or config.port == 0 or config.port > 65535); } } } test "config authentication settings" { const allocator = testing.allocator; _ = allocator; // Mark as used for future test expansions // Test authentication configuration const auth_configs = [_]struct { enabled: bool, has_api_keys: bool, should_be_valid: bool, }{ .{ .enabled = true, .has_api_keys = true, .should_be_valid = true }, .{ .enabled = false, .has_api_keys = false, .should_be_valid = true }, .{ .enabled = true, .has_api_keys = false, .should_be_valid = false }, .{ .enabled = false, .has_api_keys = true, .should_be_valid = true }, // API keys can exist but auth disabled }; for (auth_configs) |config| { if (config.enabled and !config.has_api_keys) { try testing.expect(!config.should_be_valid); } else { try testing.expect(true); // Valid configuration } } } test "config storage settings" { const allocator = testing.allocator; _ = allocator; // Mark as used for future test expansions // Test storage configuration const storage_configs = [_]struct { storage_type: []const u8, path: []const u8, should_be_valid: bool, }{ .{ .storage_type = "local", .path = "/tmp/ml_experiments", .should_be_valid = true }, .{ .storage_type = "s3", .path = "bucket-name", .should_be_valid = true }, .{ .storage_type = "", .path = "/tmp/ml_experiments", .should_be_valid = false }, .{ .storage_type = "local", .path = "", .should_be_valid = false }, .{ .storage_type = "invalid", .path = "/tmp/ml_experiments", .should_be_valid = false }, }; for (storage_configs) |config| { if (config.should_be_valid) { try testing.expect(config.storage_type.len > 0); try testing.expect(config.path.len > 0); } else { try testing.expect(config.storage_type.len == 0 or config.path.len == 0 or std.mem.eql(u8, config.storage_type, "invalid")); } } } test "config file paths" { const allocator = testing.allocator; // Test config file path resolution const config_paths = [_][]const u8{ "config.yaml", "config.yml", ".ml/config.yaml", "/etc/ml/config.yaml", }; for (config_paths) |path| { try testing.expect(path.len > 0); // Test path joining const joined = try std.fs.path.join(allocator, &.{ "/base", path }); defer allocator.free(joined); try testing.expect(joined.len > path.len); try testing.expect(std.mem.startsWith(u8, joined, "/base/")); } } test "config environment variables" { const allocator = testing.allocator; _ = allocator; // Mark as used for future test expansions // Test environment variable substitution const env_vars = [_]struct { key: []const u8, value: []const u8, should_be_substituted: bool, }{ .{ .key = "ML_SERVER_HOST", .value = "localhost", .should_be_substituted = true }, .{ .key = "ML_SERVER_PORT", .value = "8080", .should_be_substituted = true }, .{ .key = "NON_EXISTENT_VAR", .value = "", .should_be_substituted = false }, }; for (env_vars) |env_var| { if (env_var.should_be_substituted) { try testing.expect(env_var.value.len > 0); } } } test "config validation errors" { const allocator = testing.allocator; // Test various validation error scenarios const error_scenarios = [_]struct { config_content: []const u8, expected_error_type: []const u8, }{ .{ .config_content = "invalid: yaml: content: [", .expected_error_type = "yaml_syntax_error", }, .{ .config_content = "server:\n port: invalid_port", .expected_error_type = "type_error", }, .{ .config_content = "", .expected_error_type = "empty_config", }, }; for (error_scenarios) |scenario| { // For now, just verify the content is stored correctly const content = try allocator.alloc(u8, scenario.config_content.len); defer allocator.free(content); @memcpy(content, scenario.config_content); try testing.expect(std.mem.eql(u8, content, scenario.config_content)); } } test "config hot reload" { const allocator = testing.allocator; // Initial config const initial_config = \\server: \\ host: "localhost" \\ port: 8080 ; // Updated config const updated_config = \\server: \\ host: "localhost" \\ port: 9090 ; // Test config content changes const initial_content = try allocator.alloc(u8, initial_config.len); defer allocator.free(initial_content); const updated_content = try allocator.alloc(u8, updated_config.len); defer allocator.free(updated_content); @memcpy(initial_content, initial_config); @memcpy(updated_content, updated_config); try testing.expect(std.mem.indexOf(u8, initial_content, "8080") != null); try testing.expect(std.mem.indexOf(u8, updated_content, "9090") != null); try testing.expect(std.mem.indexOf(u8, updated_content, "8080") == null); }