diff --git a/source/TempDb/PeanutButter.TempDb.MySql.Base/TempDbMySqlBase.cs b/source/TempDb/PeanutButter.TempDb.MySql.Base/TempDbMySqlBase.cs index 5ccfa7e34c..7029406eec 100644 --- a/source/TempDb/PeanutButter.TempDb.MySql.Base/TempDbMySqlBase.cs +++ b/source/TempDb/PeanutButter.TempDb.MySql.Base/TempDbMySqlBase.cs @@ -89,14 +89,6 @@ public bool VerboseLoggingEnabled private bool? _verboseLoggingEnabled; - private string[] VerboseLoggingCommandLineArgs => - VerboseLoggingEnabled - ? new[] - { - "--log-error-verbosity=3" - } - : new string[0]; - private bool DetermineIfVerboseLoggingShouldBeEnabled() { var envValue = Environment.GetEnvironmentVariable(EnvironmentVariables.VERBOSE); @@ -150,6 +142,7 @@ private void DebugLog(string toLog) public TempDbMySqlServerSettings Settings { get; private set; } public int? ServerProcessId => _serverProcess?.ProcessId; + public string ServerProcessCommand => _serverProcess?.Commandline; private IProcessIO _serverProcess; public int Port { get; protected set; } @@ -461,7 +454,64 @@ private string QueryForMySqld() } private string MySqld => - _mysqld ??= Settings?.Options?.PathToMySqlD ?? FindInstalledMySqlD(); + _mysqld ??= StoreValidCommandlineArgumentsFor( + Settings?.Options?.PathToMySqlD ?? FindInstalledMySqlD() + ); + + private string StoreValidCommandlineArgumentsFor(string pathToMySqlD) + { + if (string.IsNullOrWhiteSpace(pathToMySqlD) || !File.Exists(pathToMySqlD)) + { + return pathToMySqlD; + } + + if (MySqlArguments.ContainsKey(pathToMySqlD)) + { + return pathToMySqlD; + } + + using var io = ProcessIO.Start(pathToMySqlD, "--help", "--verbose"); + var collected = new List(); + foreach (var line in io.StandardOutput) + { + var trimmed = line.Trim(); + if (trimmed.StartsWith("-")) + { + var sw = trimmed.Split(' ', '=', '['); + foreach (var sub in sw) + { + if (sub.StartsWith("-")) + { + collected.Add(sub); + } + } + } + } + + MySqlArguments[pathToMySqlD] = new HashSet( + collected, + StringComparer.OrdinalIgnoreCase + ); + return pathToMySqlD; + } + + private bool IsValidArgument(string arg) + { + if (!MySqlArguments.TryGetValue(MySqld, out var validArgs)) + { + throw new InvalidOperationException( + $"mysqld argument validation attempted before gathering valid args for '{MySqld}'" + ); + } + + return validArgs.Contains(arg); + } + + private static readonly ConcurrentDictionary> MySqlArguments = new( + Platform.IsUnixy + ? StringComparer.Ordinal + : StringComparer.OrdinalIgnoreCase + ); /// protected override void CreateDatabase() @@ -688,8 +738,13 @@ private void SetRootPasswordViaCli(int attempt = 0) $"--port={Port}", $"\"--init-file={tmpFile.Path}\"" }; - if (IsMySql8()) + if (IsValidArgument("--no-monitor")) { + // - the windows service adds it's own monitor + // process - which we disable via --no-monitor + // - the linux service has an optional, completely + // separate, monitor service. Why doesn't windows + // have this? Who knows. Good job Oracle. args = args.And("--no-monitor"); } @@ -1312,10 +1367,7 @@ string mysqld $"--port={Port}" }; - if (VerboseLoggingEnabled) - { - args = args.And(VerboseLoggingCommandLineArgs); - } + args = EnableVerboseLoggingIfRequested(args); if (IsMySql8()) { @@ -1784,6 +1836,20 @@ protected bool CanConnect() return false; } + private string[] EnableVerboseLoggingIfRequested( + string[] existingArgs + ) + { + if (!VerboseLoggingEnabled) + { + return existingArgs; + } + + return IsValidArgument("--log-error-verbosity") + ? existingArgs.And("--log-error-verbosity=3") + : existingArgs; + } + private void InitializeWith(string mysqld, string tempDefaultsFile) { Directory.CreateDirectory(DataDir); @@ -1802,10 +1868,8 @@ private void InitializeWith(string mysqld, string tempDefaultsFile) $"\"--basedir={BaseDirOf(mysqld)}\"", $"\"--datadir={DataDir}\"" }; - if (VerboseLoggingEnabled) - { - args = args.And(VerboseLoggingCommandLineArgs); - } + + args = EnableVerboseLoggingIfRequested(args); using var process = RunCommand( false, diff --git a/source/TempDb/PeanutButter.TempDb.MySql.Data.Tests/TestTempDbMySqlData.cs b/source/TempDb/PeanutButter.TempDb.MySql.Data.Tests/TestTempDbMySqlData.cs index 6e463cbae6..c885e903ed 100644 --- a/source/TempDb/PeanutButter.TempDb.MySql.Data.Tests/TestTempDbMySqlData.cs +++ b/source/TempDb/PeanutButter.TempDb.MySql.Data.Tests/TestTempDbMySqlData.cs @@ -59,6 +59,41 @@ public void ShouldBeDisposable() // Assert } + [Test] + public void ShouldBeAbleToEnableVerboseLogging() + { + // Arrange + using var _ = new AutoTempFile( + EnvironmentVariables.VERBOSE, + "1" + ); + + // Act + using var db = Create(); + // Assert + Expect(db.ServerProcessCommand) + .To.Contain("--log-error-verbosity"); + } + + [Test] + public void ShouldOnlyDisableMonitorWhenNecessary() + { + // Arrange + // Act + using var db = Create(); + // Assert + if (Platform.IsWindows) + { + Expect(db.ServerCommandline) + .To.Contain("--no-monitor"); + } + else + { + Expect(db.ServerCommandline) + .Not.To.Contain("--no-monitor"); + } + } + [TestFixture] [Timeout(LONG_TIMEOUT)] public class SnapshottingAndReusing : AutoDestroyTempDbOnTimeout