Some checks are pending
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
CI / Build og unit tests (push) Waiting to run
- Managed Instance reports 12.0.2000.8 but is evergreen: treated as the newest engine with all capabilities; new SelfManagedInfrastructure capability so backup, CHECKDB, files, tempdb, memory, patch level and lifecycle rules report 'handled by Azure' instead of false findings - Microsoft Entra ID login (managed identity, service principal, default credential chain) via SqlConnection.AccessTokenCallback - Least-privilege script recognizes Managed Instance; deadlock collector falls back to the ring buffer when event files cannot be read - Web UI shows the right release for Managed Instance - README and installation docs: notifications and Managed Instance - Catalog test: 61 rules with unique, well-formed ids Integration suite green on SQL Server 2017 and 2022. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
108 lines
3.9 KiB
C#
108 lines
3.9 KiB
C#
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 Sql2025_is_in_mainstream_support()
|
|
{
|
|
var evaluation = Rule.Evaluate(TestInstances.Context("17.0.1000.7", Today));
|
|
|
|
Assert.Equal(RuleOutcome.Passed, evaluation.Outcome);
|
|
}
|
|
|
|
[Fact]
|
|
public void Release_without_published_dates_is_not_measurable()
|
|
{
|
|
var catalog = new SupportLifecycleCatalog([new SupportLifecycle(SqlServerRelease.SqlServer2025, null, null)]);
|
|
|
|
var evaluation = new SupportLifecycleRule(catalog).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_but_not_on_managed_instance()
|
|
{
|
|
Assert.Equal([Capability.SelfManagedInfrastructure], Rule.RequiredCapabilities);
|
|
Assert.Equal(RuleOutcome.Findings, new RuleEngine([Rule]).Evaluate(TestInstances.Context("8.00.2039")).Single().Outcome);
|
|
}
|
|
|
|
[Fact]
|
|
public void Catalog_has_dates_for_every_known_release()
|
|
{
|
|
var catalog = SupportLifecycleCatalog.LoadEmbedded();
|
|
|
|
foreach (var release in Enum.GetValues<SqlServerRelease>().Where(r => r is not (SqlServerRelease.Unknown or SqlServerRelease.AzureSqlManagedInstance)))
|
|
{
|
|
var lifecycle = catalog.Find(release);
|
|
Assert.NotNull(lifecycle);
|
|
Assert.NotNull(lifecycle.MainstreamEnd);
|
|
Assert.NotNull(lifecycle.ExtendedEnd);
|
|
Assert.True(lifecycle.ExtendedEnd > lifecycle.MainstreamEnd, $"{release}: extended must end after mainstream");
|
|
}
|
|
}
|
|
}
|