Files
MBN_STOCK_WEBVIEW/tools/MBN_STOCK_WEBVIEW.DbWriteSmoke/DevelopmentDatabaseWriteSmokeApp.cs

109 lines
4.1 KiB
C#

#nullable enable
namespace MBN_STOCK_WEBVIEW.DbWriteSmoke;
internal static class DevelopmentDatabaseWriteSmokeApp
{
internal const int SuccessExitCode = 0;
internal const int FailureExitCode = 1;
internal const int NotAcknowledgedExitCode = 2;
internal const int OutcomeUnknownExitCode = 3;
internal static async Task<int> RunAsync(
IReadOnlyList<string> arguments,
Func<string?, IReadOnlyList<DevelopmentDatabaseSmokeScenario>> createPlan,
TextWriter output,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(arguments);
ArgumentNullException.ThrowIfNull(createPlan);
ArgumentNullException.ThrowIfNull(output);
if (!SmokeCommandLine.TryParse(arguments, out var options))
{
await output.WriteLineAsync(SmokeCommandLine.Usage).ConfigureAwait(false);
return NotAcknowledgedExitCode;
}
if (options.ShowHelp)
{
await output.WriteLineAsync(SmokeCommandLine.Usage).ConfigureAwait(false);
await output.WriteLineAsync(
"No write occurs unless the exact development-database acknowledgement is present.")
.ConfigureAwait(false);
return SuccessExitCode;
}
if (!options.IsWriteAcknowledged)
{
await output.WriteLineAsync(
"BLOCKED: development database writes were not acknowledged; no configuration was loaded and no database call was made.")
.ConfigureAwait(false);
await output.WriteLineAsync(SmokeCommandLine.Usage).ConfigureAwait(false);
return NotAcknowledgedExitCode;
}
IReadOnlyList<DevelopmentDatabaseSmokeScenario> plan;
try
{
plan = createPlan(options.ConfigurationPath);
}
catch
{
await output.WriteLineAsync(
"FAIL: configuration or smoke-plan creation failed (details redacted).")
.ConfigureAwait(false);
return FailureExitCode;
}
await output.WriteLineAsync(
"START: isolated development DB write/readback/cleanup smoke; credentials, SQL, identifiers, and values are redacted.")
.ConfigureAwait(false);
foreach (var scenario in plan)
{
cancellationToken.ThrowIfCancellationRequested();
await output.WriteLineAsync("RUN: " + scenario.Name).ConfigureAwait(false);
DevelopmentDatabaseSmokeResult result;
try
{
result = await scenario.RunAsync(cancellationToken).ConfigureAwait(false);
}
catch
{
await output.WriteLineAsync(
"FAIL: unclassified smoke failure; no retry was attempted (details redacted).")
.ConfigureAwait(false);
return FailureExitCode;
}
if (result.Passed)
{
await output.WriteLineAsync(
"PASS: create/save, fresh readback, cleanup, and absence verification completed.")
.ConfigureAwait(false);
continue;
}
await output.WriteLineAsync(
$"FAIL: stage={result.FailureStage}; failureClass={result.FailureClass}; cleanupAttempted={result.CleanupAttempted}; cleanupVerified={result.CleanupVerified}; details redacted.")
.ConfigureAwait(false);
if (result.OutcomeUnknown)
{
await output.WriteLineAsync(
"QUARANTINED: mutation outcome is unknown; no retry, cleanup mutation, or later scenario was issued. A uniquely prefixed record may require manual inspection.")
.ConfigureAwait(false);
return OutcomeUnknownExitCode;
}
return FailureExitCode;
}
await output.WriteLineAsync(
"PASS: every development DB write scenario was verified absent after cleanup.")
.ConfigureAwait(false);
return SuccessExitCode;
}
}