using SQLInsight.Core.Findings; using SQLInsight.Core.Instances; using SQLInsight.Rules.Engine; using SQLInsight.Rules.Lifecycle; namespace SQLInsight.Rules.Tests; public class SupportLifecycleRuleTests { private static readonly SupportLifecycleRule Rule = new(SupportLifecycleCatalog.LoadEmbedded()); private static readonly DateTimeOffset Today = new(2026, 9, 29, 0, 0, 0, TimeSpan.Zero); [Theory] [InlineData("8.00.2039")] [InlineData("9.00.5000.00")] [InlineData("10.50.6000.34")] [InlineData("12.0.6024.0")] [InlineData("13.0.6300.2")] public void Out_of_support_releases_are_critical(string version) { var evaluation = Rule.Evaluate(TestInstances.Context(version, Today)); Assert.Equal(RuleOutcome.Findings, evaluation.Outcome); Assert.Equal(Severity.Critical, Assert.Single(evaluation.Findings).Severity); } [Theory] [InlineData("2026-09-29", Severity.Medium)] // 378 days left [InlineData("2026-10-12", Severity.High)] // exactly 365 days left [InlineData("2027-10-12", Severity.High)] // last day of support [InlineData("2027-10-13", Severity.Critical)] public void Sql2017_escalates_as_extended_support_ends(string date, Severity expected) { // SQL Server 2017 extended support ends 2027-10-12. var now = DateTimeOffset.Parse(date + "T12:00:00Z", System.Globalization.CultureInfo.InvariantCulture); var evaluation = Rule.Evaluate(TestInstances.Context("14.0.3456.2", now)); Assert.Equal(expected, Assert.Single(evaluation.Findings).Severity); } [Fact] public void Extended_support_further_out_is_medium() { // SQL Server 2019 left mainstream support 2025-02-28; extended runs to 2030. var evaluation = Rule.Evaluate(TestInstances.Context("15.0.4355.3", Today)); Assert.Equal(Severity.Medium, Assert.Single(evaluation.Findings).Severity); } [Fact] public void Mainstream_support_passes() { var evaluation = Rule.Evaluate(TestInstances.Context("16.0.4135.4", Today)); Assert.Equal(RuleOutcome.Passed, evaluation.Outcome); } [Fact] public void Release_without_published_dates_is_not_measurable() { var evaluation = Rule.Evaluate(TestInstances.Context("17.0.1000.7", Today)); Assert.Equal(RuleOutcome.NotMeasurable, evaluation.Outcome); } [Fact] public void Unknown_future_release_is_not_measurable() { var evaluation = Rule.Evaluate(TestInstances.Context("18.0.100.1", Today)); Assert.Equal(RuleOutcome.NotMeasurable, evaluation.Outcome); Assert.Contains("Opdater", evaluation.Reason, StringComparison.Ordinal); } [Fact] public void Runs_on_sql2000_because_it_needs_no_capabilities() { Assert.Empty(Rule.RequiredCapabilities); } [Fact] public void Catalog_covers_every_known_release() { var catalog = SupportLifecycleCatalog.LoadEmbedded(); foreach (var release in Enum.GetValues().Where(r => r != SqlServerRelease.Unknown)) { Assert.NotNull(catalog.Find(release)); } } }