Cron: Bereich mit Schritt (7-22/3) lesen, ungueltige Ausdruecke im Scanner melden (#597)

Der Nachrichten-Digest im Dauerbetrieb der Test-VM lief nie: CronExpression
verstand 'von-bis/schritt' nicht, TaskSchedule verschluckte den Fehler.
Version 0.1.5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-14 15:51:36 +02:00
co-authored by Claude Opus 5
parent 6581fd0187
commit 8ab9d99abe
6 changed files with 118 additions and 13 deletions
@@ -48,6 +48,24 @@ public sealed class CronExpressionTests
cron.GetNextOccurrence(Local(2026, 3, 1, 0, 0)).ShouldBe(Local(2028, 2, 29, 0, 0));
}
[Fact]
public void Bereich_mit_Schritt_alle_drei_Stunden_tagsueber()
{
// #597: "0 7-22/3 * * *" warf vorher eine FormatException, die Aufgabe lief nie.
var cron = CronExpression.Parse("0 7-22/3 * * *"); // 7, 10, 13, 16, 19, 22
cron.GetNextOccurrence(Local(2026, 9, 14, 12, 0)).ShouldBe(Local(2026, 9, 14, 13, 0));
cron.GetNextOccurrence(Local(2026, 9, 14, 22, 0)).ShouldBe(Local(2026, 9, 15, 7, 0));
cron.Matches(Local(2026, 9, 14, 8, 0)).ShouldBeFalse();
}
[Fact]
public void Zahl_mit_Schritt_laeuft_bis_zum_Feldende()
{
var cron = CronExpression.Parse("10/20 * * * *"); // 10, 30, 50
cron.GetNextOccurrence(Local(2026, 9, 14, 12, 31)).ShouldBe(Local(2026, 9, 14, 12, 50));
cron.GetNextOccurrence(Local(2026, 9, 14, 12, 50)).ShouldBe(Local(2026, 9, 14, 13, 10));
}
// ─── R2: Invariante ───
[Theory]
@@ -77,6 +95,9 @@ public sealed class CronExpressionTests
[InlineData("a b c d e")] // keine Zahlen
[InlineData("*/0 * * * *")] // Schritt 0 (wäre Endlosschleife)
[InlineData("5-2 * * * *")] // rückwärtiger Bereich
[InlineData("0 22-7/3 * * *")] // rückwärtiger Bereich mit Schritt
[InlineData("0 7-25/3 * * *")] // Bereichsende außerhalb 0-23
[InlineData("0 7-/3 * * *")] // halber Bereich
[InlineData("* * * * ")] // ein leeres Feld nach Trim → 4 Felder
public void Ungueltige_Ausdruecke_werfen_eine_saubere_FormatException(string expr)
=> Should.Throw<FormatException>(() => CronExpression.Parse(expr));