|
| 1 | +// |
| 2 | +// SSLModeStringTests.swift |
| 3 | +// TableProTests |
| 4 | +// |
| 5 | +// Tests that plugin SSL config structs correctly parse SSLMode raw values. |
| 6 | +// Plugin types are bundle targets and cannot be imported directly, so we |
| 7 | +// duplicate the config parsing logic here as private test helpers. |
| 8 | +// |
| 9 | + |
| 10 | +import Foundation |
| 11 | +import Testing |
| 12 | +@testable import TablePro |
| 13 | + |
| 14 | +// MARK: - Test Helpers (mirror plugin SSL config structs) |
| 15 | + |
| 16 | +/// Mirror of MySQLSSLConfig.Mode from MariaDBPluginConnection.swift |
| 17 | +private enum TestMySQLSSLMode: String { |
| 18 | + case disabled = "Disabled" |
| 19 | + case preferred = "Preferred" |
| 20 | + case required = "Required" |
| 21 | + case verifyCa = "Verify CA" |
| 22 | + case verifyIdentity = "Verify Identity" |
| 23 | +} |
| 24 | + |
| 25 | +/// Mirror of RedisSSLConfig init from RedisPluginConnection.swift |
| 26 | +private struct TestRedisSSLConfig { |
| 27 | + var isEnabled: Bool |
| 28 | + |
| 29 | + init(additionalFields: [String: String]) { |
| 30 | + let sslMode = additionalFields["sslMode"] ?? "Disabled" |
| 31 | + self.isEnabled = sslMode != "Disabled" |
| 32 | + } |
| 33 | +} |
| 34 | + |
| 35 | +/// Mirror of PQSSLConfig from LibPQPluginConnection.swift |
| 36 | +private struct TestPQSSLConfig { |
| 37 | + var mode: String = "Disabled" |
| 38 | + |
| 39 | + init() {} |
| 40 | + |
| 41 | + init(additionalFields: [String: String]) { |
| 42 | + self.mode = additionalFields["sslMode"] ?? "Disabled" |
| 43 | + } |
| 44 | + |
| 45 | + var libpqSslMode: String { |
| 46 | + switch mode { |
| 47 | + case "Disabled": return "disable" |
| 48 | + case "Preferred": return "prefer" |
| 49 | + case "Required": return "require" |
| 50 | + case "Verify CA": return "verify-ca" |
| 51 | + case "Verify Identity": return "verify-full" |
| 52 | + default: return "disable" |
| 53 | + } |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +// MARK: - SSLMode Raw Values Match Plugin Expectations |
| 58 | + |
| 59 | +@Suite("SSL Mode String Consistency") |
| 60 | +struct SSLModeStringTests { |
| 61 | + @Test("SSLMode.disabled.rawValue matches plugin disabled check") |
| 62 | + func disabledRawValue() { |
| 63 | + #expect(SSLMode.disabled.rawValue == "Disabled") |
| 64 | + } |
| 65 | + |
| 66 | + @Test("SSLMode.required.rawValue matches plugin required check") |
| 67 | + func requiredRawValue() { |
| 68 | + #expect(SSLMode.required.rawValue == "Required") |
| 69 | + } |
| 70 | + |
| 71 | + @Test("SSLMode.verifyCa.rawValue matches plugin verify CA check") |
| 72 | + func verifyCaRawValue() { |
| 73 | + #expect(SSLMode.verifyCa.rawValue == "Verify CA") |
| 74 | + } |
| 75 | + |
| 76 | + @Test("SSLMode.verifyIdentity.rawValue matches plugin verify identity check") |
| 77 | + func verifyIdentityRawValue() { |
| 78 | + #expect(SSLMode.verifyIdentity.rawValue == "Verify Identity") |
| 79 | + } |
| 80 | + |
| 81 | + @Test("All SSLMode cases round-trip through MySQL Mode enum") |
| 82 | + func mysqlModeRoundTrip() { |
| 83 | + for sslMode in SSLMode.allCases { |
| 84 | + let parsed = TestMySQLSSLMode(rawValue: sslMode.rawValue) |
| 85 | + #expect(parsed != nil, "MySQLSSLMode failed to parse '\(sslMode.rawValue)'") |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + @Test("MySQL Mode parses each SSLMode raw value to the correct case") |
| 90 | + func mysqlModeParsesCorrectCase() { |
| 91 | + #expect(TestMySQLSSLMode(rawValue: "Disabled") == .disabled) |
| 92 | + #expect(TestMySQLSSLMode(rawValue: "Preferred") == .preferred) |
| 93 | + #expect(TestMySQLSSLMode(rawValue: "Required") == .required) |
| 94 | + #expect(TestMySQLSSLMode(rawValue: "Verify CA") == .verifyCa) |
| 95 | + #expect(TestMySQLSSLMode(rawValue: "Verify Identity") == .verifyIdentity) |
| 96 | + } |
| 97 | + |
| 98 | + @Test("Redis SSL disabled when sslMode is Disabled") |
| 99 | + func redisSSLDisabled() { |
| 100 | + let config = TestRedisSSLConfig(additionalFields: ["sslMode": "Disabled"]) |
| 101 | + #expect(!config.isEnabled) |
| 102 | + } |
| 103 | + |
| 104 | + @Test("Redis SSL enabled when sslMode is Required") |
| 105 | + func redisSSLEnabled() { |
| 106 | + let config = TestRedisSSLConfig(additionalFields: ["sslMode": "Required"]) |
| 107 | + #expect(config.isEnabled) |
| 108 | + } |
| 109 | + |
| 110 | + @Test("Redis SSL defaults to disabled when sslMode key is absent") |
| 111 | + func redisSSLDefaultDisabled() { |
| 112 | + let config = TestRedisSSLConfig(additionalFields: [:]) |
| 113 | + #expect(!config.isEnabled) |
| 114 | + } |
| 115 | + |
| 116 | + @Test("PostgreSQL maps all SSLMode raw values to correct libpq modes") |
| 117 | + func pqSSLModeMapping() { |
| 118 | + #expect(TestPQSSLConfig(additionalFields: ["sslMode": "Disabled"]).libpqSslMode == "disable") |
| 119 | + #expect(TestPQSSLConfig(additionalFields: ["sslMode": "Preferred"]).libpqSslMode == "prefer") |
| 120 | + #expect(TestPQSSLConfig(additionalFields: ["sslMode": "Required"]).libpqSslMode == "require") |
| 121 | + #expect(TestPQSSLConfig(additionalFields: ["sslMode": "Verify CA"]).libpqSslMode == "verify-ca") |
| 122 | + #expect(TestPQSSLConfig(additionalFields: ["sslMode": "Verify Identity"]).libpqSslMode == "verify-full") |
| 123 | + } |
| 124 | + |
| 125 | + @Test("PostgreSQL default init uses Disabled") |
| 126 | + func pqDefaultInit() { |
| 127 | + let config = TestPQSSLConfig() |
| 128 | + #expect(config.mode == "Disabled") |
| 129 | + #expect(config.libpqSslMode == "disable") |
| 130 | + } |
| 131 | + |
| 132 | + @Test("MongoDB SSL mode string comparisons use correct case") |
| 133 | + func mongoDBSSLModeStrings() { |
| 134 | + // These mirror the comparisons in MongoDBConnection.buildUri() |
| 135 | + let disabled = SSLMode.disabled.rawValue |
| 136 | + let verifyCa = SSLMode.verifyCa.rawValue |
| 137 | + let verifyIdentity = SSLMode.verifyIdentity.rawValue |
| 138 | + |
| 139 | + #expect(disabled == "Disabled") |
| 140 | + let sslEnabled = disabled != "Disabled" && !disabled.isEmpty |
| 141 | + #expect(!sslEnabled) |
| 142 | + |
| 143 | + let required = SSLMode.required.rawValue |
| 144 | + let sslEnabledRequired = required != "Disabled" && !required.isEmpty |
| 145 | + #expect(sslEnabledRequired) |
| 146 | + |
| 147 | + let verifiesCert = verifyCa == "Verify CA" || verifyIdentity == "Verify Identity" |
| 148 | + #expect(verifiesCert) |
| 149 | + } |
| 150 | + |
| 151 | + @Test("ClickHouse SSL mode string comparisons use correct case") |
| 152 | + func clickHouseSSLModeStrings() { |
| 153 | + // These mirror the comparisons in ClickHousePlugin.connect() / buildRequest() |
| 154 | + let disabled = SSLMode.disabled.rawValue |
| 155 | + let useTLS = disabled != "Disabled" |
| 156 | + #expect(!useTLS) |
| 157 | + |
| 158 | + let required = SSLMode.required.rawValue |
| 159 | + let skipVerification = required == "Required" |
| 160 | + #expect(skipVerification) |
| 161 | + } |
| 162 | +} |
0 commit comments