using SQLInsight.Core.Data; using SQLInsight.Core.Findings; using SQLInsight.Rules.Concurrency; using SQLInsight.Rules.Engine; using static SQLInsight.Rules.Tests.TestInstances; namespace SQLInsight.Rules.Tests; public class ActivityRuleTests { private static RuleResult Run(IRule rule, RuleContext context) => Assert.Single(new RuleEngine([rule]).Evaluate(context)); private static OpenTransaction Tran(double minutes, long logMb = 1) => new(61, 4711, "user_transaction", Now.AddMinutes(-minutes), logMb * 1024 * 1024, 0, "AX", 1, @"KUNDE\anne", "PC01", "Microsoft Dynamics AX", "sleeping", null, "UPDATE INVENTSUM SET …"); private static ActivitySnapshot Snapshot(IReadOnlyList? transactions = null, IReadOnlyList? requests = null) => new() { CapturedAt = Now, Transactions = transactions ?? [], LongRequests = requests ?? [] }; [Theory] [InlineData(9, null)] [InlineData(12, Severity.Medium)] [InlineData(61, Severity.High)] public void Open_transactions_by_age(double minutes, Severity? expected) { var result = Run(new LongTransactionRule(), With(Snapshot([Tran(minutes)]))); Assert.Equal(expected, result.Findings.SingleOrDefault()?.Severity); if (expected is not null) { var finding = result.Findings.Single(); Assert.True(finding.Evidence.Single(e => e.Name == "Login").Sensitive); Assert.True(finding.Evidence.Single(e => e.Name == "Sætning").Sensitive); Assert.DoesNotContain("anne", finding.Title + finding.Subject, StringComparison.Ordinal); } } [Theory] [InlineData(500, RuleOutcome.Passed)] [InlineData(2048, RuleOutcome.Findings)] public void Transactions_holding_much_log(long megabytes, RuleOutcome expected) => Assert.Equal(expected, Run(new LargeTransactionRule(), With(Snapshot([Tran(1, megabytes)]))).Outcome); [Fact] public void Long_running_statements_are_found_but_not_backups_or_waitfor() { var select = new LongRunningRequest(70, Now.AddMinutes(-20), 20 * 60_000, "SELECT", "suspended", "LCK_M_S", 1000, "AX", "anne", "PC01", "AX", 61, "SELECT …"); Assert.True(ActivityAnalysis.IsStatement(select)); Assert.False(ActivityAnalysis.IsStatement(select with { Command = "BACKUP DATABASE" })); Assert.False(ActivityAnalysis.IsStatement(select with { WaitType = "WAITFOR" })); var finding = Assert.Single(Run(new LongRunningStatementRule(), With(Snapshot(requests: [select]))).Findings); Assert.Equal("61", finding.Evidence.Single(e => e.Name == "Blokeret af").Value); } }