Make installer runtime acceptance transactional
This commit is contained in:
@@ -37,14 +37,22 @@ namespace BizTalkCheckmkPulse.Tests
|
||||
Run("EndpointOutputListsOnlyUnavailableTargets", EndpointOutputListsOnlyUnavailableTargets);
|
||||
Run("EndpointOutputExplainsOnlyRealResolutionGaps", EndpointOutputExplainsOnlyRealResolutionGaps);
|
||||
Run("EndpointProbeBudgetFitsMinuteInterval", EndpointProbeBudgetFitsMinuteInterval);
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
Run("ForcedEndpointRefreshRewritesFreshCatalog", ForcedEndpointRefreshRewritesFreshCatalog);
|
||||
Run("EnvironmentLabelDoesNotRenameServicesByDefault", EnvironmentLabelDoesNotRenameServicesByDefault);
|
||||
Run("DefaultServiceContractIsExact", DefaultServiceContractIsExact);
|
||||
Run("InstallerRejectsUnconfirmedServiceRename", InstallerRejectsUnconfirmedServiceRename);
|
||||
Run("InstallerAllowsConfirmedServiceRename", InstallerAllowsConfirmedServiceRename);
|
||||
>>>>>>> e694e4c (Guard Checkmk service renames during updates)
|
||||
Run("InstallerUpdatePreservesExistingSettings", InstallerUpdatePreservesExistingSettings);
|
||||
Run("RuntimeValidationAcceptsFreshConsistentArtifacts", RuntimeValidationAcceptsFreshConsistentArtifacts);
|
||||
Run("RuntimeValidationRejectsPreInstallSnapshot", RuntimeValidationRejectsPreInstallSnapshot);
|
||||
Run("RuntimeValidationRejectsWrongIdentity", RuntimeValidationRejectsWrongIdentity);
|
||||
Run("RuntimeValidationRejectsStaleCatalog", RuntimeValidationRejectsStaleCatalog);
|
||||
Run("RuntimeValidationRejectsChangedServiceContract", RuntimeValidationRejectsChangedServiceContract);
|
||||
Run("RuntimeValidationRejectsUnknownStableService", RuntimeValidationRejectsUnknownStableService);
|
||||
Run("RuntimeValidationAllowsDisabledEndpointProbeWithoutCatalog", RuntimeValidationAllowsDisabledEndpointProbeWithoutCatalog);
|
||||
Run("ForceEndpointRefreshRequiresProviderMode", ForceEndpointRefreshRequiresProviderMode);
|
||||
Run("RuntimeValidationArgumentsAreParsedStrictly", RuntimeValidationArgumentsAreParsedStrictly);
|
||||
Run("TaskCompletionRequiresFreshSuccessfulRun", TaskCompletionRequiresFreshSuccessfulRun);
|
||||
Run("SnapshotRoundTripPreservesLines", SnapshotRoundTripPreservesLines);
|
||||
Run("SnapshotRejectsTampering", SnapshotRejectsTampering);
|
||||
Run("SnapshotRejectsStaleData", SnapshotRejectsStaleData);
|
||||
@@ -337,6 +345,7 @@ namespace BizTalkCheckmkPulse.Tests
|
||||
Assert(result.IsSuccess, "snapshot should be readable: " + result.Error);
|
||||
AssertEqual(lines.Length, result.Lines.Count, "snapshot line count");
|
||||
Assert(lines.SequenceEqual(result.Lines), "snapshot payload changed");
|
||||
AssertEqual("DOMAIN\\collector$", result.Identity, "snapshot identity");
|
||||
|
||||
var replacement = lines.Select(x => x.Replace("Self test OK", "Replacement OK")).ToArray();
|
||||
store.Write(replacement, generated.AddSeconds(30), "DOMAIN\\collector$");
|
||||
@@ -690,8 +699,51 @@ namespace BizTalkCheckmkPulse.Tests
|
||||
Assert(configuredMaximum <= 30000, "configured endpoint worst-case must leave headroom in the minute interval");
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
private static void ForcedEndpointRefreshRewritesFreshCatalog()
|
||||
{
|
||||
var directory = Path.Combine(Path.GetTempPath(), "BizTalkCheckmkPulse.ForcedCatalogTests." + Guid.NewGuid().ToString("N"));
|
||||
Directory.CreateDirectory(directory);
|
||||
try
|
||||
{
|
||||
var options = new MonitoringOptions
|
||||
{
|
||||
EnvironmentName = "ACC",
|
||||
EndpointCatalogPath = Path.Combine(directory, "endpoints.xml"),
|
||||
LogDirectory = Path.Combine(directory, "logs"),
|
||||
ForceEndpointCatalogRefresh = true
|
||||
};
|
||||
var oldTimestamp = DateTime.UtcNow.AddHours(-1);
|
||||
new EndpointCatalogStore(
|
||||
options.EndpointCatalogPath,
|
||||
options.EndpointCatalogMaxBytes,
|
||||
options.EndpointCatalogMaxEntries)
|
||||
.Write(new EndpointCatalog
|
||||
{
|
||||
EnvironmentName = options.EnvironmentName,
|
||||
SynchronizedUtc = oldTimestamp
|
||||
});
|
||||
|
||||
var probeResult = new ProbeResult();
|
||||
probeResult.Platform.ReceiveLocationsDataAvailable = true;
|
||||
probeResult.Platform.SendPortsDataAvailable = true;
|
||||
new EndpointConnectivityProbe(options, new FileLogger(options.LogDirectory, 1, "test"))
|
||||
.Query(probeResult);
|
||||
|
||||
var refreshed = new EndpointCatalogStore(
|
||||
options.EndpointCatalogPath,
|
||||
options.EndpointCatalogMaxBytes,
|
||||
options.EndpointCatalogMaxEntries)
|
||||
.Read(options.EnvironmentName);
|
||||
Assert(probeResult.EndpointConnectivity.RefreshRequired, "forced catalog refresh was not requested");
|
||||
Assert(probeResult.EndpointConnectivity.RefreshSucceeded, "forced catalog refresh failed");
|
||||
Assert(refreshed.SynchronizedUtc > oldTimestamp, "forced catalog refresh did not replace timestamp");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Directory.Exists(directory)) Directory.Delete(directory, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnvironmentLabelDoesNotRenameServicesByDefault()
|
||||
{
|
||||
var options = new MonitoringOptions { EnvironmentName = "ACC" };
|
||||
@@ -765,7 +817,6 @@ namespace BizTalkCheckmkPulse.Tests
|
||||
return line.Substring(start, end - start);
|
||||
}
|
||||
|
||||
>>>>>>> e694e4c (Guard Checkmk service renames during updates)
|
||||
private static void InstallerUpdatePreservesExistingSettings()
|
||||
{
|
||||
var directory = Path.Combine(Path.GetTempPath(), "BizTalkCheckmkPulse.InstallerTests." + Guid.NewGuid().ToString("N"));
|
||||
@@ -779,6 +830,7 @@ namespace BizTalkCheckmkPulse.Tests
|
||||
source,
|
||||
"<configuration><appSettings>"
|
||||
+ "<add key=\"EnvironmentName\" value=\"\" />"
|
||||
+ "<add key=\"IncludeEnvironmentInServiceName\" value=\"false\" />"
|
||||
+ "<add key=\"EndpointProbeMaxConcurrency\" value=\"16\" />"
|
||||
+ "<add key=\"EndpointMaxCount\" value=\"100\" />"
|
||||
+ "<add key=\"EndpointCatalogMaxEntries\" value=\"1000\" />"
|
||||
@@ -802,6 +854,7 @@ namespace BizTalkCheckmkPulse.Tests
|
||||
string.Empty);
|
||||
var merged = File.ReadAllText(staged);
|
||||
AssertEqual("ACC", effectiveEnvironment, "preserved installer environment");
|
||||
Assert(merged.Contains("key=\"IncludeEnvironmentInServiceName\" value=\"false\""), "stable service-name default must be added on update");
|
||||
Assert(merged.Contains("key=\"EndpointProbeMaxConcurrency\" value=\"7\""), "existing operational value must be preserved");
|
||||
Assert(merged.Contains("key=\"EndpointMaxCount\" value=\"100\""), "superseded old default must migrate to new bounded default");
|
||||
Assert(merged.Contains("key=\"EndpointCatalogMaxEntries\" value=\"1000\""), "new catalog entry limit must be added");
|
||||
@@ -821,6 +874,214 @@ namespace BizTalkCheckmkPulse.Tests
|
||||
}
|
||||
}
|
||||
|
||||
private static void RuntimeValidationAcceptsFreshConsistentArtifacts()
|
||||
{
|
||||
var boundary = DateTime.UtcNow.AddMinutes(-1);
|
||||
var result = ValidateRuntimeArtifacts(
|
||||
boundary,
|
||||
boundary.AddSeconds(10),
|
||||
boundary.AddSeconds(5),
|
||||
"BEW\\t231bizmon",
|
||||
"BEW\\t231bizmon",
|
||||
true,
|
||||
null);
|
||||
Assert(result.IsSuccess, "fresh consistent runtime artifacts must pass: " + result.Error);
|
||||
AssertEqual(9, result.StableServiceCount, "validated stable service count");
|
||||
}
|
||||
|
||||
private static void RuntimeValidationRejectsPreInstallSnapshot()
|
||||
{
|
||||
var boundary = DateTime.UtcNow.AddMinutes(-1);
|
||||
var result = ValidateRuntimeArtifacts(
|
||||
boundary,
|
||||
boundary.AddSeconds(-1),
|
||||
boundary.AddSeconds(5),
|
||||
"BEW\\t231bizmon",
|
||||
"BEW\\t231bizmon",
|
||||
true,
|
||||
null);
|
||||
Assert(!result.IsSuccess, "snapshot from before installation must fail");
|
||||
Assert(result.Error.Contains("nicht aus dem gestarteten Providerlauf"), "old snapshot reason missing");
|
||||
}
|
||||
|
||||
private static void RuntimeValidationRejectsWrongIdentity()
|
||||
{
|
||||
var boundary = DateTime.UtcNow.AddMinutes(-1);
|
||||
var result = ValidateRuntimeArtifacts(
|
||||
boundary,
|
||||
boundary.AddSeconds(10),
|
||||
boundary.AddSeconds(5),
|
||||
"BEW\\other-account",
|
||||
"BEW\\t231bizmon",
|
||||
true,
|
||||
null);
|
||||
Assert(!result.IsSuccess, "unexpected provider identity must fail");
|
||||
Assert(result.Error.Contains("unerwarteten Identitaet"), "identity mismatch reason missing");
|
||||
}
|
||||
|
||||
private static void RuntimeValidationRejectsStaleCatalog()
|
||||
{
|
||||
var boundary = DateTime.UtcNow.AddMinutes(-1);
|
||||
var result = ValidateRuntimeArtifacts(
|
||||
boundary,
|
||||
boundary.AddSeconds(10),
|
||||
boundary.AddSeconds(-1),
|
||||
"BEW\\t231bizmon",
|
||||
"BEW\\t231bizmon",
|
||||
true,
|
||||
null);
|
||||
Assert(!result.IsSuccess, "catalog from before installation must fail");
|
||||
Assert(result.Error.Contains("nicht aktualisiert"), "old catalog reason missing");
|
||||
}
|
||||
|
||||
private static void RuntimeValidationRejectsChangedServiceContract()
|
||||
{
|
||||
var boundary = DateTime.UtcNow.AddMinutes(-1);
|
||||
var lines = new CheckmkLocalFormatter(new MonitoringOptions()).FormatSelfTest().ToArray();
|
||||
lines[0] = lines[0].Replace("BizTalk Platform", "BizTalk Renamed Platform");
|
||||
var result = ValidateRuntimeArtifacts(
|
||||
boundary,
|
||||
boundary.AddSeconds(10),
|
||||
boundary.AddSeconds(5),
|
||||
"BEW\\t231bizmon",
|
||||
"BEW\\t231bizmon",
|
||||
true,
|
||||
lines);
|
||||
Assert(!result.IsSuccess, "changed runtime service contract must fail");
|
||||
Assert(result.Error.Contains("Fehlend=[BizTalk Platform]"), "missing stable service reason missing");
|
||||
}
|
||||
|
||||
private static void RuntimeValidationAllowsDisabledEndpointProbeWithoutCatalog()
|
||||
{
|
||||
var boundary = DateTime.UtcNow.AddMinutes(-1);
|
||||
var result = ValidateRuntimeArtifacts(
|
||||
boundary,
|
||||
boundary.AddSeconds(10),
|
||||
null,
|
||||
"BEW\\t231bizmon",
|
||||
"BEW\\t231bizmon",
|
||||
false,
|
||||
null);
|
||||
Assert(result.IsSuccess, "disabled endpoint probe must not require catalog: " + result.Error);
|
||||
Assert(!result.CatalogSynchronizedUtc.HasValue, "disabled endpoint probe must report no catalog timestamp");
|
||||
}
|
||||
|
||||
private static void RuntimeValidationRejectsUnknownStableService()
|
||||
{
|
||||
var boundary = DateTime.UtcNow.AddMinutes(-1);
|
||||
var lines = new CheckmkLocalFormatter(new MonitoringOptions()).FormatSelfTest().ToArray();
|
||||
lines[0] = "3" + lines[0].Substring(1);
|
||||
var result = ValidateRuntimeArtifacts(
|
||||
boundary,
|
||||
boundary.AddSeconds(10),
|
||||
boundary.AddSeconds(5),
|
||||
"BEW\\t231bizmon",
|
||||
"BEW\\t231bizmon",
|
||||
true,
|
||||
lines);
|
||||
Assert(!result.IsSuccess, "UNKNOWN stable service must fail runtime acceptance");
|
||||
Assert(result.Error.Contains("UNKNOWN=[BizTalk Platform]"), "UNKNOWN stable service reason missing");
|
||||
}
|
||||
|
||||
private static void ForceEndpointRefreshRequiresProviderMode()
|
||||
{
|
||||
var options = MonitoringOptions.Load(new[] { "--collect", "--force-endpoint-refresh" });
|
||||
Assert(options.Collect, "forced refresh must retain provider mode");
|
||||
Assert(options.ForceEndpointCatalogRefresh, "forced refresh option missing");
|
||||
|
||||
try
|
||||
{
|
||||
MonitoringOptions.Load(new[] { "--force-endpoint-refresh" });
|
||||
throw new InvalidOperationException("forced refresh without provider mode was accepted");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Assert(ex.Message.Contains("valid only in provider mode"), "forced refresh rejection reason missing");
|
||||
}
|
||||
}
|
||||
|
||||
private static void RuntimeValidationArgumentsAreParsedStrictly()
|
||||
{
|
||||
var timestamp = DateTime.UtcNow;
|
||||
var identity = "BEW\\t231bizmon";
|
||||
var options = MonitoringOptions.Load(new[]
|
||||
{
|
||||
"--validate-runtime",
|
||||
"--validation-not-before-utc",
|
||||
timestamp.ToString("o"),
|
||||
"--expected-identity-base64",
|
||||
Convert.ToBase64String(Encoding.UTF8.GetBytes(identity))
|
||||
});
|
||||
Assert(options.RuntimeValidation, "runtime validation mode missing");
|
||||
AssertEqual(timestamp.ToString("o"), options.RuntimeValidationNotBeforeUtc.Value.ToString("o"), "runtime validation timestamp");
|
||||
AssertEqual(identity, options.ExpectedRuntimeIdentity, "runtime validation identity");
|
||||
}
|
||||
|
||||
private static void TaskCompletionRequiresFreshSuccessfulRun()
|
||||
{
|
||||
var boundary = DateTime.UtcNow;
|
||||
Assert(BizTalkCheckmkPulse.Setup.TaskSchedulerService.IsSuccessfulCompletion(
|
||||
3, 0, boundary.AddSeconds(1), boundary), "fresh successful ready task must pass");
|
||||
Assert(!BizTalkCheckmkPulse.Setup.TaskSchedulerService.IsSuccessfulCompletion(
|
||||
4, 0, boundary.AddSeconds(1), boundary), "running task must not pass");
|
||||
Assert(!BizTalkCheckmkPulse.Setup.TaskSchedulerService.IsSuccessfulCompletion(
|
||||
3, 1, boundary.AddSeconds(1), boundary), "failed task result must not pass");
|
||||
Assert(!BizTalkCheckmkPulse.Setup.TaskSchedulerService.IsSuccessfulCompletion(
|
||||
3, 0, boundary.AddSeconds(-3), boundary), "old successful task must not pass");
|
||||
}
|
||||
|
||||
private static RuntimeValidationResult ValidateRuntimeArtifacts(
|
||||
DateTime boundaryUtc,
|
||||
DateTime snapshotUtc,
|
||||
DateTime? catalogUtc,
|
||||
string snapshotIdentity,
|
||||
string expectedIdentity,
|
||||
bool probeEndpoints,
|
||||
string[] snapshotLines)
|
||||
{
|
||||
var directory = Path.Combine(Path.GetTempPath(), "BizTalkCheckmkPulse.RuntimeValidationTests." + Guid.NewGuid().ToString("N"));
|
||||
Directory.CreateDirectory(directory);
|
||||
try
|
||||
{
|
||||
var options = new MonitoringOptions
|
||||
{
|
||||
EnvironmentName = "ACC",
|
||||
SnapshotPath = Path.Combine(directory, "snapshot.txt"),
|
||||
EndpointCatalogPath = Path.Combine(directory, "endpoints.xml"),
|
||||
ProbeEndpointConnectivity = probeEndpoints
|
||||
};
|
||||
var formatter = new CheckmkLocalFormatter(options);
|
||||
new SnapshotStore(options.SnapshotPath, options.SnapshotMaxBytes).Write(
|
||||
snapshotLines ?? formatter.FormatSelfTest().ToArray(),
|
||||
snapshotUtc,
|
||||
snapshotIdentity);
|
||||
|
||||
if (catalogUtc.HasValue)
|
||||
{
|
||||
new EndpointCatalogStore(
|
||||
options.EndpointCatalogPath,
|
||||
options.EndpointCatalogMaxBytes,
|
||||
options.EndpointCatalogMaxEntries)
|
||||
.Write(new EndpointCatalog
|
||||
{
|
||||
EnvironmentName = options.EnvironmentName,
|
||||
SynchronizedUtc = catalogUtc.Value
|
||||
});
|
||||
}
|
||||
|
||||
return RuntimeValidator.Validate(
|
||||
options,
|
||||
formatter,
|
||||
boundaryUtc,
|
||||
expectedIdentity,
|
||||
boundaryUtc.AddMinutes(1));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Directory.Exists(directory)) Directory.Delete(directory, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SnapshotRejectsTampering()
|
||||
{
|
||||
WithTemporarySnapshot((path, store) =>
|
||||
|
||||
Reference in New Issue
Block a user