sqlinsight-pro/tests/SQLInsight.Core.Tests/ConfigurationFingerprintTests.cs
Søren Eggert Lundsteen Olsen ab8cfcad97 Configuration page with change log
- new collector instance-config: collation, edition, version, services and
  accounts (sys.dm_server_services, 2008 R2 SP1+), Instant File
  Initialization and Lock Pages in Memory (where the build has the
  columns), tempdb files, default paths; plus a fingerprint of the whole
  setup (sp_configure, trace flags, services, version, tempdb files)
- changes are computed against the previous collection, which the agent
  restores from the repository after a restart; migration 0008 keeps them
  in insight.ConfigurationChanges (as long as resolved findings)
- SQLI-CFG-013 "Konfiguration ændret": information for a day when
  sp_configure, a trace flag or a service account changes (account names
  are sensitive evidence)
- page /instanser/{navn}/konfiguration: instance, CPU and memory, services,
  tempdb, trace flags, non-default sp_configure (default vs. in use vs.
  configured) and the change log; linked from the instance page
- the management report lists configuration changes in the period
- trace flag reading shared by trace-flags and instance-config

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 08:12:26 +02:00

69 lines
3.4 KiB
C#

using SQLInsight.Core.Data;
namespace SQLInsight.Core.Tests;
public class ConfigurationFingerprintTests
{
private static readonly DateTimeOffset At = new(2026, 10, 2, 8, 0, 0, TimeSpan.Zero);
[Fact]
public void Changed_added_and_removed_items_are_listed()
{
ConfigurationItem[] before =
[
new("sp_configure", "max degree of parallelism", "0"),
new("Trace flag", "1222", "til"),
new("Tjenestekonto", "SQL Server (MSSQLSERVER)", @"NT Service\MSSQLSERVER"),
];
ConfigurationItem[] after =
[
new("sp_configure", "max degree of parallelism", "1"),
new("Trace flag", "3226", "til"),
new("Tjenestekonto", "SQL Server (MSSQLSERVER)", @"NT Service\MSSQLSERVER"),
];
var changes = ConfigurationFingerprint.Diff(before, after, At);
Assert.Equal(3, changes.Count);
Assert.Contains(new ConfigurationChange("sp_configure", "max degree of parallelism", "0", "1", At), changes);
Assert.Contains(new ConfigurationChange("Trace flag", "3226", null, "til", At), changes);
Assert.Contains(new ConfigurationChange("Trace flag", "1222", "til", null, At), changes);
}
[Fact]
public void Same_setup_has_no_changes() =>
Assert.Empty(ConfigurationFingerprint.Diff([new("Instans", "Collation", "Danish_Norwegian_CI_AS")], [new("Instans", "Collation", "Danish_Norwegian_CI_AS")], At));
[Fact]
public void Fingerprint_covers_options_flags_services_and_instance_settings()
{
var instance = new InstanceConfigurationSnapshot
{
CapturedAt = At,
ProductVersion = "16.0.4135.4",
ProductLevel = "RTM",
Collation = "Danish_Norwegian_CI_AS",
Services = [new ServiceInfo("SQL Server (MSSQLSERVER)", @"KUNDE\svc-sql", "Automatic", "Running", true)],
InstantFileInitialization = true,
TempdbFiles = [new TempdbFile("tempdev", "ROWS", 8, "64 MB", "ubegrænset"), new TempdbFile("temp2", "ROWS", 8, "64 MB", "ubegrænset"), new TempdbFile("templog", "LOG", 8, "64 MB", "ubegrænset")],
};
var items = ConfigurationFingerprint.Items(instance, [new ConfigurationOption("max server memory (MB)", 8192, 8192)], [1222]);
Assert.Contains(new ConfigurationItem("sp_configure", "max server memory (MB)", "8192"), items);
Assert.Contains(new ConfigurationItem("Trace flag", "1222", "til"), items);
Assert.Contains(new ConfigurationItem("Tjenestekonto", "SQL Server (MSSQLSERVER)", @"KUNDE\svc-sql"), items);
Assert.Contains(new ConfigurationItem("Instans", "Version", "16.0.4135.4 RTM"), items);
Assert.Contains(new ConfigurationItem("Tempdb", "Antal datafiler", "2"), items);
Assert.Contains(new ConfigurationItem("Hukommelse", "Instant File Initialization", "til"), items);
Assert.DoesNotContain(items, i => i.Name == "Lock Pages in Memory"); // unknown on this build: not part of the fingerprint
}
[Theory]
[InlineData("cost threshold for parallelism", 5L)]
[InlineData("max server memory (MB)", 2147483647L)]
[InlineData("default trace enabled", 1L)]
[InlineData("an option nobody knows", null)]
public void Defaults_are_known_for_the_documented_options(string option, long? expected) =>
Assert.Equal(expected, ConfigurationFingerprint.DefaultValue(option));
}