Stufe 4c (#764): Bezeichner auf Englisch - Typen, Methoden, Felder, Parameter, Locals, Testnamen
Mit Roslyn umbenannt (Verweise folgen, Zeichenketten bleiben unberuehrt). Nicht umbenannt, weil gespeichert oder ueber die API gebunden (Stufe 4e): Properties, Record-Parameter, Enum-Member sowie die Parameter der Endpunkt-Handler (Routen-/Query-Bindung ueber den Namen). Die JSON-Felder anonymer Objekte bleiben ausdruecklich benannt (JsonFilter: pfad). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
837a634a22
commit
77062facc9
@@ -23,9 +23,9 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
Path.GetTempPath(), "clawd-tests", "auto-" + Guid.NewGuid().ToString("N")[..8]);
|
||||
|
||||
private readonly FakeLauncher _launcher = new();
|
||||
private readonly FakeChannel _kanal = new();
|
||||
private readonly FakeChannel _channel = new();
|
||||
private readonly FakeTokenSource _tokens = new();
|
||||
private readonly InstanceDirectoryManager _verzeichnisse;
|
||||
private readonly InstanceDirectoryManager _directories;
|
||||
|
||||
private static readonly SupervisionOptions Options = new(
|
||||
ProbeInterval: TimeSpan.FromMilliseconds(50),
|
||||
@@ -38,12 +38,12 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
public AutostartTests()
|
||||
{
|
||||
Directory.CreateDirectory(_root);
|
||||
_verzeichnisse = new InstanceDirectoryManager(Path.Combine(_root, "Instances"));
|
||||
_directories = new InstanceDirectoryManager(Path.Combine(_root, "Instances"));
|
||||
|
||||
// The socket only answers if a process is really running - otherwise an
|
||||
// answer stored in advance would mean "already running", and the manager would take over
|
||||
// instead of starting.
|
||||
_kanal.Launcher = _launcher;
|
||||
_channel.Launcher = _launcher;
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
@@ -56,7 +56,7 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
private ManagerCore Manager(RestartPolicy? policy = null)
|
||||
{
|
||||
var register = new InstanceRegistry(
|
||||
_verzeichnisse, _launcher, _kanal, NullLoggerFactory.Instance, Options);
|
||||
_directories, _launcher, _channel, NullLoggerFactory.Instance, Options);
|
||||
|
||||
return new ManagerCore(
|
||||
new ManagerSettingsStore(_root), register, _tokens, NullLoggerFactory.Instance,
|
||||
@@ -64,30 +64,30 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
}
|
||||
|
||||
/// <summary>Creates an instance and sets the switch in its instance file.</summary>
|
||||
private string Instanz(string name, bool autostart)
|
||||
private string Instance(string name, bool autostart)
|
||||
{
|
||||
var pfad = _verzeichnisse.CreateInstance(name);
|
||||
var datei = Path.Combine(pfad, "InstanceSettings.json");
|
||||
var path = _directories.CreateInstance(name);
|
||||
var datei = Path.Combine(path, "InstanceSettings.json");
|
||||
|
||||
var config = JsonSerializer.Deserialize<InstanceConfig>(File.ReadAllText(datei))!;
|
||||
config.AutostartByManager = autostart;
|
||||
File.WriteAllText(datei, JsonSerializer.Serialize(config));
|
||||
|
||||
_kanal.AnswerFor[Path.GetFullPath(pfad)] = new InstanceIdentity("i-" + name, name, "0.1.2");
|
||||
_channel.AnswerFor[Path.GetFullPath(path)] = new InstanceIdentity("i-" + name, name, "0.1.2");
|
||||
|
||||
return pfad;
|
||||
return path;
|
||||
}
|
||||
|
||||
private static SupervisionEvent Absturz(string pfad, string name) => new(
|
||||
InstanceEventKind.Crashed, Path.GetFullPath(pfad), name, 4711, 137,
|
||||
private static SupervisionEvent Crash(string path, string name) => new(
|
||||
InstanceEventKind.Crashed, Path.GetFullPath(path), name, 4711, 137,
|
||||
"unerwartet beendet", DateTimeOffset.UtcNow);
|
||||
|
||||
// ─── When coming up ───
|
||||
|
||||
[Fact]
|
||||
public async Task Eine_Instanz_mit_Autostart_wird_beim_Hochfahren_gestartet()
|
||||
public async Task An_instance_with_autostart_is_started_on_startup()
|
||||
{
|
||||
Instanz("Alpha", autostart: true);
|
||||
Instance("Alpha", autostart: true);
|
||||
|
||||
await using var manager = Manager();
|
||||
await manager.StartAsync();
|
||||
@@ -97,9 +97,9 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Ohne_Autostart_bleibt_sie_aus()
|
||||
public async Task Without_autostart_it_stays_off()
|
||||
{
|
||||
Instanz("Alpha", autostart: false);
|
||||
Instance("Alpha", autostart: false);
|
||||
|
||||
await using var manager = Manager();
|
||||
await manager.StartAsync();
|
||||
@@ -113,27 +113,27 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
/// <c>state.db</c> would be the opposite of helpful.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Was_schon_laeuft_wird_nicht_noch_einmal_gestartet()
|
||||
public async Task What_already_runs_is_not_started_again()
|
||||
{
|
||||
var pfad = Instanz("Alpha", autostart: true);
|
||||
var path = Instance("Alpha", autostart: true);
|
||||
|
||||
await using (var erster = Manager())
|
||||
await erster.StartAsync();
|
||||
await using (var firstOne = Manager())
|
||||
await firstOne.StartAsync();
|
||||
|
||||
_launcher.Starts.ShouldBe(1);
|
||||
|
||||
await using var zweiter = Manager();
|
||||
await zweiter.StartAsync();
|
||||
await using var secondOne = Manager();
|
||||
await secondOne.StartAsync();
|
||||
|
||||
_launcher.Starts.ShouldBe(1, "Uebernommen, nicht neu gestartet.");
|
||||
zweiter.Instances.Instances.Single().ProcessId.ShouldBe(_launcher.Last!.Id);
|
||||
secondOne.Instances.Instances.Single().ProcessId.ShouldBe(_launcher.Last!.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Der_Schalter_steht_in_der_Liste()
|
||||
public async Task The_switch_is_in_the_list()
|
||||
{
|
||||
Instanz("Mit", autostart: true);
|
||||
Instanz("Ohne", autostart: false);
|
||||
Instance("Mit", autostart: true);
|
||||
Instance("Ohne", autostart: false);
|
||||
|
||||
await using var manager = Manager();
|
||||
await manager.StartAsync();
|
||||
@@ -145,33 +145,33 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
// ─── After a crash ───
|
||||
|
||||
[Fact]
|
||||
public async Task Nach_einem_Absturz_wird_wieder_gestartet()
|
||||
public async Task After_a_crash_it_is_restarted()
|
||||
{
|
||||
var pfad = Instanz("Alpha", autostart: true);
|
||||
var path = Instance("Alpha", autostart: true);
|
||||
|
||||
await using var manager = Manager();
|
||||
await manager.StartAsync();
|
||||
|
||||
var vorher = _launcher.Starts;
|
||||
var before = _launcher.Starts;
|
||||
|
||||
// The process is gone; supervision has reported it.
|
||||
_launcher.Last!.Exit(137);
|
||||
await manager.RestartAfterCrashAsync(Absturz(pfad, "Alpha"));
|
||||
await manager.RestartAfterCrashAsync(Crash(path, "Alpha"));
|
||||
|
||||
_launcher.Starts.ShouldBe(vorher + 1);
|
||||
_launcher.Starts.ShouldBe(before + 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Ohne_Autostart_wird_nach_einem_Absturz_nichts_getan()
|
||||
public async Task Without_autostart_nothing_is_done_after_a_crash()
|
||||
{
|
||||
var pfad = Instanz("Alpha", autostart: false);
|
||||
var path = Instance("Alpha", autostart: false);
|
||||
|
||||
await using var manager = Manager();
|
||||
await manager.StartAsync();
|
||||
await manager.StartInstanceAsync(pfad);
|
||||
await manager.StartInstanceAsync(path);
|
||||
|
||||
_launcher.Last!.Exit(137);
|
||||
await manager.RestartAfterCrashAsync(Absturz(pfad, "Alpha"));
|
||||
await manager.RestartAfterCrashAsync(Crash(path, "Alpha"));
|
||||
|
||||
_launcher.Starts.ShouldBe(1, "Nur der Start von Hand, kein Neustart.");
|
||||
}
|
||||
@@ -187,38 +187,38 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
/// the start nobody sits on the database any more.</para>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Eine_verstummte_Instanz_wird_erst_beendet_und_dann_neu_gestartet()
|
||||
public async Task A_silent_instance_is_first_stopped_and_then_restarted()
|
||||
{
|
||||
var pfad = Instanz("Alpha", autostart: true);
|
||||
var path = Instance("Alpha", autostart: true);
|
||||
|
||||
await using var manager = Manager();
|
||||
await manager.StartAsync();
|
||||
|
||||
var alt = _launcher.Last.ShouldNotBeNull();
|
||||
var old = _launcher.Last.ShouldNotBeNull();
|
||||
_launcher.Starts.ShouldBe(1);
|
||||
|
||||
// From now on it hangs: the process lives, the socket no longer answers.
|
||||
_kanal.Verstummen(pfad);
|
||||
_channel.GoSilent(path);
|
||||
|
||||
var aufsicht = manager.Instances.SupervisorFor(pfad).ShouldNotBeNull();
|
||||
var supervisor = manager.Instances.SupervisorFor(path).ShouldNotBeNull();
|
||||
|
||||
// Three passes until the alarm - nothing is done before that.
|
||||
for (var i = 0; i < 3; i++) await aufsicht.CheckAsync();
|
||||
for (var i = 0; i < 3; i++) await supervisor.CheckAsync();
|
||||
|
||||
aufsicht.Condition.ShouldBe(InstanceCondition.Silent);
|
||||
alt.WasKilled.ShouldBeFalse("Vor Ablauf der Frist wird nicht abgeschossen.");
|
||||
supervisor.Condition.ShouldBe(InstanceCondition.Silent);
|
||||
old.WasKilled.ShouldBeFalse("Vor Ablauf der Frist wird nicht abgeschossen.");
|
||||
|
||||
// The deadline expires (SilentKillGrace: 300ms).
|
||||
await Task.Delay(400);
|
||||
await aufsicht.CheckAsync();
|
||||
await supervisor.CheckAsync();
|
||||
|
||||
alt.WasKilled.ShouldBeTrue("Nach der Frist wird der haengende Prozess beendet.");
|
||||
old.WasKilled.ShouldBeTrue("Nach der Frist wird der haengende Prozess beendet.");
|
||||
|
||||
// The crash path restarts - and the new process is a different one.
|
||||
await Warte(() => _launcher.Starts >= 2);
|
||||
await WaitFor(() => _launcher.Starts >= 2);
|
||||
|
||||
_launcher.Last.ShouldNotBeNull().Id.ShouldNotBe(alt.Id);
|
||||
alt.HasExited.ShouldBeTrue("Der alte Prozess darf beim Start nicht mehr leben.");
|
||||
_launcher.Last.ShouldNotBeNull().Id.ShouldNotBe(old.Id);
|
||||
old.HasExited.ShouldBeTrue("Der alte Prozess darf beim Start nicht mehr leben.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -229,31 +229,31 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
/// "someone answered".</para>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Wer_aufraeumt_gilt_nicht_als_verstummt()
|
||||
public async Task Whoever_cleans_up_does_not_count_as_silent()
|
||||
{
|
||||
var pfad = Instanz("Alpha", autostart: true);
|
||||
var path = Instance("Alpha", autostart: true);
|
||||
|
||||
await using var manager = Manager();
|
||||
await manager.StartAsync();
|
||||
|
||||
var prozess = _launcher.Last.ShouldNotBeNull();
|
||||
var process = _launcher.Last.ShouldNotBeNull();
|
||||
|
||||
_kanal.AnswerFor[Path.GetFullPath(pfad)] = new InstanceIdentity(
|
||||
_channel.AnswerFor[Path.GetFullPath(path)] = new InstanceIdentity(
|
||||
"i-Alpha", "Alpha", "0.1.2",
|
||||
ShutdownPhase.Draining, OpenWork: 2, OpenSummary: "Agentenläufe: 2");
|
||||
|
||||
var aufsicht = manager.Instances.SupervisorFor(pfad).ShouldNotBeNull();
|
||||
var supervisor = manager.Instances.SupervisorFor(path).ShouldNotBeNull();
|
||||
|
||||
for (var i = 0; i < 5; i++) await aufsicht.CheckAsync();
|
||||
for (var i = 0; i < 5; i++) await supervisor.CheckAsync();
|
||||
|
||||
aufsicht.Condition.ShouldBe(InstanceCondition.Running);
|
||||
prozess.WasKilled.ShouldBeFalse();
|
||||
supervisor.Condition.ShouldBe(InstanceCondition.Running);
|
||||
process.WasKilled.ShouldBeFalse();
|
||||
_launcher.Starts.ShouldBe(1);
|
||||
}
|
||||
|
||||
private static async Task Warte(Func<bool> bedingung)
|
||||
private static async Task WaitFor(Func<bool> condition)
|
||||
{
|
||||
for (var i = 0; i < 100 && !bedingung(); i++)
|
||||
for (var i = 0; i < 100 && !condition(); i++)
|
||||
await Task.Delay(20);
|
||||
}
|
||||
|
||||
@@ -265,22 +265,22 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
/// log and a bug tracker full of repetitions.</para>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Nach_drei_Neustarts_im_Zeitfenster_setzt_der_Manager_aus()
|
||||
public async Task After_three_restarts_in_the_time_window_the_manager_pauses()
|
||||
{
|
||||
var pfad = Instanz("Wackelig", autostart: true);
|
||||
var path = Instance("Wackelig", autostart: true);
|
||||
|
||||
await using var manager = Manager(new RestartPolicy(MaxRestarts: 3, Window: TimeSpan.FromMinutes(10)));
|
||||
await manager.StartAsync();
|
||||
|
||||
var nachStart = _launcher.Starts;
|
||||
var afterStart = _launcher.Starts;
|
||||
|
||||
for (var i = 0; i < 6; i++)
|
||||
{
|
||||
_launcher.Last!.Exit(137);
|
||||
await manager.RestartAfterCrashAsync(Absturz(pfad, "Wackelig"));
|
||||
await manager.RestartAfterCrashAsync(Crash(path, "Wackelig"));
|
||||
}
|
||||
|
||||
(_launcher.Starts - nachStart).ShouldBe(3, "Drei Versuche, dann Schluss.");
|
||||
(_launcher.Starts - afterStart).ShouldBe(3, "Drei Versuche, dann Schluss.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -288,9 +288,9 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
/// the earlier attempts would mean punishing them for the crash.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Ein_Start_von_Hand_raeumt_den_Zaehler_ab()
|
||||
public async Task A_manual_start_clears_the_counter()
|
||||
{
|
||||
var pfad = Instanz("Wackelig", autostart: true);
|
||||
var path = Instance("Wackelig", autostart: true);
|
||||
|
||||
await using var manager = Manager(new RestartPolicy(3, TimeSpan.FromMinutes(10)));
|
||||
await manager.StartAsync();
|
||||
@@ -298,53 +298,53 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
_launcher.Last!.Exit(137);
|
||||
await manager.RestartAfterCrashAsync(Absturz(pfad, "Wackelig"));
|
||||
await manager.RestartAfterCrashAsync(Crash(path, "Wackelig"));
|
||||
}
|
||||
|
||||
var erschoepft = _launcher.Starts;
|
||||
var exhausted = _launcher.Starts;
|
||||
|
||||
// A new manager starts at zero - just like a start by hand.
|
||||
await using var frisch = Manager(new RestartPolicy(3, TimeSpan.FromMinutes(10)));
|
||||
await frisch.StartAsync();
|
||||
await using var fresh = Manager(new RestartPolicy(3, TimeSpan.FromMinutes(10)));
|
||||
await fresh.StartAsync();
|
||||
|
||||
_launcher.Last!.Exit(137);
|
||||
await frisch.RestartAfterCrashAsync(Absturz(pfad, "Wackelig"));
|
||||
await fresh.RestartAfterCrashAsync(Crash(path, "Wackelig"));
|
||||
|
||||
_launcher.Starts.ShouldBeGreaterThan(erschoepft);
|
||||
_launcher.Starts.ShouldBeGreaterThan(exhausted);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The circuit breaker on its own.</summary>
|
||||
public sealed class RestartLedgerTests
|
||||
{
|
||||
private sealed class Uhr(DateTimeOffset jetzt) : TimeProvider
|
||||
private sealed class Clock(DateTimeOffset jetzt) : TimeProvider
|
||||
{
|
||||
public DateTimeOffset Jetzt { get; set; } = jetzt;
|
||||
public override DateTimeOffset GetUtcNow() => Jetzt;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bis_zur_Grenze_ja_danach_nein()
|
||||
public void Yes_up_to_the_limit_no_after_it()
|
||||
{
|
||||
var buch = new RestartLedger(new RestartPolicy(3, TimeSpan.FromMinutes(10)));
|
||||
var book = new RestartLedger(new RestartPolicy(3, TimeSpan.FromMinutes(10)));
|
||||
|
||||
buch.TryRecord("/a", out _).ShouldBeTrue();
|
||||
buch.TryRecord("/a", out _).ShouldBeTrue();
|
||||
buch.TryRecord("/a", out var dritter).ShouldBeTrue();
|
||||
dritter.ShouldBe(3);
|
||||
book.TryRecord("/a", out _).ShouldBeTrue();
|
||||
book.TryRecord("/a", out _).ShouldBeTrue();
|
||||
book.TryRecord("/a", out var third).ShouldBeTrue();
|
||||
third.ShouldBe(3);
|
||||
|
||||
buch.TryRecord("/a", out _).ShouldBeFalse();
|
||||
book.TryRecord("/a", out _).ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Jede_Instanz_hat_ihr_eigenes_Konto()
|
||||
public void Every_instance_has_its_own_account()
|
||||
{
|
||||
var buch = new RestartLedger(new RestartPolicy(1, TimeSpan.FromMinutes(10)));
|
||||
var book = new RestartLedger(new RestartPolicy(1, TimeSpan.FromMinutes(10)));
|
||||
|
||||
buch.TryRecord("/a", out _).ShouldBeTrue();
|
||||
buch.TryRecord("/a", out _).ShouldBeFalse();
|
||||
book.TryRecord("/a", out _).ShouldBeTrue();
|
||||
book.TryRecord("/a", out _).ShouldBeFalse();
|
||||
|
||||
buch.TryRecord("/b", out _).ShouldBeTrue("Die eine Instanz sperrt die andere nicht.");
|
||||
book.TryRecord("/b", out _).ShouldBeTrue("Die eine Instanz sperrt die andere nicht.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -352,32 +352,32 @@ public sealed class RestartLedgerTests
|
||||
/// up never runs into the limit — one that falls every minute does immediately.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Alte_Versuche_fallen_aus_dem_Fenster()
|
||||
public void Old_attempts_fall_out_of_the_window()
|
||||
{
|
||||
var uhr = new Uhr(DateTimeOffset.UnixEpoch);
|
||||
var buch = new RestartLedger(new RestartPolicy(2, TimeSpan.FromMinutes(10)), uhr);
|
||||
var clock = new Clock(DateTimeOffset.UnixEpoch);
|
||||
var book = new RestartLedger(new RestartPolicy(2, TimeSpan.FromMinutes(10)), clock);
|
||||
|
||||
buch.TryRecord("/a", out _).ShouldBeTrue();
|
||||
buch.TryRecord("/a", out _).ShouldBeTrue();
|
||||
buch.TryRecord("/a", out _).ShouldBeFalse();
|
||||
book.TryRecord("/a", out _).ShouldBeTrue();
|
||||
book.TryRecord("/a", out _).ShouldBeTrue();
|
||||
book.TryRecord("/a", out _).ShouldBeFalse();
|
||||
|
||||
uhr.Jetzt = uhr.Jetzt.AddMinutes(11);
|
||||
clock.Jetzt = clock.Jetzt.AddMinutes(11);
|
||||
|
||||
buch.TryRecord("/a", out var wieder).ShouldBeTrue();
|
||||
wieder.ShouldBe(1, "Die alten Versuche zaehlen nicht mehr mit.");
|
||||
book.TryRecord("/a", out var repeated).ShouldBeTrue();
|
||||
repeated.ShouldBe(1, "Die alten Versuche zaehlen nicht mehr mit.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Vergessen_setzt_zurueck()
|
||||
public void Forgetting_resets()
|
||||
{
|
||||
var buch = new RestartLedger(new RestartPolicy(1, TimeSpan.FromMinutes(10)));
|
||||
var book = new RestartLedger(new RestartPolicy(1, TimeSpan.FromMinutes(10)));
|
||||
|
||||
buch.TryRecord("/a", out _).ShouldBeTrue();
|
||||
buch.TryRecord("/a", out _).ShouldBeFalse();
|
||||
book.TryRecord("/a", out _).ShouldBeTrue();
|
||||
book.TryRecord("/a", out _).ShouldBeFalse();
|
||||
|
||||
buch.Forget("/a");
|
||||
book.Forget("/a");
|
||||
|
||||
buch.TryRecord("/a", out _).ShouldBeTrue();
|
||||
book.TryRecord("/a", out _).ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,13 +395,13 @@ public sealed class StaleStateTests : IAsyncDisposable
|
||||
Path.GetTempPath(), "clawd-tests", "stale-" + Guid.NewGuid().ToString("N")[..8]);
|
||||
|
||||
private readonly FakeLauncher _launcher = new();
|
||||
private readonly FakeChannel _kanal = new();
|
||||
private readonly FakeChannel _channel = new();
|
||||
|
||||
public StaleStateTests()
|
||||
{
|
||||
Directory.CreateDirectory(_root);
|
||||
_kanal.Launcher = _launcher;
|
||||
_kanal.Answer = new InstanceIdentity("i-1", "Alpha", "0.1.2");
|
||||
_channel.Launcher = _launcher;
|
||||
_channel.Answer = new InstanceIdentity("i-1", "Alpha", "0.1.2");
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
@@ -412,13 +412,13 @@ public sealed class StaleStateTests : IAsyncDisposable
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Ein_Start_prueft_nach_statt_dem_eigenen_Zustand_zu_glauben()
|
||||
public async Task A_start_verifies_instead_of_trusting_its_own_state()
|
||||
{
|
||||
var dir = Path.Combine(_root, "Instance-Alpha");
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
await using var aufsicht = new InstanceSupervisor(
|
||||
dir, _launcher, _kanal, NullLogger.Instance,
|
||||
await using var supervisor = new InstanceSupervisor(
|
||||
dir, _launcher, _channel, NullLogger.Instance,
|
||||
new SupervisionOptions(
|
||||
TimeSpan.FromSeconds(30), // deliberately sluggish: no pass in between
|
||||
TimeSpan.FromMilliseconds(600),
|
||||
@@ -427,17 +427,17 @@ public sealed class StaleStateTests : IAsyncDisposable
|
||||
TimeSpan.FromMilliseconds(300),
|
||||
TimeSpan.FromSeconds(2)));
|
||||
|
||||
(await aufsicht.StartAsync()).ShouldBeTrue();
|
||||
aufsicht.Condition.ShouldBe(InstanceCondition.Running);
|
||||
(await supervisor.StartAsync()).ShouldBeTrue();
|
||||
supervisor.Condition.ShouldBe(InstanceCondition.Running);
|
||||
|
||||
// The instance breaks away. Supervision has not noticed yet - the next
|
||||
// pass would only come in thirty seconds.
|
||||
_launcher.Last!.Exit(137);
|
||||
aufsicht.Condition.ShouldBe(InstanceCondition.Running, "Noch nichts bemerkt.");
|
||||
supervisor.Condition.ShouldBe(InstanceCondition.Running, "Noch nichts bemerkt.");
|
||||
|
||||
(await aufsicht.StartAsync()).ShouldBeTrue();
|
||||
(await supervisor.StartAsync()).ShouldBeTrue();
|
||||
|
||||
_launcher.Starts.ShouldBe(2, "Es wurde wirklich gestartet, nicht nur zugestimmt.");
|
||||
aufsicht.Condition.ShouldBe(InstanceCondition.Running);
|
||||
supervisor.Condition.ShouldBe(InstanceCondition.Running);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user