Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.

This commit is contained in:
StellaOps Bot
2025-12-26 21:54:17 +02:00
parent 335ff7da16
commit c2b9cd8d1f
3717 changed files with 264714 additions and 48202 deletions

View File

@@ -1,111 +1,215 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Notifier", "StellaOps.Notifier", "{B561C84F-7AB2-7B4E-D703-D6D5908493D1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notifier.Tests", "StellaOps.Notifier\StellaOps.Notifier.Tests\StellaOps.Notifier.Tests.csproj", "{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notifier.Worker", "StellaOps.Notifier\StellaOps.Notifier.Worker\StellaOps.Notifier.Worker.csproj", "{1488AD55-0086-46D2-967B-8D0E07161876}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notify.Models", "..\Notify\__Libraries\StellaOps.Notify.Models\StellaOps.Notify.Models.csproj", "{52391B39-F69D-4C9A-9588-EAC5AD023546}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notify.Queue", "..\Notify\__Libraries\StellaOps.Notify.Queue\StellaOps.Notify.Queue.csproj", "{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notify.Engine", "..\Notify\__Libraries\StellaOps.Notify.Engine\StellaOps.Notify.Engine.csproj", "{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notifier.WebService", "StellaOps.Notifier\StellaOps.Notifier.WebService\StellaOps.Notifier.WebService.csproj", "{F6252853-A408-4658-9006-5DDF140A536A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Debug|x64.ActiveCfg = Debug|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Debug|x64.Build.0 = Debug|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Debug|x86.ActiveCfg = Debug|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Debug|x86.Build.0 = Debug|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Release|Any CPU.Build.0 = Release|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Release|x64.ActiveCfg = Release|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Release|x64.Build.0 = Release|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Release|x86.ActiveCfg = Release|Any CPU
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54}.Release|x86.Build.0 = Release|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Debug|x64.ActiveCfg = Debug|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Debug|x64.Build.0 = Debug|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Debug|x86.ActiveCfg = Debug|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Debug|x86.Build.0 = Debug|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Release|Any CPU.Build.0 = Release|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Release|x64.ActiveCfg = Release|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Release|x64.Build.0 = Release|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Release|x86.ActiveCfg = Release|Any CPU
{1488AD55-0086-46D2-967B-8D0E07161876}.Release|x86.Build.0 = Release|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Debug|x64.ActiveCfg = Debug|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Debug|x64.Build.0 = Debug|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Debug|x86.ActiveCfg = Debug|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Debug|x86.Build.0 = Debug|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Release|Any CPU.Build.0 = Release|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Release|x64.ActiveCfg = Release|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Release|x64.Build.0 = Release|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Release|x86.ActiveCfg = Release|Any CPU
{52391B39-F69D-4C9A-9588-EAC5AD023546}.Release|x86.Build.0 = Release|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Debug|x64.ActiveCfg = Debug|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Debug|x64.Build.0 = Debug|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Debug|x86.ActiveCfg = Debug|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Debug|x86.Build.0 = Debug|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Release|Any CPU.Build.0 = Release|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Release|x64.ActiveCfg = Release|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Release|x64.Build.0 = Release|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Release|x86.ActiveCfg = Release|Any CPU
{6D2D2F1F-45AA-4F52-AD1B-1F7562F7C714}.Release|x86.Build.0 = Release|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Debug|x64.ActiveCfg = Debug|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Debug|x64.Build.0 = Debug|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Debug|x86.ActiveCfg = Debug|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Debug|x86.Build.0 = Debug|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Release|Any CPU.Build.0 = Release|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Release|x64.ActiveCfg = Release|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Release|x64.Build.0 = Release|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Release|x86.ActiveCfg = Release|Any CPU
{E61AA8CA-29C2-4BEB-B53B-36B7DE31E9AE}.Release|x86.Build.0 = Release|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Debug|x64.ActiveCfg = Debug|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Debug|x64.Build.0 = Debug|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Debug|x86.ActiveCfg = Debug|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Debug|x86.Build.0 = Debug|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Release|Any CPU.Build.0 = Release|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Release|x64.ActiveCfg = Release|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Release|x64.Build.0 = Release|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Release|x86.ActiveCfg = Release|Any CPU
{F6252853-A408-4658-9006-5DDF140A536A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{65E29FD4-99F5-49DA-BBCC-BE04096F9E54} = {B561C84F-7AB2-7B4E-D703-D6D5908493D1}
{1488AD55-0086-46D2-967B-8D0E07161876} = {B561C84F-7AB2-7B4E-D703-D6D5908493D1}
{F6252853-A408-4658-9006-5DDF140A536A} = {B561C84F-7AB2-7B4E-D703-D6D5908493D1}
EndGlobalSection
EndGlobal
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Notifier", "StellaOps.Notifier", "{639596D3-53A6-3894-2109-085AA8166F49}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Notifier.Tests", "StellaOps.Notifier.Tests", "{37856662-AA7B-BD21-3B47-3480699EA4E8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Notifier.WebService", "StellaOps.Notifier.WebService", "{977AC9AB-7D67-08D4-2B1C-DBE2ACC89C97}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Notifier.Worker", "StellaOps.Notifier.Worker", "{E19B124B-8FBE-341C-D798-9B6263896CBD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "__External", "__External", "{5B52EF8A-3661-DCFF-797D-BC4D6AC60BDA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AirGap", "AirGap", "{F310596E-88BB-9E54-885E-21C61971917E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.AirGap.Policy", "StellaOps.AirGap.Policy", "{D9492ED1-A812-924B-65E4-F518592B49BB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.AirGap.Policy", "StellaOps.AirGap.Policy", "{3823DE1E-2ACE-C956-99E1-00DB786D9E1D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Notify", "Notify", "{D2162FEA-AFA4-2A88-6444-2F6D845260BB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "__Libraries", "__Libraries", "{63EAEA3B-ADC9-631D-774E-7AA04490EDDD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Notify.Engine", "StellaOps.Notify.Engine", "{FFBCC722-2884-8426-A5ED-D73D8A0C5CE6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Notify.Models", "StellaOps.Notify.Models", "{B0F64757-F7A7-1A11-8DEC-BAC72EB5EC29}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Notify.Persistence", "StellaOps.Notify.Persistence", "{C5F86BAD-155A-591C-9610-55D40F59C775}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Notify.Queue", "StellaOps.Notify.Queue", "{4F9F3B3A-221C-4F00-B4E9-4AA44C0C8F9A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Router", "Router", "{FC018E5B-1E2F-DE19-1E97-0C845058C469}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "__Libraries", "__Libraries", "{1BE5B76C-B486-560B-6CB2-44C6537249AA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Microservice", "StellaOps.Microservice", "{3DE1DCDC-C845-4AC7-7B66-34B0A9E8626B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Microservice.AspNetCore", "StellaOps.Microservice.AspNetCore", "{6FA01E92-606B-0CB8-8583-6F693A903CFC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Router.AspNet", "StellaOps.Router.AspNet", "{A5994E92-7E0E-89FE-5628-DE1A0176B8BA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Router.Common", "StellaOps.Router.Common", "{54C11B29-4C54-7255-AB44-BEB63AF9BD1F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "__Libraries", "__Libraries", "{1345DD29-BB3A-FB5F-4B3D-E29F6045A27A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Canonical.Json", "StellaOps.Canonical.Json", "{79E122F4-2325-3E92-438E-5825A307B594}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Cryptography", "StellaOps.Cryptography", "{66557252-B5C4-664B-D807-07018C627474}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Infrastructure.EfCore", "StellaOps.Infrastructure.EfCore", "{FCD529E0-DD17-6587-B29C-12D425C0AD0C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Infrastructure.Postgres", "StellaOps.Infrastructure.Postgres", "{61B23570-4F2D-B060-BE1F-37995682E494}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.TestKit", "StellaOps.TestKit", "{8380A20C-A5B8-EE91-1A58-270323688CB9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.AirGap.Policy", "E:\dev\git.stella-ops.org\src\AirGap\StellaOps.AirGap.Policy\StellaOps.AirGap.Policy\StellaOps.AirGap.Policy.csproj", "{AD31623A-BC43-52C2-D906-AC1D8784A541}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Canonical.Json", "E:\dev\git.stella-ops.org\src\__Libraries\StellaOps.Canonical.Json\StellaOps.Canonical.Json.csproj", "{AF9E7F02-25AD-3540-18D7-F6A4F8BA5A60}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Cryptography", "E:\dev\git.stella-ops.org\src\__Libraries\StellaOps.Cryptography\StellaOps.Cryptography.csproj", "{F664A948-E352-5808-E780-77A03F19E93E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Infrastructure.EfCore", "E:\dev\git.stella-ops.org\src\__Libraries\StellaOps.Infrastructure.EfCore\StellaOps.Infrastructure.EfCore.csproj", "{A63897D9-9531-989B-7309-E384BCFC2BB9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Infrastructure.Postgres", "E:\dev\git.stella-ops.org\src\__Libraries\StellaOps.Infrastructure.Postgres\StellaOps.Infrastructure.Postgres.csproj", "{8C594D82-3463-3367-4F06-900AC707753D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Microservice", "E:\dev\git.stella-ops.org\src\Router\__Libraries\StellaOps.Microservice\StellaOps.Microservice.csproj", "{BAD08D96-A80A-D27F-5D9C-656AEEB3D568}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Microservice.AspNetCore", "E:\dev\git.stella-ops.org\src\Router\__Libraries\StellaOps.Microservice.AspNetCore\StellaOps.Microservice.AspNetCore.csproj", "{F63694F1-B56D-6E72-3F5D-5D38B1541F0F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notifier.Tests", "StellaOps.Notifier\StellaOps.Notifier.Tests\StellaOps.Notifier.Tests.csproj", "{8188439A-89F5-3400-98E8-9A1E10FDC6E9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notifier.WebService", "StellaOps.Notifier\StellaOps.Notifier.WebService\StellaOps.Notifier.WebService.csproj", "{D4AF8947-BA45-BD10-DA38-18C1EB291161}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notifier.Worker", "StellaOps.Notifier\StellaOps.Notifier.Worker\StellaOps.Notifier.Worker.csproj", "{DADF4D7D-CF18-3174-6EFB-53281F0F02E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notify.Engine", "E:\dev\git.stella-ops.org\src\Notify\__Libraries\StellaOps.Notify.Engine\StellaOps.Notify.Engine.csproj", "{8ED04856-EACE-5385-CDFB-BBA78C545AA7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notify.Models", "E:\dev\git.stella-ops.org\src\Notify\__Libraries\StellaOps.Notify.Models\StellaOps.Notify.Models.csproj", "{20D1569C-2A47-38B8-075E-47225B674394}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notify.Persistence", "E:\dev\git.stella-ops.org\src\Notify\__Libraries\StellaOps.Notify.Persistence\StellaOps.Notify.Persistence.csproj", "{2F7AA715-25AE-086A-7DF4-CAB5EF00E2B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notify.Queue", "E:\dev\git.stella-ops.org\src\Notify\__Libraries\StellaOps.Notify.Queue\StellaOps.Notify.Queue.csproj", "{6A93F807-4839-1633-8B24-810660BB4C28}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Router.AspNet", "E:\dev\git.stella-ops.org\src\Router\__Libraries\StellaOps.Router.AspNet\StellaOps.Router.AspNet.csproj", "{79104479-B087-E5D0-5523-F1803282A246}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Router.Common", "E:\dev\git.stella-ops.org\src\Router\__Libraries\StellaOps.Router.Common\StellaOps.Router.Common.csproj", "{F17A6F0B-3120-2BA9-84D8-5F8BA0B9705D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.TestKit", "E:\dev\git.stella-ops.org\src\__Libraries\StellaOps.TestKit\StellaOps.TestKit.csproj", "{AF043113-CCE3-59C1-DF71-9804155F26A8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AD31623A-BC43-52C2-D906-AC1D8784A541}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD31623A-BC43-52C2-D906-AC1D8784A541}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD31623A-BC43-52C2-D906-AC1D8784A541}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD31623A-BC43-52C2-D906-AC1D8784A541}.Release|Any CPU.Build.0 = Release|Any CPU
{AF9E7F02-25AD-3540-18D7-F6A4F8BA5A60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF9E7F02-25AD-3540-18D7-F6A4F8BA5A60}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF9E7F02-25AD-3540-18D7-F6A4F8BA5A60}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF9E7F02-25AD-3540-18D7-F6A4F8BA5A60}.Release|Any CPU.Build.0 = Release|Any CPU
{F664A948-E352-5808-E780-77A03F19E93E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F664A948-E352-5808-E780-77A03F19E93E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F664A948-E352-5808-E780-77A03F19E93E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F664A948-E352-5808-E780-77A03F19E93E}.Release|Any CPU.Build.0 = Release|Any CPU
{A63897D9-9531-989B-7309-E384BCFC2BB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

View File

@@ -58,7 +58,7 @@ public sealed class AttestationEventEndpointTests : IClassFixture<NotifierApplic
};
message.Headers.Add("X-StellaOps-Tenant", "tenant-sample");
var response = await client.SendAsync(message, TestContext.Current.CancellationToken);
var response = await client.SendAsync(message, CancellationToken.None);
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
Assert.Single(recordingQueue.Published);

View File

@@ -24,23 +24,23 @@ public sealed class AttestationTemplateSeederTests
templateRepo,
contentRoot,
logger,
TestContext.Current.CancellationToken);
CancellationToken.None);
var seededRouting = await AttestationTemplateSeeder.SeedRoutingAsync(
channelRepo,
ruleRepo,
contentRoot,
logger,
TestContext.Current.CancellationToken);
CancellationToken.None);
Assert.True(seededTemplates >= 6, "Expected attestation templates to be seeded.");
Assert.True(seededRouting >= 0, $"Expected attestation routing seed to create channels and rules but got {seededRouting}.");
var templates = await templateRepo.ListAsync("bootstrap", TestContext.Current.CancellationToken);
var templates = await templateRepo.ListAsync("bootstrap", CancellationToken.None);
Assert.Contains(templates, t => t.Key == "tmpl-attest-key-rotation");
Assert.Contains(templates, t => t.Key == "tmpl-attest-transparency-anomaly");
var rules = await ruleRepo.ListAsync("bootstrap", TestContext.Current.CancellationToken);
var rules = await ruleRepo.ListAsync("bootstrap", CancellationToken.None);
Assert.Contains(rules, r => r.Match.EventKinds.Contains("authority.keys.rotated"));
Assert.Contains(rules, r => r.Match.EventKinds.Contains("attestor.transparency.anomaly"));
}

View File

@@ -72,7 +72,7 @@ public class CorrelationEngineTests
.ReturnsAsync(ThrottleCheckResult.NotThrottled());
// Act
var result = await _engine.CorrelateAsync(notifyEvent);
var result = await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
Assert.True(result.Correlated);
@@ -110,7 +110,7 @@ public class CorrelationEngineTests
.ReturnsAsync(ThrottleCheckResult.NotThrottled());
// Act
var result = await _engine.CorrelateAsync(notifyEvent);
var result = await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
Assert.False(result.IsNewIncident);
@@ -145,7 +145,7 @@ public class CorrelationEngineTests
.ReturnsAsync(ThrottleCheckResult.NotThrottled());
// Act
var result = await _engine.CorrelateAsync(notifyEvent);
var result = await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
Assert.False(result.IsNewIncident);
@@ -174,7 +174,7 @@ public class CorrelationEngineTests
.ReturnsAsync(SuppressionCheckResult.Suppressed("Quiet hours", "quiet_hours"));
// Act
var result = await _engine.CorrelateAsync(notifyEvent);
var result = await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
Assert.False(result.ShouldNotify);
@@ -208,7 +208,7 @@ public class CorrelationEngineTests
.ReturnsAsync(ThrottleCheckResult.Throttled(15));
// Act
var result = await _engine.CorrelateAsync(notifyEvent);
var result = await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
Assert.False(result.ShouldNotify);
@@ -249,7 +249,7 @@ public class CorrelationEngineTests
.ReturnsAsync(ThrottleCheckResult.NotThrottled());
// Act
await _engine.CorrelateAsync(notifyEvent);
await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
_keyBuilderFactory.Verify(f => f.GetBuilder("template"), Times.Once);
@@ -289,7 +289,7 @@ public class CorrelationEngineTests
.ReturnsAsync(ThrottleCheckResult.NotThrottled());
// Act
await _engine.CorrelateAsync(notifyEvent);
await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
_keyBuilderFactory.Verify(f => f.GetBuilder("custom"), Times.Once);
@@ -323,7 +323,7 @@ public class CorrelationEngineTests
.ReturnsAsync(ThrottleCheckResult.NotThrottled());
// Act
var result = await _engine.CorrelateAsync(notifyEvent);
var result = await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
Assert.True(result.ShouldNotify);
@@ -358,7 +358,7 @@ public class CorrelationEngineTests
.ReturnsAsync(ThrottleCheckResult.NotThrottled());
// Act
var result = await _engine.CorrelateAsync(notifyEvent);
var result = await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
Assert.True(result.ShouldNotify);
@@ -393,7 +393,7 @@ public class CorrelationEngineTests
.ReturnsAsync(ThrottleCheckResult.NotThrottled());
// Act
var result = await _engine.CorrelateAsync(notifyEvent);
var result = await _engine.CorrelateAsync(notifyEvent, CancellationToken.None);
// Assert
Assert.True(result.ShouldNotify);
@@ -406,7 +406,7 @@ public class CorrelationEngineTests
_options.ThrottlingEnabled = false;
// Act
var result = await _engine.CheckThrottleAsync("tenant1", "key1", null);
var result = await _engine.CheckThrottleAsync("tenant1", "key1", null, CancellationToken.None);
// Assert
Assert.False(result.IsThrottled);

View File

@@ -29,8 +29,7 @@ public class InMemoryIncidentManagerTests
public async Task GetOrCreateIncidentAsync_CreatesNewIncident()
{
// Act
var incident = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Assert
Assert.NotNull(incident);
@@ -47,13 +46,11 @@ public class InMemoryIncidentManagerTests
public async Task GetOrCreateIncidentAsync_ReturnsSameIncidentWithinWindow()
{
// Arrange
var incident1 = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident1 = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Act - request again within correlation window
_timeProvider.Advance(TimeSpan.FromMinutes(30));
var incident2 = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident2 = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Assert
Assert.Equal(incident1.IncidentId, incident2.IncidentId);
@@ -63,16 +60,14 @@ public class InMemoryIncidentManagerTests
public async Task GetOrCreateIncidentAsync_CreatesNewIncidentOutsideWindow()
{
// Arrange
var incident1 = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident1 = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Record an event to set LastOccurrence
await _manager.RecordEventAsync("tenant1", incident1.IncidentId, "event-1");
await _manager.RecordEventAsync("tenant1", incident1.IncidentId, "event-1", CancellationToken.None);
// Act - request again outside correlation window
_timeProvider.Advance(TimeSpan.FromHours(2));
var incident2 = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident2 = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Assert
Assert.NotEqual(incident1.IncidentId, incident2.IncidentId);
@@ -82,14 +77,12 @@ public class InMemoryIncidentManagerTests
public async Task GetOrCreateIncidentAsync_CreatesNewIncidentAfterResolution()
{
// Arrange
var incident1 = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident1 = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
await _manager.ResolveAsync("tenant1", incident1.IncidentId, "operator");
await _manager.ResolveAsync("tenant1", incident1.IncidentId, "operator", cancellationToken: CancellationToken.None);
// Act - request again after resolution
var incident2 = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident2 = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Assert
Assert.NotEqual(incident1.IncidentId, incident2.IncidentId);
@@ -99,11 +92,10 @@ public class InMemoryIncidentManagerTests
public async Task RecordEventAsync_IncrementsEventCount()
{
// Arrange
var incident = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Act
var updated = await _manager.RecordEventAsync("tenant1", incident.IncidentId, "event-1");
var updated = await _manager.RecordEventAsync("tenant1", incident.IncidentId, "event-1", CancellationToken.None);
// Assert
Assert.Equal(1, updated.EventCount);
@@ -114,14 +106,13 @@ public class InMemoryIncidentManagerTests
public async Task RecordEventAsync_UpdatesLastOccurrence()
{
// Arrange
var incident = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
var initialTime = incident.LastOccurrence;
// Act
_timeProvider.Advance(TimeSpan.FromMinutes(10));
var updated = await _manager.RecordEventAsync("tenant1", incident.IncidentId, "event-1");
var updated = await _manager.RecordEventAsync("tenant1", incident.IncidentId, "event-1", CancellationToken.None);
// Assert
Assert.True(updated.LastOccurrence > initialTime);
@@ -132,13 +123,12 @@ public class InMemoryIncidentManagerTests
{
// Arrange
_options.ReopenOnNewEvent = true;
var incident = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
await _manager.AcknowledgeAsync("tenant1", incident.IncidentId, "operator");
await _manager.AcknowledgeAsync("tenant1", incident.IncidentId, "operator", cancellationToken: CancellationToken.None);
// Act
var updated = await _manager.RecordEventAsync("tenant1", incident.IncidentId, "event-1");
var updated = await _manager.RecordEventAsync("tenant1", incident.IncidentId, "event-1", CancellationToken.None);
// Assert
Assert.Equal(IncidentStatus.Open, updated.Status);
@@ -149,19 +139,17 @@ public class InMemoryIncidentManagerTests
{
// Act & Assert
await Assert.ThrowsAsync<InvalidOperationException>(
() => _manager.RecordEventAsync("tenant1", "unknown-id", "event-1"));
() => _manager.RecordEventAsync("tenant1", "unknown-id", "event-1", CancellationToken.None));
}
[Fact]
public async Task AcknowledgeAsync_SetsAcknowledgedStatus()
{
// Arrange
var incident = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Act
var acknowledged = await _manager.AcknowledgeAsync(
"tenant1", incident.IncidentId, "operator", "Looking into it");
var acknowledged = await _manager.AcknowledgeAsync("tenant1", incident.IncidentId, "operator", "Looking into it", CancellationToken.None);
// Assert
Assert.NotNull(acknowledged);
@@ -175,7 +163,7 @@ public class InMemoryIncidentManagerTests
public async Task AcknowledgeAsync_ReturnsNullForUnknownIncident()
{
// Act
var result = await _manager.AcknowledgeAsync("tenant1", "unknown-id", "operator");
var result = await _manager.AcknowledgeAsync("tenant1", "unknown-id", "operator", cancellationToken: CancellationToken.None);
// Assert
Assert.Null(result);
@@ -185,11 +173,10 @@ public class InMemoryIncidentManagerTests
public async Task AcknowledgeAsync_ReturnsNullForWrongTenant()
{
// Arrange
var incident = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Act
var result = await _manager.AcknowledgeAsync("tenant2", incident.IncidentId, "operator");
var result = await _manager.AcknowledgeAsync("tenant2", incident.IncidentId, "operator", cancellationToken: CancellationToken.None);
// Assert
Assert.Null(result);
@@ -199,13 +186,12 @@ public class InMemoryIncidentManagerTests
public async Task AcknowledgeAsync_DoesNotChangeResolvedIncident()
{
// Arrange
var incident = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
await _manager.ResolveAsync("tenant1", incident.IncidentId, "operator");
await _manager.ResolveAsync("tenant1", incident.IncidentId, "operator", cancellationToken: CancellationToken.None);
// Act
var result = await _manager.AcknowledgeAsync("tenant1", incident.IncidentId, "operator2");
var result = await _manager.AcknowledgeAsync("tenant1", incident.IncidentId, "operator2", cancellationToken: CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -216,12 +202,10 @@ public class InMemoryIncidentManagerTests
public async Task ResolveAsync_SetsResolvedStatus()
{
// Arrange
var incident = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var incident = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Act
var resolved = await _manager.ResolveAsync(
"tenant1", incident.IncidentId, "operator", "Issue fixed");
var resolved = await _manager.ResolveAsync("tenant1", incident.IncidentId, "operator", "Issue fixed", CancellationToken.None);
// Assert
Assert.NotNull(resolved);
@@ -235,7 +219,7 @@ public class InMemoryIncidentManagerTests
public async Task ResolveAsync_ReturnsNullForUnknownIncident()
{
// Act
var result = await _manager.ResolveAsync("tenant1", "unknown-id", "operator");
var result = await _manager.ResolveAsync("tenant1", "unknown-id", "operator", cancellationToken: CancellationToken.None);
// Assert
Assert.Null(result);
@@ -245,11 +229,10 @@ public class InMemoryIncidentManagerTests
public async Task GetAsync_ReturnsIncident()
{
// Arrange
var created = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var created = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Act
var result = await _manager.GetAsync("tenant1", created.IncidentId);
var result = await _manager.GetAsync("tenant1", created.IncidentId, CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -260,7 +243,7 @@ public class InMemoryIncidentManagerTests
public async Task GetAsync_ReturnsNullForUnknownIncident()
{
// Act
var result = await _manager.GetAsync("tenant1", "unknown-id");
var result = await _manager.GetAsync("tenant1", "unknown-id", CancellationToken.None);
// Assert
Assert.Null(result);
@@ -270,11 +253,10 @@ public class InMemoryIncidentManagerTests
public async Task GetAsync_ReturnsNullForWrongTenant()
{
// Arrange
var created = await _manager.GetOrCreateIncidentAsync(
"tenant1", "correlation-key", "security.alert", "Test Alert");
var created = await _manager.GetOrCreateIncidentAsync("tenant1", "correlation-key", "security.alert", "Test Alert", CancellationToken.None);
// Act
var result = await _manager.GetAsync("tenant2", created.IncidentId);
var result = await _manager.GetAsync("tenant2", created.IncidentId, CancellationToken.None);
// Assert
Assert.Null(result);
@@ -284,12 +266,12 @@ public class InMemoryIncidentManagerTests
public async Task ListAsync_ReturnsIncidentsForTenant()
{
// Arrange
await _manager.GetOrCreateIncidentAsync("tenant1", "key1", "event1", "Alert 1");
await _manager.GetOrCreateIncidentAsync("tenant1", "key2", "event2", "Alert 2");
await _manager.GetOrCreateIncidentAsync("tenant2", "key3", "event3", "Alert 3");
await _manager.GetOrCreateIncidentAsync("tenant1", "key1", "event1", "Alert 1", CancellationToken.None);
await _manager.GetOrCreateIncidentAsync("tenant1", "key2", "event2", "Alert 2", CancellationToken.None);
await _manager.GetOrCreateIncidentAsync("tenant2", "key3", "event3", "Alert 3", CancellationToken.None);
// Act
var result = await _manager.ListAsync("tenant1");
var result = await _manager.ListAsync("tenant1", cancellationToken: CancellationToken.None);
// Assert
Assert.Equal(2, result.Count);
@@ -300,15 +282,15 @@ public class InMemoryIncidentManagerTests
public async Task ListAsync_FiltersbyStatus()
{
// Arrange
var inc1 = await _manager.GetOrCreateIncidentAsync("tenant1", "key1", "event1", "Alert 1");
var inc2 = await _manager.GetOrCreateIncidentAsync("tenant1", "key2", "event2", "Alert 2");
await _manager.AcknowledgeAsync("tenant1", inc1.IncidentId, "operator");
await _manager.ResolveAsync("tenant1", inc2.IncidentId, "operator");
var inc1 = await _manager.GetOrCreateIncidentAsync("tenant1", "key1", "event1", "Alert 1", CancellationToken.None);
var inc2 = await _manager.GetOrCreateIncidentAsync("tenant1", "key2", "event2", "Alert 2", CancellationToken.None);
await _manager.AcknowledgeAsync("tenant1", inc1.IncidentId, "operator", cancellationToken: CancellationToken.None);
await _manager.ResolveAsync("tenant1", inc2.IncidentId, "operator", cancellationToken: CancellationToken.None);
// Act
var openIncidents = await _manager.ListAsync("tenant1", IncidentStatus.Open);
var acknowledgedIncidents = await _manager.ListAsync("tenant1", IncidentStatus.Acknowledged);
var resolvedIncidents = await _manager.ListAsync("tenant1", IncidentStatus.Resolved);
var openIncidents = await _manager.ListAsync("tenant1", IncidentStatus.Open, cancellationToken: CancellationToken.None);
var acknowledgedIncidents = await _manager.ListAsync("tenant1", IncidentStatus.Acknowledged, cancellationToken: CancellationToken.None);
var resolvedIncidents = await _manager.ListAsync("tenant1", IncidentStatus.Resolved, cancellationToken: CancellationToken.None);
// Assert
Assert.Empty(openIncidents);
@@ -320,21 +302,21 @@ public class InMemoryIncidentManagerTests
public async Task ListAsync_OrdersByLastOccurrenceDescending()
{
// Arrange
var inc1 = await _manager.GetOrCreateIncidentAsync("tenant1", "key1", "event1", "Alert 1");
await _manager.RecordEventAsync("tenant1", inc1.IncidentId, "e1");
var inc1 = await _manager.GetOrCreateIncidentAsync("tenant1", "key1", "event1", "Alert 1", CancellationToken.None);
await _manager.RecordEventAsync("tenant1", inc1.IncidentId, "e1", CancellationToken.None);
_timeProvider.Advance(TimeSpan.FromMinutes(1));
var inc2 = await _manager.GetOrCreateIncidentAsync("tenant1", "key2", "event2", "Alert 2");
await _manager.RecordEventAsync("tenant1", inc2.IncidentId, "e2");
var inc2 = await _manager.GetOrCreateIncidentAsync("tenant1", "key2", "event2", "Alert 2", CancellationToken.None);
await _manager.RecordEventAsync("tenant1", inc2.IncidentId, "e2", CancellationToken.None);
_timeProvider.Advance(TimeSpan.FromMinutes(1));
var inc3 = await _manager.GetOrCreateIncidentAsync("tenant1", "key3", "event3", "Alert 3");
await _manager.RecordEventAsync("tenant1", inc3.IncidentId, "e3");
var inc3 = await _manager.GetOrCreateIncidentAsync("tenant1", "key3", "event3", "Alert 3", CancellationToken.None);
await _manager.RecordEventAsync("tenant1", inc3.IncidentId, "e3", CancellationToken.None);
// Act
var result = await _manager.ListAsync("tenant1");
var result = await _manager.ListAsync("tenant1", cancellationToken: CancellationToken.None);
// Assert
Assert.Equal(3, result.Count);
@@ -349,11 +331,11 @@ public class InMemoryIncidentManagerTests
// Arrange
for (int i = 0; i < 10; i++)
{
await _manager.GetOrCreateIncidentAsync("tenant1", $"key{i}", $"event{i}", $"Alert {i}");
await _manager.GetOrCreateIncidentAsync("tenant1", $"key{i}", $"event{i}", $"Alert {i}", CancellationToken.None);
}
// Act
var result = await _manager.ListAsync("tenant1", limit: 5);
var result = await _manager.ListAsync("tenant1", limit: 5, cancellationToken: CancellationToken.None);
// Assert
Assert.Equal(5, result.Count);

View File

@@ -30,8 +30,8 @@ public class InMemoryNotifyThrottlerTests
public async Task RecordEventAsync_AddsEventToState()
{
// Act
await _throttler.RecordEventAsync("tenant1", "key1");
var result = await _throttler.CheckAsync("tenant1", "key1", null, null);
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
var result = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
// Assert
Assert.False(result.IsThrottled);
@@ -42,7 +42,7 @@ public class InMemoryNotifyThrottlerTests
public async Task CheckAsync_NoEvents_ReturnsNotThrottled()
{
// Act
var result = await _throttler.CheckAsync("tenant1", "key1", null, null);
var result = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
// Assert
Assert.False(result.IsThrottled);
@@ -55,11 +55,11 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 5; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Act
var result = await _throttler.CheckAsync("tenant1", "key1", null, null);
var result = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
// Assert
Assert.False(result.IsThrottled);
@@ -72,11 +72,11 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 10; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Act
var result = await _throttler.CheckAsync("tenant1", "key1", null, null);
var result = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
// Assert
Assert.True(result.IsThrottled);
@@ -89,11 +89,11 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 15; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Act
var result = await _throttler.CheckAsync("tenant1", "key1", null, null);
var result = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
// Assert
Assert.True(result.IsThrottled);
@@ -106,14 +106,14 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 8; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Move time forward past the window
_timeProvider.Advance(TimeSpan.FromMinutes(6));
// Act
var result = await _throttler.CheckAsync("tenant1", "key1", null, null);
var result = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
// Assert
Assert.False(result.IsThrottled);
@@ -126,7 +126,7 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 5; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Move time forward 2 minutes
@@ -135,11 +135,11 @@ public class InMemoryNotifyThrottlerTests
// Add more events
for (int i = 0; i < 3; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Act - check with 1 minute window (should only see recent 3)
var result = await _throttler.CheckAsync("tenant1", "key1", TimeSpan.FromMinutes(1), null);
var result = await _throttler.CheckAsync("tenant1", "key1", TimeSpan.FromMinutes(1), null, CancellationToken.None);
// Assert
Assert.False(result.IsThrottled);
@@ -152,11 +152,11 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 5; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Act - check with max 3 events
var result = await _throttler.CheckAsync("tenant1", "key1", null, 3);
var result = await _throttler.CheckAsync("tenant1", "key1", null, 3, CancellationToken.None);
// Assert
Assert.True(result.IsThrottled);
@@ -167,7 +167,7 @@ public class InMemoryNotifyThrottlerTests
public async Task CheckAsync_ThrottledReturnsResetTime()
{
// Arrange
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
// Move time forward 2 minutes
_timeProvider.Advance(TimeSpan.FromMinutes(2));
@@ -175,11 +175,11 @@ public class InMemoryNotifyThrottlerTests
// Fill up to threshold
for (int i = 0; i < 9; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Act
var result = await _throttler.CheckAsync("tenant1", "key1", null, null);
var result = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
// Assert
Assert.True(result.IsThrottled);
@@ -194,12 +194,12 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 10; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Act
var result1 = await _throttler.CheckAsync("tenant1", "key1", null, null);
var result2 = await _throttler.CheckAsync("tenant1", "key2", null, null);
var result1 = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
var result2 = await _throttler.CheckAsync("tenant1", "key2", null, null, CancellationToken.None);
// Assert
Assert.True(result1.IsThrottled);
@@ -212,12 +212,12 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 10; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Act
var result1 = await _throttler.CheckAsync("tenant1", "key1", null, null);
var result2 = await _throttler.CheckAsync("tenant2", "key1", null, null);
var result1 = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
var result2 = await _throttler.CheckAsync("tenant2", "key1", null, null, CancellationToken.None);
// Assert
Assert.True(result1.IsThrottled);
@@ -230,18 +230,18 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 10; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
}
// Verify throttled
var beforeClear = await _throttler.CheckAsync("tenant1", "key1", null, null);
var beforeClear = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
Assert.True(beforeClear.IsThrottled);
// Act
await _throttler.ClearAsync("tenant1", "key1");
await _throttler.ClearAsync("tenant1", "key1", CancellationToken.None);
// Assert
var afterClear = await _throttler.CheckAsync("tenant1", "key1", null, null);
var afterClear = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
Assert.False(afterClear.IsThrottled);
Assert.Equal(0, afterClear.RecentEventCount);
}
@@ -252,16 +252,16 @@ public class InMemoryNotifyThrottlerTests
// Arrange
for (int i = 0; i < 10; i++)
{
await _throttler.RecordEventAsync("tenant1", "key1");
await _throttler.RecordEventAsync("tenant1", "key2");
await _throttler.RecordEventAsync("tenant1", "key1", CancellationToken.None);
await _throttler.RecordEventAsync("tenant1", "key2", CancellationToken.None);
}
// Act
await _throttler.ClearAsync("tenant1", "key1");
await _throttler.ClearAsync("tenant1", "key1", CancellationToken.None);
// Assert
var result1 = await _throttler.CheckAsync("tenant1", "key1", null, null);
var result2 = await _throttler.CheckAsync("tenant1", "key2", null, null);
var result1 = await _throttler.CheckAsync("tenant1", "key1", null, null, CancellationToken.None);
var result2 = await _throttler.CheckAsync("tenant1", "key2", null, null, CancellationToken.None);
Assert.False(result1.IsThrottled);
Assert.True(result2.IsThrottled);

View File

@@ -43,7 +43,7 @@ public class OperatorOverrideServiceTests
};
// Act
var @override = await _service.CreateOverrideAsync("tenant1", request, "admin@example.com");
var @override = await _service.CreateOverrideAsync("tenant1", request, "admin@example.com", CancellationToken.None);
// Assert
Assert.NotNull(@override);
@@ -69,7 +69,7 @@ public class OperatorOverrideServiceTests
// Act & Assert
await Assert.ThrowsAsync<ArgumentException>(() =>
_service.CreateOverrideAsync("tenant1", request, "admin"));
_service.CreateOverrideAsync("tenant1", request, "admin", CancellationToken.None));
}
[Fact]
@@ -85,7 +85,7 @@ public class OperatorOverrideServiceTests
// Act & Assert
await Assert.ThrowsAsync<ArgumentException>(() =>
_service.CreateOverrideAsync("tenant1", request, "admin"));
_service.CreateOverrideAsync("tenant1", request, "admin", CancellationToken.None));
}
[Fact]
@@ -100,7 +100,7 @@ public class OperatorOverrideServiceTests
};
// Act
await _service.CreateOverrideAsync("tenant1", request, "admin");
await _service.CreateOverrideAsync("tenant1", request, "admin", CancellationToken.None);
// Assert
_auditLogger.Verify(a => a.LogAsync(
@@ -120,10 +120,10 @@ public class OperatorOverrideServiceTests
Type = OverrideType.Throttle,
Reason = "Test override",
Duration = TimeSpan.FromHours(1)
}, "admin");
}, "admin", CancellationToken.None);
// Act
var retrieved = await _service.GetOverrideAsync("tenant1", created.OverrideId);
var retrieved = await _service.GetOverrideAsync("tenant1", created.OverrideId, CancellationToken.None);
// Assert
Assert.NotNull(retrieved);
@@ -139,13 +139,13 @@ public class OperatorOverrideServiceTests
Type = OverrideType.All,
Reason = "Short override",
Duration = TimeSpan.FromMinutes(30)
}, "admin");
}, "admin", CancellationToken.None);
// Advance time past expiry
_timeProvider.Advance(TimeSpan.FromMinutes(31));
// Act
var retrieved = await _service.GetOverrideAsync("tenant1", created.OverrideId);
var retrieved = await _service.GetOverrideAsync("tenant1", created.OverrideId, CancellationToken.None);
// Assert
Assert.NotNull(retrieved);
@@ -161,20 +161,20 @@ public class OperatorOverrideServiceTests
Type = OverrideType.All,
Reason = "Override 1",
Duration = TimeSpan.FromHours(2)
}, "admin");
}, "admin", CancellationToken.None);
await _service.CreateOverrideAsync("tenant1", new OperatorOverrideCreate
{
Type = OverrideType.QuietHours,
Reason = "Override 2 (short)",
Duration = TimeSpan.FromMinutes(10)
}, "admin");
}, "admin", CancellationToken.None);
// Advance time so second override expires
_timeProvider.Advance(TimeSpan.FromMinutes(15));
// Act
var active = await _service.ListActiveOverridesAsync("tenant1");
var active = await _service.ListActiveOverridesAsync("tenant1", CancellationToken.None);
// Assert
Assert.Single(active);
@@ -190,15 +190,15 @@ public class OperatorOverrideServiceTests
Type = OverrideType.All,
Reason = "To be revoked",
Duration = TimeSpan.FromHours(1)
}, "admin");
}, "admin", CancellationToken.None);
// Act
var revoked = await _service.RevokeOverrideAsync("tenant1", created.OverrideId, "supervisor", "No longer needed");
var revoked = await _service.RevokeOverrideAsync("tenant1", created.OverrideId, "supervisor", "No longer needed", CancellationToken.None);
// Assert
Assert.True(revoked);
var retrieved = await _service.GetOverrideAsync("tenant1", created.OverrideId);
var retrieved = await _service.GetOverrideAsync("tenant1", created.OverrideId, CancellationToken.None);
Assert.NotNull(retrieved);
Assert.Equal(OverrideStatus.Revoked, retrieved.Status);
Assert.Equal("supervisor", retrieved.RevokedBy);
@@ -214,10 +214,10 @@ public class OperatorOverrideServiceTests
Type = OverrideType.All,
Reason = "To be revoked",
Duration = TimeSpan.FromHours(1)
}, "admin");
}, "admin", CancellationToken.None);
// Act
await _service.RevokeOverrideAsync("tenant1", created.OverrideId, "supervisor", "Testing");
await _service.RevokeOverrideAsync("tenant1", created.OverrideId, "supervisor", "Testing", CancellationToken.None);
// Assert
_auditLogger.Verify(a => a.LogAsync(
@@ -236,10 +236,10 @@ public class OperatorOverrideServiceTests
Type = OverrideType.QuietHours,
Reason = "Deployment override",
Duration = TimeSpan.FromHours(1)
}, "admin");
}, "admin", CancellationToken.None);
// Act
var result = await _service.CheckOverrideAsync("tenant1", "deployment.complete", null);
var result = await _service.CheckOverrideAsync("tenant1", "deployment.complete", null, CancellationToken.None);
// Assert
Assert.True(result.HasOverride);
@@ -251,7 +251,7 @@ public class OperatorOverrideServiceTests
public async Task CheckOverrideAsync_ReturnsNoOverrideWhenNoneMatch()
{
// Act
var result = await _service.CheckOverrideAsync("tenant1", "event.test", null);
var result = await _service.CheckOverrideAsync("tenant1", "event.test", null, CancellationToken.None);
// Assert
Assert.False(result.HasOverride);
@@ -268,11 +268,11 @@ public class OperatorOverrideServiceTests
Reason = "Only for deployments",
Duration = TimeSpan.FromHours(1),
EventKinds = ["deployment.", "release."]
}, "admin");
}, "admin", CancellationToken.None);
// Act
var deploymentResult = await _service.CheckOverrideAsync("tenant1", "deployment.started", null);
var otherResult = await _service.CheckOverrideAsync("tenant1", "vulnerability.found", null);
var deploymentResult = await _service.CheckOverrideAsync("tenant1", "deployment.started", null, CancellationToken.None);
var otherResult = await _service.CheckOverrideAsync("tenant1", "vulnerability.found", null, CancellationToken.None);
// Assert
Assert.True(deploymentResult.HasOverride);
@@ -289,11 +289,11 @@ public class OperatorOverrideServiceTests
Reason = "Specific incident",
Duration = TimeSpan.FromHours(1),
CorrelationKeys = ["incident-123", "incident-456"]
}, "admin");
}, "admin", CancellationToken.None);
// Act
var matchingResult = await _service.CheckOverrideAsync("tenant1", "event.test", "incident-123");
var nonMatchingResult = await _service.CheckOverrideAsync("tenant1", "event.test", "incident-789");
var matchingResult = await _service.CheckOverrideAsync("tenant1", "event.test", "incident-123", CancellationToken.None);
var nonMatchingResult = await _service.CheckOverrideAsync("tenant1", "event.test", "incident-789", CancellationToken.None);
// Assert
Assert.True(matchingResult.HasOverride);
@@ -310,14 +310,14 @@ public class OperatorOverrideServiceTests
Reason = "Limited use override",
Duration = TimeSpan.FromHours(1),
MaxUsageCount = 5
}, "admin");
}, "admin", CancellationToken.None);
// Act
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test");
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test");
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test", CancellationToken.None);
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test", CancellationToken.None);
// Assert
var updated = await _service.GetOverrideAsync("tenant1", created.OverrideId);
var updated = await _service.GetOverrideAsync("tenant1", created.OverrideId, CancellationToken.None);
Assert.NotNull(updated);
Assert.Equal(2, updated.UsageCount);
}
@@ -332,14 +332,14 @@ public class OperatorOverrideServiceTests
Reason = "Single use override",
Duration = TimeSpan.FromHours(1),
MaxUsageCount = 2
}, "admin");
}, "admin", CancellationToken.None);
// Act
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test");
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test");
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test", CancellationToken.None);
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test", CancellationToken.None);
// Assert
var updated = await _service.GetOverrideAsync("tenant1", created.OverrideId);
var updated = await _service.GetOverrideAsync("tenant1", created.OverrideId, CancellationToken.None);
Assert.NotNull(updated);
Assert.Equal(OverrideStatus.Exhausted, updated.Status);
}
@@ -353,10 +353,10 @@ public class OperatorOverrideServiceTests
Type = OverrideType.All,
Reason = "Override for audit test",
Duration = TimeSpan.FromHours(1)
}, "admin");
}, "admin", CancellationToken.None);
// Act
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test");
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test", CancellationToken.None);
// Assert
_auditLogger.Verify(a => a.LogAsync(
@@ -376,12 +376,12 @@ public class OperatorOverrideServiceTests
Reason = "Single use",
Duration = TimeSpan.FromHours(1),
MaxUsageCount = 1
}, "admin");
}, "admin", CancellationToken.None);
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test");
await _service.RecordOverrideUsageAsync("tenant1", created.OverrideId, "event.test", CancellationToken.None);
// Act
var result = await _service.CheckOverrideAsync("tenant1", "event.other", null);
var result = await _service.CheckOverrideAsync("tenant1", "event.other", null, CancellationToken.None);
// Assert
Assert.False(result.HasOverride);
@@ -401,7 +401,7 @@ public class OperatorOverrideServiceTests
};
// Act
var created = await _service.CreateOverrideAsync("tenant1", request, "admin");
var created = await _service.CreateOverrideAsync("tenant1", request, "admin", CancellationToken.None);
// Assert
Assert.Equal(futureTime, created.EffectiveFrom);
@@ -419,10 +419,10 @@ public class OperatorOverrideServiceTests
Reason = "Future override",
Duration = TimeSpan.FromHours(2),
EffectiveFrom = futureTime
}, "admin");
}, "admin", CancellationToken.None);
// Act (before effective time)
var result = await _service.CheckOverrideAsync("tenant1", "event.test", null);
var result = await _service.CheckOverrideAsync("tenant1", "event.test", null, CancellationToken.None);
// Assert
Assert.False(result.HasOverride);
@@ -437,10 +437,10 @@ public class OperatorOverrideServiceTests
Type = OverrideType.QuietHours | OverrideType.Throttle, // Multiple types
Reason = "Partial override",
Duration = TimeSpan.FromHours(1)
}, "admin");
}, "admin", CancellationToken.None);
// Act
var result = await _service.CheckOverrideAsync("tenant1", "event.test", null);
var result = await _service.CheckOverrideAsync("tenant1", "event.test", null, CancellationToken.None);
// Assert
Assert.True(result.HasOverride);

View File

@@ -42,7 +42,7 @@ public class QuietHourCalendarServiceTests
};
// Act
var calendar = await _service.CreateCalendarAsync("tenant1", request, "admin@example.com");
var calendar = await _service.CreateCalendarAsync("tenant1", request, "admin@example.com", CancellationToken.None);
// Assert
Assert.NotNull(calendar);
@@ -64,7 +64,7 @@ public class QuietHourCalendarServiceTests
};
// Act
await _service.CreateCalendarAsync("tenant1", request, "admin");
await _service.CreateCalendarAsync("tenant1", request, "admin", CancellationToken.None);
// Assert
_auditLogger.Verify(a => a.LogAsync(
@@ -79,12 +79,12 @@ public class QuietHourCalendarServiceTests
public async Task ListCalendarsAsync_ReturnsAllCalendarsForTenant()
{
// Arrange
await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "Calendar 1", Priority = 50 }, "admin");
await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "Calendar 2", Priority = 100 }, "admin");
await _service.CreateCalendarAsync("tenant2", new QuietHourCalendarCreate { Name = "Other Tenant" }, "admin");
await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "Calendar 1", Priority = 50 }, "admin", CancellationToken.None);
await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "Calendar 2", Priority = 100 }, "admin", CancellationToken.None);
await _service.CreateCalendarAsync("tenant2", new QuietHourCalendarCreate { Name = "Other Tenant" }, "admin", CancellationToken.None);
// Act
var calendars = await _service.ListCalendarsAsync("tenant1");
var calendars = await _service.ListCalendarsAsync("tenant1", CancellationToken.None);
// Assert
Assert.Equal(2, calendars.Count);
@@ -96,10 +96,10 @@ public class QuietHourCalendarServiceTests
public async Task GetCalendarAsync_ReturnsCalendarIfExists()
{
// Arrange
var created = await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "Test" }, "admin");
var created = await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "Test" }, "admin", CancellationToken.None);
// Act
var retrieved = await _service.GetCalendarAsync("tenant1", created.CalendarId);
var retrieved = await _service.GetCalendarAsync("tenant1", created.CalendarId, CancellationToken.None);
// Assert
Assert.NotNull(retrieved);
@@ -111,7 +111,7 @@ public class QuietHourCalendarServiceTests
public async Task GetCalendarAsync_ReturnsNullIfNotExists()
{
// Act
var result = await _service.GetCalendarAsync("tenant1", "nonexistent");
var result = await _service.GetCalendarAsync("tenant1", "nonexistent", CancellationToken.None);
// Assert
Assert.Null(result);
@@ -121,7 +121,7 @@ public class QuietHourCalendarServiceTests
public async Task UpdateCalendarAsync_UpdatesExistingCalendar()
{
// Arrange
var created = await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "Original" }, "admin");
var created = await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "Original" }, "admin", CancellationToken.None);
var update = new QuietHourCalendarUpdate
{
@@ -130,7 +130,7 @@ public class QuietHourCalendarServiceTests
};
// Act
var updated = await _service.UpdateCalendarAsync("tenant1", created.CalendarId, update, "other-admin");
var updated = await _service.UpdateCalendarAsync("tenant1", created.CalendarId, update, "other-admin", CancellationToken.None);
// Assert
Assert.NotNull(updated);
@@ -143,14 +143,14 @@ public class QuietHourCalendarServiceTests
public async Task DeleteCalendarAsync_RemovesCalendar()
{
// Arrange
var created = await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "ToDelete" }, "admin");
var created = await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate { Name = "ToDelete" }, "admin", CancellationToken.None);
// Act
var deleted = await _service.DeleteCalendarAsync("tenant1", created.CalendarId, "admin");
var deleted = await _service.DeleteCalendarAsync("tenant1", created.CalendarId, "admin", CancellationToken.None);
// Assert
Assert.True(deleted);
var retrieved = await _service.GetCalendarAsync("tenant1", created.CalendarId);
var retrieved = await _service.GetCalendarAsync("tenant1", created.CalendarId, CancellationToken.None);
Assert.Null(retrieved);
}
@@ -170,13 +170,13 @@ public class QuietHourCalendarServiceTests
EndTime = "08:00"
}
]
}, "admin");
}, "admin", CancellationToken.None);
// Set time to 23:00 (11pm) - within quiet hours
_timeProvider.SetUtcNow(new DateTimeOffset(2024, 1, 15, 23, 0, 0, TimeSpan.Zero));
// Act
var result = await _service.EvaluateCalendarsAsync("tenant1", "vulnerability.found", null);
var result = await _service.EvaluateCalendarsAsync("tenant1", "vulnerability.found", null, CancellationToken.None);
// Assert
Assert.True(result.IsSuppressed);
@@ -200,12 +200,12 @@ public class QuietHourCalendarServiceTests
EndTime = "08:00"
}
]
}, "admin");
}, "admin", CancellationToken.None);
// Time is 2pm (14:00) - outside quiet hours
// Act
var result = await _service.EvaluateCalendarsAsync("tenant1", "vulnerability.found", null);
var result = await _service.EvaluateCalendarsAsync("tenant1", "vulnerability.found", null, CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -228,14 +228,14 @@ public class QuietHourCalendarServiceTests
EndTime = "08:00"
}
]
}, "admin");
}, "admin", CancellationToken.None);
// Set time to 23:00 (11pm) - within quiet hours
_timeProvider.SetUtcNow(new DateTimeOffset(2024, 1, 15, 23, 0, 0, TimeSpan.Zero));
// Act
var criticalResult = await _service.EvaluateCalendarsAsync("tenant1", "critical.security.breach", null);
var normalResult = await _service.EvaluateCalendarsAsync("tenant1", "info.scan.complete", null);
var criticalResult = await _service.EvaluateCalendarsAsync("tenant1", "critical.security.breach", null, CancellationToken.None);
var normalResult = await _service.EvaluateCalendarsAsync("tenant1", "info.scan.complete", null, CancellationToken.None);
// Assert
Assert.False(criticalResult.IsSuppressed); // Critical events not suppressed
@@ -259,11 +259,11 @@ public class QuietHourCalendarServiceTests
EndTime = "23:59"
}
]
}, "admin");
}, "admin", CancellationToken.None);
// Act
var scanResult = await _service.EvaluateCalendarsAsync("tenant1", "scan.complete", null);
var otherResult = await _service.EvaluateCalendarsAsync("tenant1", "vulnerability.found", null);
var scanResult = await _service.EvaluateCalendarsAsync("tenant1", "scan.complete", null, CancellationToken.None);
var otherResult = await _service.EvaluateCalendarsAsync("tenant1", "vulnerability.found", null, CancellationToken.None);
// Assert
Assert.True(scanResult.IsSuppressed);
@@ -287,11 +287,11 @@ public class QuietHourCalendarServiceTests
EndTime = "23:59"
}
]
}, "admin");
}, "admin", CancellationToken.None);
// Act
var teamAResult = await _service.EvaluateCalendarsAsync("tenant1", "event.test", ["team-a"]);
var teamCResult = await _service.EvaluateCalendarsAsync("tenant1", "event.test", ["team-c"]);
var teamAResult = await _service.EvaluateCalendarsAsync("tenant1", "event.test", ["team-a"], CancellationToken.None);
var teamCResult = await _service.EvaluateCalendarsAsync("tenant1", "event.test", ["team-c"], CancellationToken.None);
// Assert
Assert.True(teamAResult.IsSuppressed);
@@ -315,14 +315,14 @@ public class QuietHourCalendarServiceTests
DaysOfWeek = [0, 6] // Sunday and Saturday
}
]
}, "admin");
}, "admin", CancellationToken.None);
// Monday (current time is Monday)
var mondayResult = await _service.EvaluateCalendarsAsync("tenant1", "event.test", null);
var mondayResult = await _service.EvaluateCalendarsAsync("tenant1", "event.test", null, CancellationToken.None);
// Set to Saturday
_timeProvider.SetUtcNow(new DateTimeOffset(2024, 1, 20, 14, 0, 0, TimeSpan.Zero));
var saturdayResult = await _service.EvaluateCalendarsAsync("tenant1", "event.test", null);
var saturdayResult = await _service.EvaluateCalendarsAsync("tenant1", "event.test", null, CancellationToken.None);
// Assert
Assert.False(mondayResult.IsSuppressed);
@@ -345,13 +345,13 @@ public class QuietHourCalendarServiceTests
EndTime = "23:59"
}
]
}, "admin");
}, "admin", CancellationToken.None);
// Disable the calendar
await _service.UpdateCalendarAsync("tenant1", created.CalendarId, new QuietHourCalendarUpdate { Enabled = false }, "admin");
await _service.UpdateCalendarAsync("tenant1", created.CalendarId, new QuietHourCalendarUpdate { Enabled = false }, "admin", CancellationToken.None);
// Act
var result = await _service.EvaluateCalendarsAsync("tenant1", "event.test", null);
var result = await _service.EvaluateCalendarsAsync("tenant1", "event.test", null, CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -375,7 +375,7 @@ public class QuietHourCalendarServiceTests
EndTime = "23:59"
}
]
}, "admin");
}, "admin", CancellationToken.None);
await _service.CreateCalendarAsync("tenant1", new QuietHourCalendarCreate
{
@@ -390,10 +390,10 @@ public class QuietHourCalendarServiceTests
EndTime = "23:59"
}
]
}, "admin");
}, "admin", CancellationToken.None);
// Act
var result = await _service.EvaluateCalendarsAsync("tenant1", "critical.alert", null);
var result = await _service.EvaluateCalendarsAsync("tenant1", "critical.alert", null, CancellationToken.None);
// Assert
Assert.True(result.IsSuppressed);

View File

@@ -34,7 +34,7 @@ public class QuietHoursEvaluatorTests
_options.Schedule = null;
// Act
var result = await _evaluator.EvaluateAsync("tenant1", "test.event");
var result = await _evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -47,7 +47,7 @@ public class QuietHoursEvaluatorTests
_options.Schedule = new QuietHoursSchedule { Enabled = false };
// Act
var result = await _evaluator.EvaluateAsync("tenant1", "test.event");
var result = await _evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -66,7 +66,7 @@ public class QuietHoursEvaluatorTests
};
// Act
var result = await _evaluator.EvaluateAsync("tenant1", "test.event");
var result = await _evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -86,7 +86,7 @@ public class QuietHoursEvaluatorTests
var evaluator = CreateEvaluator();
// Act
var result = await evaluator.EvaluateAsync("tenant1", "test.event");
var result = await evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.True(result.IsSuppressed);
@@ -108,7 +108,7 @@ public class QuietHoursEvaluatorTests
var evaluator = CreateEvaluator();
// Act
var result = await evaluator.EvaluateAsync("tenant1", "test.event");
var result = await evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -128,7 +128,7 @@ public class QuietHoursEvaluatorTests
var evaluator = CreateEvaluator();
// Act
var result = await evaluator.EvaluateAsync("tenant1", "test.event");
var result = await evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.True(result.IsSuppressed);
@@ -148,7 +148,7 @@ public class QuietHoursEvaluatorTests
var evaluator = CreateEvaluator();
// Act
var result = await evaluator.EvaluateAsync("tenant1", "test.event");
var result = await evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.True(result.IsSuppressed);
@@ -168,7 +168,7 @@ public class QuietHoursEvaluatorTests
var evaluator = CreateEvaluator();
// Act
var result = await evaluator.EvaluateAsync("tenant1", "test.event");
var result = await evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -189,7 +189,7 @@ public class QuietHoursEvaluatorTests
var evaluator = CreateEvaluator();
// Act
var result = await evaluator.EvaluateAsync("tenant1", "test.event");
var result = await evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert - Wednesday is not in the list
Assert.False(result.IsSuppressed);
@@ -210,7 +210,7 @@ public class QuietHoursEvaluatorTests
var evaluator = CreateEvaluator();
// Act
var result = await evaluator.EvaluateAsync("tenant1", "test.event");
var result = await evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.True(result.IsSuppressed);
@@ -231,7 +231,7 @@ public class QuietHoursEvaluatorTests
var evaluator = CreateEvaluator();
// Act
var result = await evaluator.EvaluateAsync("tenant1", "security.alert");
var result = await evaluator.EvaluateAsync("tenant1", "security.alert", CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -251,10 +251,10 @@ public class QuietHoursEvaluatorTests
Description = "Scheduled maintenance"
};
await _evaluator.AddMaintenanceWindowAsync("tenant1", window);
await _evaluator.AddMaintenanceWindowAsync("tenant1", window, CancellationToken.None);
// Act
var result = await _evaluator.EvaluateAsync("tenant1", "test.event");
var result = await _evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.True(result.IsSuppressed);
@@ -276,10 +276,10 @@ public class QuietHoursEvaluatorTests
Description = "Future maintenance"
};
await _evaluator.AddMaintenanceWindowAsync("tenant1", window);
await _evaluator.AddMaintenanceWindowAsync("tenant1", window, CancellationToken.None);
// Act
var result = await _evaluator.EvaluateAsync("tenant1", "test.event");
var result = await _evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -298,10 +298,10 @@ public class QuietHoursEvaluatorTests
EndTime = now.AddHours(1)
};
await _evaluator.AddMaintenanceWindowAsync("tenant1", window);
await _evaluator.AddMaintenanceWindowAsync("tenant1", window, CancellationToken.None);
// Act
var result = await _evaluator.EvaluateAsync("tenant2", "test.event");
var result = await _evaluator.EvaluateAsync("tenant2", "test.event", CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -321,10 +321,10 @@ public class QuietHoursEvaluatorTests
AffectedEventKinds = ["scanner", "monitor"]
};
await _evaluator.AddMaintenanceWindowAsync("tenant1", window);
await _evaluator.AddMaintenanceWindowAsync("tenant1", window, CancellationToken.None);
// Act
var result = await _evaluator.EvaluateAsync("tenant1", "scanner.complete");
var result = await _evaluator.EvaluateAsync("tenant1", "scanner.complete", CancellationToken.None);
// Assert
Assert.True(result.IsSuppressed);
@@ -344,10 +344,10 @@ public class QuietHoursEvaluatorTests
AffectedEventKinds = ["scanner", "monitor"]
};
await _evaluator.AddMaintenanceWindowAsync("tenant1", window);
await _evaluator.AddMaintenanceWindowAsync("tenant1", window, CancellationToken.None);
// Act
var result = await _evaluator.EvaluateAsync("tenant1", "security.alert");
var result = await _evaluator.EvaluateAsync("tenant1", "security.alert", CancellationToken.None);
// Assert
Assert.False(result.IsSuppressed);
@@ -367,10 +367,10 @@ public class QuietHoursEvaluatorTests
};
// Act
await _evaluator.AddMaintenanceWindowAsync("tenant1", window);
await _evaluator.AddMaintenanceWindowAsync("tenant1", window, CancellationToken.None);
// Assert
var windows = await _evaluator.ListMaintenanceWindowsAsync("tenant1");
var windows = await _evaluator.ListMaintenanceWindowsAsync("tenant1", CancellationToken.None);
Assert.Single(windows);
Assert.Equal("maint-1", windows[0].WindowId);
}
@@ -388,13 +388,13 @@ public class QuietHoursEvaluatorTests
EndTime = now.AddHours(2)
};
await _evaluator.AddMaintenanceWindowAsync("tenant1", window);
await _evaluator.AddMaintenanceWindowAsync("tenant1", window, CancellationToken.None);
// Act
await _evaluator.RemoveMaintenanceWindowAsync("tenant1", "maint-1");
await _evaluator.RemoveMaintenanceWindowAsync("tenant1", "maint-1", CancellationToken.None);
// Assert
var windows = await _evaluator.ListMaintenanceWindowsAsync("tenant1");
var windows = await _evaluator.ListMaintenanceWindowsAsync("tenant1", CancellationToken.None);
Assert.Empty(windows);
}
@@ -419,11 +419,11 @@ public class QuietHoursEvaluatorTests
EndTime = now.AddHours(-1)
};
await _evaluator.AddMaintenanceWindowAsync("tenant1", activeWindow);
await _evaluator.AddMaintenanceWindowAsync("tenant1", expiredWindow);
await _evaluator.AddMaintenanceWindowAsync("tenant1", activeWindow, CancellationToken.None);
await _evaluator.AddMaintenanceWindowAsync("tenant1", expiredWindow, CancellationToken.None);
// Act
var windows = await _evaluator.ListMaintenanceWindowsAsync("tenant1");
var windows = await _evaluator.ListMaintenanceWindowsAsync("tenant1", CancellationToken.None);
// Assert
Assert.Single(windows);
@@ -454,10 +454,10 @@ public class QuietHoursEvaluatorTests
Description = "System upgrade"
};
await evaluator.AddMaintenanceWindowAsync("tenant1", window);
await evaluator.AddMaintenanceWindowAsync("tenant1", window, CancellationToken.None);
// Act
var result = await evaluator.EvaluateAsync("tenant1", "test.event");
var result = await evaluator.EvaluateAsync("tenant1", "test.event", CancellationToken.None);
// Assert - maintenance should take priority
Assert.True(result.IsSuppressed);

View File

@@ -28,10 +28,10 @@ public class SuppressionAuditLoggerTests
var entry = CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated);
// Act
await _logger.LogAsync(entry);
await _logger.LogAsync(entry, CancellationToken.None);
// Assert
var results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant1" });
var results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant1" }, CancellationToken.None);
Assert.Single(results);
Assert.Equal(entry.EntryId, results[0].EntryId);
}
@@ -40,7 +40,7 @@ public class SuppressionAuditLoggerTests
public async Task QueryAsync_ReturnsEmptyForUnknownTenant()
{
// Act
var results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "nonexistent" });
var results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "nonexistent" }, CancellationToken.None);
// Assert
Assert.Empty(results);
@@ -51,9 +51,9 @@ public class SuppressionAuditLoggerTests
{
// Arrange
var now = DateTimeOffset.UtcNow;
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, now.AddHours(-3)));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated, now.AddHours(-1)));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarDeleted, now));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, now.AddHours(-3)), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated, now.AddHours(-1)), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarDeleted, now), CancellationToken.None);
// Act
var results = await _logger.QueryAsync(new SuppressionAuditQuery
@@ -61,7 +61,7 @@ public class SuppressionAuditLoggerTests
TenantId = "tenant1",
From = now.AddHours(-2),
To = now.AddMinutes(-30)
});
}, CancellationToken.None);
// Assert
Assert.Single(results);
@@ -72,16 +72,16 @@ public class SuppressionAuditLoggerTests
public async Task QueryAsync_FiltersByAction()
{
// Arrange
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.ThrottleConfigUpdated));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.ThrottleConfigUpdated), CancellationToken.None);
// Act
var results = await _logger.QueryAsync(new SuppressionAuditQuery
{
TenantId = "tenant1",
Actions = [SuppressionAuditAction.CalendarCreated, SuppressionAuditAction.CalendarUpdated]
});
}, CancellationToken.None);
// Assert
Assert.Equal(2, results.Count);
@@ -92,16 +92,16 @@ public class SuppressionAuditLoggerTests
public async Task QueryAsync_FiltersByActor()
{
// Arrange
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, actor: "admin1"));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated, actor: "admin2"));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarDeleted, actor: "admin1"));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, actor: "admin1"), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated, actor: "admin2"), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarDeleted, actor: "admin1"), CancellationToken.None);
// Act
var results = await _logger.QueryAsync(new SuppressionAuditQuery
{
TenantId = "tenant1",
Actor = "admin1"
});
}, CancellationToken.None);
// Assert
Assert.Equal(2, results.Count);
@@ -112,15 +112,15 @@ public class SuppressionAuditLoggerTests
public async Task QueryAsync_FiltersByResourceType()
{
// Arrange
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, resourceType: "QuietHourCalendar"));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.ThrottleConfigUpdated, resourceType: "TenantThrottleConfig"));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, resourceType: "QuietHourCalendar"), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.ThrottleConfigUpdated, resourceType: "TenantThrottleConfig"), CancellationToken.None);
// Act
var results = await _logger.QueryAsync(new SuppressionAuditQuery
{
TenantId = "tenant1",
ResourceType = "QuietHourCalendar"
});
}, CancellationToken.None);
// Assert
Assert.Single(results);
@@ -131,15 +131,15 @@ public class SuppressionAuditLoggerTests
public async Task QueryAsync_FiltersByResourceId()
{
// Arrange
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, resourceId: "cal-123"));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated, resourceId: "cal-456"));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, resourceId: "cal-123"), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated, resourceId: "cal-456"), CancellationToken.None);
// Act
var results = await _logger.QueryAsync(new SuppressionAuditQuery
{
TenantId = "tenant1",
ResourceId = "cal-123"
});
}, CancellationToken.None);
// Assert
Assert.Single(results);
@@ -153,7 +153,7 @@ public class SuppressionAuditLoggerTests
var now = DateTimeOffset.UtcNow;
for (int i = 0; i < 10; i++)
{
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, now.AddMinutes(-i)));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, now.AddMinutes(-i)), CancellationToken.None);
}
// Act
@@ -162,14 +162,14 @@ public class SuppressionAuditLoggerTests
TenantId = "tenant1",
Limit = 3,
Offset = 0
});
}, CancellationToken.None);
var secondPage = await _logger.QueryAsync(new SuppressionAuditQuery
{
TenantId = "tenant1",
Limit = 3,
Offset = 3
});
}, CancellationToken.None);
// Assert
Assert.Equal(3, firstPage.Count);
@@ -182,12 +182,12 @@ public class SuppressionAuditLoggerTests
{
// Arrange
var now = DateTimeOffset.UtcNow;
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, now.AddHours(-2)));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated, now.AddHours(-1)));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarDeleted, now));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated, now.AddHours(-2)), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarUpdated, now.AddHours(-1)), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarDeleted, now), CancellationToken.None);
// Act
var results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant1" });
var results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant1" }, CancellationToken.None);
// Assert
Assert.Equal(3, results.Count);
@@ -207,11 +207,11 @@ public class SuppressionAuditLoggerTests
// Act - Add more entries than the limit
for (int i = 0; i < 10; i++)
{
await logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated));
await logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated), CancellationToken.None);
}
// Assert
var results = await logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant1" });
var results = await logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant1" }, CancellationToken.None);
Assert.Equal(5, results.Count);
}
@@ -219,13 +219,13 @@ public class SuppressionAuditLoggerTests
public async Task LogAsync_IsolatesTenantsCorrectly()
{
// Arrange
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated));
await _logger.LogAsync(CreateEntry("tenant2", SuppressionAuditAction.CalendarUpdated));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarDeleted));
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarCreated), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant2", SuppressionAuditAction.CalendarUpdated), CancellationToken.None);
await _logger.LogAsync(CreateEntry("tenant1", SuppressionAuditAction.CalendarDeleted), CancellationToken.None);
// Act
var tenant1Results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant1" });
var tenant2Results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant2" });
var tenant1Results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant1" }, CancellationToken.None);
var tenant2Results = await _logger.QueryAsync(new SuppressionAuditQuery { TenantId = "tenant2" }, CancellationToken.None);
// Assert
Assert.Equal(2, tenant1Results.Count);

View File

@@ -35,7 +35,7 @@ public class ThrottleConfigServiceTests
public async Task GetEffectiveConfigAsync_ReturnsGlobalDefaultsWhenNoTenantConfig()
{
// Act
var config = await _service.GetEffectiveConfigAsync("tenant1", "vulnerability.found");
var config = await _service.GetEffectiveConfigAsync("tenant1", "vulnerability.found", CancellationToken.None);
// Assert
Assert.True(config.Enabled);
@@ -56,7 +56,7 @@ public class ThrottleConfigServiceTests
};
// Act
var config = await _service.SetTenantConfigAsync("tenant1", update, "admin");
var config = await _service.SetTenantConfigAsync("tenant1", update, "admin", CancellationToken.None);
// Assert
Assert.Equal("tenant1", config.TenantId);
@@ -73,7 +73,7 @@ public class ThrottleConfigServiceTests
var update = new TenantThrottleConfigUpdate { DefaultMaxEvents = 50 };
// Act
await _service.SetTenantConfigAsync("tenant1", update, "admin");
await _service.SetTenantConfigAsync("tenant1", update, "admin", CancellationToken.None);
// Assert
_auditLogger.Verify(a => a.LogAsync(
@@ -92,10 +92,10 @@ public class ThrottleConfigServiceTests
{
DefaultWindow = TimeSpan.FromMinutes(15),
DefaultMaxEvents = 25
}, "admin");
}, "admin", CancellationToken.None);
// Act
var config = await _service.GetEffectiveConfigAsync("tenant1", "event.test");
var config = await _service.GetEffectiveConfigAsync("tenant1", "event.test", CancellationToken.None);
// Assert
Assert.Equal(TimeSpan.FromMinutes(15), config.Window);
@@ -114,7 +114,7 @@ public class ThrottleConfigServiceTests
};
// Act
var config = await _service.SetEventKindConfigAsync("tenant1", "critical.*", update, "admin");
var config = await _service.SetEventKindConfigAsync("tenant1", "critical.*", update, "admin", CancellationToken.None);
// Assert
Assert.Equal("tenant1", config.TenantId);
@@ -131,17 +131,17 @@ public class ThrottleConfigServiceTests
{
DefaultWindow = TimeSpan.FromMinutes(10),
DefaultMaxEvents = 20
}, "admin");
}, "admin", CancellationToken.None);
await _service.SetEventKindConfigAsync("tenant1", "critical.*", new EventKindThrottleConfigUpdate
{
Window = TimeSpan.FromMinutes(1),
MaxEvents = 100
}, "admin");
}, "admin", CancellationToken.None);
// Act
var criticalConfig = await _service.GetEffectiveConfigAsync("tenant1", "critical.security.breach");
var normalConfig = await _service.GetEffectiveConfigAsync("tenant1", "info.scan.complete");
var criticalConfig = await _service.GetEffectiveConfigAsync("tenant1", "critical.security.breach", CancellationToken.None);
var normalConfig = await _service.GetEffectiveConfigAsync("tenant1", "info.scan.complete", CancellationToken.None);
// Assert
Assert.Equal("event_kind", criticalConfig.Source);
@@ -162,17 +162,17 @@ public class ThrottleConfigServiceTests
{
MaxEvents = 10,
Priority = 100
}, "admin");
}, "admin", CancellationToken.None);
await _service.SetEventKindConfigAsync("tenant1", "vulnerability.critical.*", new EventKindThrottleConfigUpdate
{
MaxEvents = 5,
Priority = 50 // Higher priority (lower number)
}, "admin");
}, "admin", CancellationToken.None);
// Act
var specificConfig = await _service.GetEffectiveConfigAsync("tenant1", "vulnerability.critical.cve123");
var generalConfig = await _service.GetEffectiveConfigAsync("tenant1", "vulnerability.low.cve456");
var specificConfig = await _service.GetEffectiveConfigAsync("tenant1", "vulnerability.critical.cve123", CancellationToken.None);
var generalConfig = await _service.GetEffectiveConfigAsync("tenant1", "vulnerability.low.cve456", CancellationToken.None);
// Assert
Assert.Equal(5, specificConfig.MaxEvents);
@@ -190,15 +190,15 @@ public class ThrottleConfigServiceTests
{
Enabled = true,
DefaultMaxEvents = 20
}, "admin");
}, "admin", CancellationToken.None);
await _service.SetEventKindConfigAsync("tenant1", "info.*", new EventKindThrottleConfigUpdate
{
Enabled = false
}, "admin");
}, "admin", CancellationToken.None);
// Act
var config = await _service.GetEffectiveConfigAsync("tenant1", "info.log");
var config = await _service.GetEffectiveConfigAsync("tenant1", "info.log", CancellationToken.None);
// Assert
Assert.False(config.Enabled);
@@ -209,12 +209,12 @@ public class ThrottleConfigServiceTests
public async Task ListEventKindConfigsAsync_ReturnsAllConfigsForTenant()
{
// Arrange
await _service.SetEventKindConfigAsync("tenant1", "critical.*", new EventKindThrottleConfigUpdate { MaxEvents = 5, Priority = 10 }, "admin");
await _service.SetEventKindConfigAsync("tenant1", "info.*", new EventKindThrottleConfigUpdate { MaxEvents = 100, Priority = 100 }, "admin");
await _service.SetEventKindConfigAsync("tenant2", "other.*", new EventKindThrottleConfigUpdate { MaxEvents = 50 }, "admin");
await _service.SetEventKindConfigAsync("tenant1", "critical.*", new EventKindThrottleConfigUpdate { MaxEvents = 5, Priority = 10 }, "admin", CancellationToken.None);
await _service.SetEventKindConfigAsync("tenant1", "info.*", new EventKindThrottleConfigUpdate { MaxEvents = 100, Priority = 100 }, "admin", CancellationToken.None);
await _service.SetEventKindConfigAsync("tenant2", "other.*", new EventKindThrottleConfigUpdate { MaxEvents = 50 }, "admin", CancellationToken.None);
// Act
var configs = await _service.ListEventKindConfigsAsync("tenant1");
var configs = await _service.ListEventKindConfigsAsync("tenant1", CancellationToken.None);
// Assert
Assert.Equal(2, configs.Count);
@@ -226,14 +226,14 @@ public class ThrottleConfigServiceTests
public async Task RemoveEventKindConfigAsync_RemovesConfig()
{
// Arrange
await _service.SetEventKindConfigAsync("tenant1", "test.*", new EventKindThrottleConfigUpdate { MaxEvents = 5 }, "admin");
await _service.SetEventKindConfigAsync("tenant1", "test.*", new EventKindThrottleConfigUpdate { MaxEvents = 5 }, "admin", CancellationToken.None);
// Act
var removed = await _service.RemoveEventKindConfigAsync("tenant1", "test.*", "admin");
var removed = await _service.RemoveEventKindConfigAsync("tenant1", "test.*", "admin", CancellationToken.None);
// Assert
Assert.True(removed);
var configs = await _service.ListEventKindConfigsAsync("tenant1");
var configs = await _service.ListEventKindConfigsAsync("tenant1", CancellationToken.None);
Assert.Empty(configs);
}
@@ -241,10 +241,10 @@ public class ThrottleConfigServiceTests
public async Task RemoveEventKindConfigAsync_LogsAuditEntry()
{
// Arrange
await _service.SetEventKindConfigAsync("tenant1", "test.*", new EventKindThrottleConfigUpdate { MaxEvents = 5 }, "admin");
await _service.SetEventKindConfigAsync("tenant1", "test.*", new EventKindThrottleConfigUpdate { MaxEvents = 5 }, "admin", CancellationToken.None);
// Act
await _service.RemoveEventKindConfigAsync("tenant1", "test.*", "admin");
await _service.RemoveEventKindConfigAsync("tenant1", "test.*", "admin", CancellationToken.None);
// Assert
_auditLogger.Verify(a => a.LogAsync(
@@ -258,7 +258,7 @@ public class ThrottleConfigServiceTests
public async Task GetTenantConfigAsync_ReturnsNullWhenNotSet()
{
// Act
var config = await _service.GetTenantConfigAsync("nonexistent");
var config = await _service.GetTenantConfigAsync("nonexistent", CancellationToken.None);
// Assert
Assert.Null(config);
@@ -268,10 +268,10 @@ public class ThrottleConfigServiceTests
public async Task GetTenantConfigAsync_ReturnsConfigWhenSet()
{
// Arrange
await _service.SetTenantConfigAsync("tenant1", new TenantThrottleConfigUpdate { DefaultMaxEvents = 50 }, "admin");
await _service.SetTenantConfigAsync("tenant1", new TenantThrottleConfigUpdate { DefaultMaxEvents = 50 }, "admin", CancellationToken.None);
// Act
var config = await _service.GetTenantConfigAsync("tenant1");
var config = await _service.GetTenantConfigAsync("tenant1", CancellationToken.None);
// Assert
Assert.NotNull(config);
@@ -282,10 +282,10 @@ public class ThrottleConfigServiceTests
public async Task SetTenantConfigAsync_UpdatesExistingConfig()
{
// Arrange
await _service.SetTenantConfigAsync("tenant1", new TenantThrottleConfigUpdate { DefaultMaxEvents = 10 }, "admin1");
await _service.SetTenantConfigAsync("tenant1", new TenantThrottleConfigUpdate { DefaultMaxEvents = 10 }, "admin1", CancellationToken.None);
// Act
var updated = await _service.SetTenantConfigAsync("tenant1", new TenantThrottleConfigUpdate { DefaultMaxEvents = 20 }, "admin2");
var updated = await _service.SetTenantConfigAsync("tenant1", new TenantThrottleConfigUpdate { DefaultMaxEvents = 20 }, "admin2", CancellationToken.None);
// Assert
Assert.Equal(20, updated.DefaultMaxEvents);
@@ -300,10 +300,10 @@ public class ThrottleConfigServiceTests
{
BurstAllowance = 5,
CooldownPeriod = TimeSpan.FromMinutes(10)
}, "admin");
}, "admin", CancellationToken.None);
// Act
var config = await _service.GetEffectiveConfigAsync("tenant1", "event.test");
var config = await _service.GetEffectiveConfigAsync("tenant1", "event.test", CancellationToken.None);
// Assert
Assert.Equal(5, config.BurstAllowance);
@@ -318,10 +318,10 @@ public class ThrottleConfigServiceTests
{
MaxEvents = 1000,
Priority = 1000 // Very low priority
}, "admin");
}, "admin", CancellationToken.None);
// Act
var config = await _service.GetEffectiveConfigAsync("tenant1", "any.event.kind.here");
var config = await _service.GetEffectiveConfigAsync("tenant1", "any.event.kind.here", CancellationToken.None);
// Assert
Assert.Equal(1000, config.MaxEvents);

View File

@@ -50,7 +50,7 @@ public sealed class DigestGeneratorTests
var query = DigestQuery.LastHours(24, _timeProvider.GetUtcNow());
// Act
var result = await _generator.GenerateAsync("tenant-1", query);
var result = await _generator.GenerateAsync("tenant-1", query, CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -65,15 +65,14 @@ public sealed class DigestGeneratorTests
public async Task GenerateAsync_WithIncidents_ReturnsSummary()
{
// Arrange
var incident = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "vuln:critical:pkg-foo", "vulnerability.detected", "Critical vulnerability in pkg-foo");
await _incidentManager.RecordEventAsync("tenant-1", incident.IncidentId, "evt-1");
await _incidentManager.RecordEventAsync("tenant-1", incident.IncidentId, "evt-2");
var incident = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "vuln:critical:pkg-foo", "vulnerability.detected", "Critical vulnerability in pkg-foo", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", incident.IncidentId, "evt-1", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", incident.IncidentId, "evt-2", CancellationToken.None);
var query = DigestQuery.LastHours(24, _timeProvider.GetUtcNow());
// Act
var result = await _generator.GenerateAsync("tenant-1", query);
var result = await _generator.GenerateAsync("tenant-1", query, CancellationToken.None);
// Assert
Assert.Single(result.Incidents);
@@ -87,22 +86,19 @@ public sealed class DigestGeneratorTests
public async Task GenerateAsync_MultipleIncidents_GroupsByEventKind()
{
// Arrange
var inc1 = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "key1", "vulnerability.detected", "Vuln 1");
await _incidentManager.RecordEventAsync("tenant-1", inc1.IncidentId, "evt-1");
var inc1 = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "key1", "vulnerability.detected", "Vuln 1", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", inc1.IncidentId, "evt-1", CancellationToken.None);
var inc2 = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "key2", "vulnerability.detected", "Vuln 2");
await _incidentManager.RecordEventAsync("tenant-1", inc2.IncidentId, "evt-2");
var inc2 = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "key2", "vulnerability.detected", "Vuln 2", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", inc2.IncidentId, "evt-2", CancellationToken.None);
var inc3 = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "key3", "pack.approval.required", "Approval needed");
await _incidentManager.RecordEventAsync("tenant-1", inc3.IncidentId, "evt-3");
var inc3 = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "key3", "pack.approval.required", "Approval needed", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", inc3.IncidentId, "evt-3", CancellationToken.None);
var query = DigestQuery.LastHours(24, _timeProvider.GetUtcNow());
// Act
var result = await _generator.GenerateAsync("tenant-1", query);
var result = await _generator.GenerateAsync("tenant-1", query, CancellationToken.None);
// Assert
Assert.Equal(3, result.Incidents.Count);
@@ -117,14 +113,13 @@ public sealed class DigestGeneratorTests
public async Task GenerateAsync_RendersContent()
{
// Arrange
var incident = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "key", "vulnerability.detected", "Critical issue");
await _incidentManager.RecordEventAsync("tenant-1", incident.IncidentId, "evt-1");
var incident = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "key", "vulnerability.detected", "Critical issue", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", incident.IncidentId, "evt-1", CancellationToken.None);
var query = DigestQuery.LastHours(24, _timeProvider.GetUtcNow());
// Act
var result = await _generator.GenerateAsync("tenant-1", query);
var result = await _generator.GenerateAsync("tenant-1", query, CancellationToken.None);
// Assert
Assert.NotNull(result.Content);
@@ -145,9 +140,8 @@ public sealed class DigestGeneratorTests
// Arrange
for (var i = 0; i < 10; i++)
{
var inc = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", $"key-{i}", "test.event", $"Test incident {i}");
await _incidentManager.RecordEventAsync("tenant-1", inc.IncidentId, $"evt-{i}");
var inc = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", $"key-{i}", "test.event", $"Test incident {i}", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", inc.IncidentId, $"evt-{i}", CancellationToken.None);
}
var query = new DigestQuery
@@ -158,7 +152,7 @@ public sealed class DigestGeneratorTests
};
// Act
var result = await _generator.GenerateAsync("tenant-1", query);
var result = await _generator.GenerateAsync("tenant-1", query, CancellationToken.None);
// Assert
Assert.Equal(5, result.Incidents.Count);
@@ -170,14 +164,12 @@ public sealed class DigestGeneratorTests
public async Task GenerateAsync_FiltersResolvedIncidents()
{
// Arrange
var openInc = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "key-open", "test.event", "Open incident");
await _incidentManager.RecordEventAsync("tenant-1", openInc.IncidentId, "evt-1");
var openInc = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "key-open", "test.event", "Open incident", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", openInc.IncidentId, "evt-1", CancellationToken.None);
var resolvedInc = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "key-resolved", "test.event", "Resolved incident");
await _incidentManager.RecordEventAsync("tenant-1", resolvedInc.IncidentId, "evt-2");
await _incidentManager.ResolveAsync("tenant-1", resolvedInc.IncidentId, "system", "Auto-resolved");
var resolvedInc = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "key-resolved", "test.event", "Resolved incident", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", resolvedInc.IncidentId, "evt-2", CancellationToken.None);
await _incidentManager.ResolveAsync("tenant-1", resolvedInc.IncidentId, "system", "Auto-resolved", CancellationToken.None);
var queryExcludeResolved = new DigestQuery
{
@@ -194,8 +186,8 @@ public sealed class DigestGeneratorTests
};
// Act
var resultExclude = await _generator.GenerateAsync("tenant-1", queryExcludeResolved);
var resultInclude = await _generator.GenerateAsync("tenant-1", queryIncludeResolved);
var resultExclude = await _generator.GenerateAsync("tenant-1", queryExcludeResolved, CancellationToken.None);
var resultInclude = await _generator.GenerateAsync("tenant-1", queryIncludeResolved, CancellationToken.None);
// Assert
Assert.Single(resultExclude.Incidents);
@@ -208,13 +200,11 @@ public sealed class DigestGeneratorTests
public async Task GenerateAsync_FiltersEventKinds()
{
// Arrange
var vulnInc = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "key-vuln", "vulnerability.detected", "Vulnerability");
await _incidentManager.RecordEventAsync("tenant-1", vulnInc.IncidentId, "evt-1");
var vulnInc = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "key-vuln", "vulnerability.detected", "Vulnerability", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", vulnInc.IncidentId, "evt-1", CancellationToken.None);
var approvalInc = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "key-approval", "pack.approval.required", "Approval");
await _incidentManager.RecordEventAsync("tenant-1", approvalInc.IncidentId, "evt-2");
var approvalInc = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "key-approval", "pack.approval.required", "Approval", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", approvalInc.IncidentId, "evt-2", CancellationToken.None);
var query = new DigestQuery
{
@@ -224,7 +214,7 @@ public sealed class DigestGeneratorTests
};
// Act
var result = await _generator.GenerateAsync("tenant-1", query);
var result = await _generator.GenerateAsync("tenant-1", query, CancellationToken.None);
// Assert
Assert.Single(result.Incidents);
@@ -235,14 +225,13 @@ public sealed class DigestGeneratorTests
public async Task PreviewAsync_SetsIsPreviewFlag()
{
// Arrange
var incident = await _incidentManager.GetOrCreateIncidentAsync(
"tenant-1", "key", "test.event", "Test");
await _incidentManager.RecordEventAsync("tenant-1", incident.IncidentId, "evt-1");
var incident = await _incidentManager.GetOrCreateIncidentAsync("tenant-1", "key", "test.event", "Test", CancellationToken.None);
await _incidentManager.RecordEventAsync("tenant-1", incident.IncidentId, "evt-1", CancellationToken.None);
var query = DigestQuery.LastHours(24, _timeProvider.GetUtcNow());
// Act
var result = await _generator.PreviewAsync("tenant-1", query);
var result = await _generator.PreviewAsync("tenant-1", query, CancellationToken.None);
// Assert
Assert.True(result.IsPreview);

View File

@@ -24,7 +24,7 @@ public class InMemoryDigestSchedulerTests
var schedule = CreateTestSchedule("schedule-1");
// Act
var result = await _scheduler.UpsertScheduleAsync(schedule);
var result = await _scheduler.UpsertScheduleAsync(schedule, CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -37,12 +37,12 @@ public class InMemoryDigestSchedulerTests
{
// Arrange
var schedule = CreateTestSchedule("schedule-1");
await _scheduler.UpsertScheduleAsync(schedule);
await _scheduler.UpsertScheduleAsync(schedule, CancellationToken.None);
var updated = schedule with { Name = "Updated Name" };
// Act
var result = await _scheduler.UpsertScheduleAsync(updated);
var result = await _scheduler.UpsertScheduleAsync(updated, CancellationToken.None);
// Assert
Assert.Equal("Updated Name", result.Name);
@@ -53,10 +53,10 @@ public class InMemoryDigestSchedulerTests
{
// Arrange
var schedule = CreateTestSchedule("schedule-1");
await _scheduler.UpsertScheduleAsync(schedule);
await _scheduler.UpsertScheduleAsync(schedule, CancellationToken.None);
// Act
var result = await _scheduler.GetScheduleAsync("tenant1", "schedule-1");
var result = await _scheduler.GetScheduleAsync("tenant1", "schedule-1", CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -67,7 +67,7 @@ public class InMemoryDigestSchedulerTests
public async Task GetScheduleAsync_ReturnsNullForUnknown()
{
// Act
var result = await _scheduler.GetScheduleAsync("tenant1", "unknown");
var result = await _scheduler.GetScheduleAsync("tenant1", "unknown", CancellationToken.None);
// Assert
Assert.Null(result);
@@ -77,12 +77,12 @@ public class InMemoryDigestSchedulerTests
public async Task GetSchedulesAsync_ReturnsTenantSchedules()
{
// Arrange
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-1", "tenant1"));
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-2", "tenant1"));
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-3", "tenant2"));
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-1", "tenant1"), CancellationToken.None);
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-2", "tenant1"), CancellationToken.None);
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-3", "tenant2"), CancellationToken.None);
// Act
var result = await _scheduler.GetSchedulesAsync("tenant1");
var result = await _scheduler.GetSchedulesAsync("tenant1", CancellationToken.None);
// Assert
Assert.Equal(2, result.Count);
@@ -93,14 +93,14 @@ public class InMemoryDigestSchedulerTests
public async Task DeleteScheduleAsync_RemovesSchedule()
{
// Arrange
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-1"));
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-1"), CancellationToken.None);
// Act
var deleted = await _scheduler.DeleteScheduleAsync("tenant1", "schedule-1");
var deleted = await _scheduler.DeleteScheduleAsync("tenant1", "schedule-1", CancellationToken.None);
// Assert
Assert.True(deleted);
var result = await _scheduler.GetScheduleAsync("tenant1", "schedule-1");
var result = await _scheduler.GetScheduleAsync("tenant1", "schedule-1", CancellationToken.None);
Assert.Null(result);
}
@@ -108,7 +108,7 @@ public class InMemoryDigestSchedulerTests
public async Task DeleteScheduleAsync_ReturnsFalseForUnknown()
{
// Act
var deleted = await _scheduler.DeleteScheduleAsync("tenant1", "unknown");
var deleted = await _scheduler.DeleteScheduleAsync("tenant1", "unknown", CancellationToken.None);
// Assert
Assert.False(deleted);
@@ -122,13 +122,13 @@ public class InMemoryDigestSchedulerTests
{
CronExpression = "0 * * * * *" // Every minute
};
await _scheduler.UpsertScheduleAsync(schedule);
await _scheduler.UpsertScheduleAsync(schedule, CancellationToken.None);
// Advance time past next run
_timeProvider.Advance(TimeSpan.FromMinutes(2));
// Act
var dueSchedules = await _scheduler.GetDueSchedulesAsync(_timeProvider.GetUtcNow());
var dueSchedules = await _scheduler.GetDueSchedulesAsync(_timeProvider.GetUtcNow(), CancellationToken.None);
// Assert
Assert.Single(dueSchedules);
@@ -144,12 +144,12 @@ public class InMemoryDigestSchedulerTests
Enabled = false,
CronExpression = "0 * * * * *"
};
await _scheduler.UpsertScheduleAsync(schedule);
await _scheduler.UpsertScheduleAsync(schedule, CancellationToken.None);
_timeProvider.Advance(TimeSpan.FromMinutes(2));
// Act
var dueSchedules = await _scheduler.GetDueSchedulesAsync(_timeProvider.GetUtcNow());
var dueSchedules = await _scheduler.GetDueSchedulesAsync(_timeProvider.GetUtcNow(), CancellationToken.None);
// Assert
Assert.Empty(dueSchedules);
@@ -163,15 +163,15 @@ public class InMemoryDigestSchedulerTests
{
CronExpression = "0 0 * * * *" // Every hour
};
await _scheduler.UpsertScheduleAsync(schedule);
await _scheduler.UpsertScheduleAsync(schedule, CancellationToken.None);
var runTime = _timeProvider.GetUtcNow();
// Act
await _scheduler.UpdateLastRunAsync("tenant1", "schedule-1", runTime);
await _scheduler.UpdateLastRunAsync("tenant1", "schedule-1", runTime, CancellationToken.None);
// Assert
var updated = await _scheduler.GetScheduleAsync("tenant1", "schedule-1");
var updated = await _scheduler.GetScheduleAsync("tenant1", "schedule-1", CancellationToken.None);
Assert.NotNull(updated);
Assert.Equal(runTime, updated.LastRunAt);
Assert.NotNull(updated.NextRunAt);
@@ -189,7 +189,7 @@ public class InMemoryDigestSchedulerTests
};
// Act
var result = await _scheduler.UpsertScheduleAsync(schedule);
var result = await _scheduler.UpsertScheduleAsync(schedule, CancellationToken.None);
// Assert
Assert.NotNull(result.NextRunAt);
@@ -205,7 +205,7 @@ public class InMemoryDigestSchedulerTests
};
// Act
var result = await _scheduler.UpsertScheduleAsync(schedule);
var result = await _scheduler.UpsertScheduleAsync(schedule, CancellationToken.None);
// Assert
Assert.Null(result.NextRunAt);
@@ -215,12 +215,12 @@ public class InMemoryDigestSchedulerTests
public async Task GetSchedulesAsync_OrdersByName()
{
// Arrange
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-c") with { Name = "Charlie" });
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-a") with { Name = "Alpha" });
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-b") with { Name = "Bravo" });
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-c") with { Name = "Charlie" }, CancellationToken.None);
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-a") with { Name = "Alpha" }, CancellationToken.None);
await _scheduler.UpsertScheduleAsync(CreateTestSchedule("schedule-b") with { Name = "Bravo" }, CancellationToken.None);
// Act
var result = await _scheduler.GetSchedulesAsync("tenant1");
var result = await _scheduler.GetSchedulesAsync("tenant1", CancellationToken.None);
// Assert
Assert.Equal(3, result.Count);

View File

@@ -35,7 +35,7 @@ public sealed class SimpleTemplateRendererTests
actor: "admin@example.com",
version: "1");
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
Assert.Contains("Hello admin@example.com", result.Body);
Assert.Contains("event policy.violation occurred", result.Body);
@@ -67,7 +67,7 @@ public sealed class SimpleTemplateRendererTests
payload: payload,
version: "1");
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
Assert.Contains("Image: registry.local/api:v1.0", result.Body);
Assert.Contains("Severity: critical", result.Body);
@@ -101,7 +101,7 @@ public sealed class SimpleTemplateRendererTests
payload: payload,
version: "1");
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
Assert.Contains("Package: lodash v4.17.21", result.Body);
}
@@ -131,7 +131,7 @@ public sealed class SimpleTemplateRendererTests
payload: payload,
version: "1");
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
Assert.Contains("[REDACTED]", result.Body);
Assert.Contains("User: testuser", result.Body);
@@ -157,7 +157,7 @@ public sealed class SimpleTemplateRendererTests
payload: new JsonObject(),
version: "1");
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
Assert.Equal("Value: -end", result.Body);
}
@@ -186,7 +186,7 @@ public sealed class SimpleTemplateRendererTests
payload: payload,
version: "1");
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
Assert.Contains("alpha", result.Body);
Assert.Contains("beta", result.Body);
@@ -213,7 +213,7 @@ public sealed class SimpleTemplateRendererTests
payload: new JsonObject(),
version: "1");
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
Assert.Equal("Alert: critical.alert", result.Subject);
}
@@ -237,8 +237,8 @@ public sealed class SimpleTemplateRendererTests
payload: new JsonObject(),
version: "1");
var result1 = await _renderer.RenderAsync(template, notifyEvent);
var result2 = await _renderer.RenderAsync(template, notifyEvent);
var result1 = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
var result2 = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
Assert.Equal(result1.BodyHash, result2.BodyHash);
Assert.Equal(64, result1.BodyHash.Length); // SHA256 hex
@@ -264,7 +264,7 @@ public sealed class SimpleTemplateRendererTests
payload: new JsonObject(),
version: "1");
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
Assert.Equal(NotifyDeliveryFormat.Markdown, result.Format);
}

View File

@@ -31,7 +31,7 @@ public sealed class WebhookChannelDispatcherTests
var content = CreateContent("Test message");
var delivery = CreateDelivery();
var result = await dispatcher.DispatchAsync(channel, content, delivery);
var result = await dispatcher.DispatchAsync(channel, content, delivery, CancellationToken.None);
Assert.True(result.Success);
Assert.Equal(NotifyDeliveryStatus.Delivered, result.Status);
@@ -49,7 +49,7 @@ public sealed class WebhookChannelDispatcherTests
var content = CreateContent("Test message");
var delivery = CreateDelivery();
var result = await dispatcher.DispatchAsync(channel, content, delivery);
var result = await dispatcher.DispatchAsync(channel, content, delivery, CancellationToken.None);
Assert.False(result.Success);
Assert.Equal(NotifyDeliveryStatus.Failed, result.Status);
@@ -67,7 +67,7 @@ public sealed class WebhookChannelDispatcherTests
var content = CreateContent("Test message");
var delivery = CreateDelivery();
var result = await dispatcher.DispatchAsync(channel, content, delivery);
var result = await dispatcher.DispatchAsync(channel, content, delivery, CancellationToken.None);
Assert.False(result.Success);
Assert.Contains("Invalid webhook endpoint", result.ErrorMessage);
@@ -84,7 +84,7 @@ public sealed class WebhookChannelDispatcherTests
var content = CreateContent("Test message");
var delivery = CreateDelivery();
var result = await dispatcher.DispatchAsync(channel, content, delivery);
var result = await dispatcher.DispatchAsync(channel, content, delivery, CancellationToken.None);
Assert.False(result.Success);
Assert.Equal(NotifyDeliveryStatus.Failed, result.Status);
@@ -102,7 +102,7 @@ public sealed class WebhookChannelDispatcherTests
var content = CreateContent("Test message");
var delivery = CreateDelivery();
var result = await dispatcher.DispatchAsync(channel, content, delivery);
var result = await dispatcher.DispatchAsync(channel, content, delivery, CancellationToken.None);
Assert.False(result.Success);
Assert.True(result.IsRetryable);
@@ -120,7 +120,7 @@ public sealed class WebhookChannelDispatcherTests
var content = CreateContent("Test message");
var delivery = CreateDelivery();
var result = await dispatcher.DispatchAsync(channel, content, delivery);
var result = await dispatcher.DispatchAsync(channel, content, delivery, CancellationToken.None);
Assert.False(result.Success);
Assert.True(result.IsRetryable);
@@ -150,7 +150,7 @@ public sealed class WebhookChannelDispatcherTests
var content = CreateContent("Alert notification");
var delivery = CreateDelivery();
await dispatcher.DispatchAsync(channel, content, delivery);
await dispatcher.DispatchAsync(channel, content, delivery, CancellationToken.None);
Assert.NotNull(capturedBody);
Assert.Contains("\"text\":", capturedBody);
@@ -173,7 +173,7 @@ public sealed class WebhookChannelDispatcherTests
var content = CreateContent("Webhook content");
var delivery = CreateDelivery();
await dispatcher.DispatchAsync(channel, content, delivery);
await dispatcher.DispatchAsync(channel, content, delivery, CancellationToken.None);
Assert.NotNull(capturedBody);
Assert.Contains("\"deliveryId\":", capturedBody);

View File

@@ -46,11 +46,11 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
public async Task GetRules_ReturnsEmptyList_WhenNoRules()
{
// Act
var response = await _client.GetAsync("/api/v2/notify/rules");
var response = await _client.GetAsync("/api/v2/notify/rules", CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var rules = await response.Content.ReadFromJsonAsync<List<RuleResponse>>();
var rules = await response.Content.ReadFromJsonAsync<List<RuleResponse>>(cancellationToken: CancellationToken.None);
Assert.NotNull(rules);
Assert.Empty(rules);
}
@@ -82,11 +82,11 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
};
// Act
var response = await _client.PostAsJsonAsync("/api/v2/notify/rules", request);
var response = await _client.PostAsJsonAsync("/api/v2/notify/rules", request, cancellationToken: CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
var rule = await response.Content.ReadFromJsonAsync<RuleResponse>();
var rule = await response.Content.ReadFromJsonAsync<RuleResponse>(cancellationToken: CancellationToken.None);
Assert.NotNull(rule);
Assert.Equal("rule-001", rule.RuleId);
Assert.Equal("Test Rule", rule.Name);
@@ -108,14 +108,14 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
channel: "slack:alerts",
template: "tmpl-001")
});
await _ruleRepository.UpsertAsync(rule);
await _ruleRepository.UpsertAsync(rule, CancellationToken.None);
// Act
var response = await _client.GetAsync("/api/v2/notify/rules/rule-get-001");
var response = await _client.GetAsync("/api/v2/notify/rules/rule-get-001", CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await response.Content.ReadFromJsonAsync<RuleResponse>();
var result = await response.Content.ReadFromJsonAsync<RuleResponse>(cancellationToken: CancellationToken.None);
Assert.NotNull(result);
Assert.Equal("rule-get-001", result.RuleId);
}
@@ -124,7 +124,7 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
public async Task GetRule_ReturnsNotFound_WhenNotExists()
{
// Act
var response = await _client.GetAsync("/api/v2/notify/rules/nonexistent");
var response = await _client.GetAsync("/api/v2/notify/rules/nonexistent", CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
@@ -146,10 +146,10 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
channel: "slack:alerts",
template: "tmpl-001")
});
await _ruleRepository.UpsertAsync(rule);
await _ruleRepository.UpsertAsync(rule, CancellationToken.None);
// Act
var response = await _client.DeleteAsync("/api/v2/notify/rules/rule-delete-001");
var response = await _client.DeleteAsync("/api/v2/notify/rules/rule-delete-001", CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
@@ -163,11 +163,11 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
public async Task GetTemplates_ReturnsEmptyList_WhenNoTemplates()
{
// Act
var response = await _client.GetAsync("/api/v2/notify/templates");
var response = await _client.GetAsync("/api/v2/notify/templates", CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var templates = await response.Content.ReadFromJsonAsync<List<TemplateResponse>>();
var templates = await response.Content.ReadFromJsonAsync<List<TemplateResponse>>(cancellationToken: CancellationToken.None);
Assert.NotNull(templates);
}
@@ -182,11 +182,11 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
};
// Act
var response = await _client.PostAsJsonAsync("/api/v2/notify/templates/preview", request);
var response = await _client.PostAsJsonAsync("/api/v2/notify/templates/preview", request, cancellationToken: CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var preview = await response.Content.ReadFromJsonAsync<TemplatePreviewResponse>();
var preview = await response.Content.ReadFromJsonAsync<TemplatePreviewResponse>(cancellationToken: CancellationToken.None);
Assert.NotNull(preview);
Assert.Contains("Hello World", preview.RenderedBody);
Assert.Contains("5", preview.RenderedBody);
@@ -202,11 +202,11 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
};
// Act
var response = await _client.PostAsJsonAsync("/api/v2/notify/templates/validate", request);
var response = await _client.PostAsJsonAsync("/api/v2/notify/templates/validate", request, cancellationToken: CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await response.Content.ReadFromJsonAsync<JsonElement>();
var result = await response.Content.ReadFromJsonAsync<JsonElement>(cancellationToken: CancellationToken.None);
Assert.True(result.GetProperty("isValid").GetBoolean());
}
@@ -220,11 +220,11 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
};
// Act
var response = await _client.PostAsJsonAsync("/api/v2/notify/templates/validate", request);
var response = await _client.PostAsJsonAsync("/api/v2/notify/templates/validate", request, cancellationToken: CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await response.Content.ReadFromJsonAsync<JsonElement>();
var result = await response.Content.ReadFromJsonAsync<JsonElement>(cancellationToken: CancellationToken.None);
Assert.False(result.GetProperty("isValid").GetBoolean());
}
@@ -236,11 +236,11 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
public async Task GetIncidents_ReturnsIncidentList()
{
// Act
var response = await _client.GetAsync("/api/v2/notify/incidents");
var response = await _client.GetAsync("/api/v2/notify/incidents", CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await response.Content.ReadFromJsonAsync<IncidentListResponse>();
var result = await response.Content.ReadFromJsonAsync<IncidentListResponse>(cancellationToken: CancellationToken.None);
Assert.NotNull(result);
Assert.NotNull(result.Incidents);
}
@@ -256,7 +256,7 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
};
// Act
var response = await _client.PostAsJsonAsync("/api/v2/notify/incidents/incident-001/ack", request);
var response = await _client.PostAsJsonAsync("/api/v2/notify/incidents/incident-001/ack", request, cancellationToken: CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
@@ -273,7 +273,7 @@ public sealed class NotifyApiEndpointsTests : IClassFixture<WebApplicationFactor
var clientWithoutTenant = _factory.CreateClient();
// Act
var response = await clientWithoutTenant.GetAsync("/api/v2/notify/rules");
var response = await clientWithoutTenant.GetAsync("/api/v2/notify/rules", CancellationToken.None);
// Assert - should fail without tenant header
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);

View File

@@ -82,10 +82,10 @@ public sealed class EventProcessorTests
actor: "policy-engine",
version: "1");
var deliveriesFirst = await processor.ProcessAsync(notifyEvent, "worker-1", TestContext.Current.CancellationToken);
var deliveriesFirst = await processor.ProcessAsync(notifyEvent, "worker-1", CancellationToken.None);
var key = IdempotencyKeyBuilder.Build("tenant-a", rule.RuleId, "act-slack", notifyEvent);
var reservedAfterFirst = await lockRepository.TryAcquireAsync("tenant-a", key, "worker-verify", TimeSpan.FromMinutes(5), TestContext.Current.CancellationToken);
var deliveriesSecond = await processor.ProcessAsync(notifyEvent, "worker-1", TestContext.Current.CancellationToken);
var reservedAfterFirst = await lockRepository.TryAcquireAsync("tenant-a", key, "worker-verify", TimeSpan.FromMinutes(5), CancellationToken.None);
var deliveriesSecond = await processor.ProcessAsync(notifyEvent, "worker-1", CancellationToken.None);
Assert.Equal(1, deliveriesFirst);
Assert.False(reservedAfterFirst);
@@ -187,7 +187,7 @@ public sealed class EventProcessorTests
actor: "policy-engine",
version: "1");
var deliveries = await processor.ProcessAsync(notifyEvent, "worker-1", TestContext.Current.CancellationToken);
var deliveries = await processor.ProcessAsync(notifyEvent, "worker-1", CancellationToken.None);
Assert.Equal(1, deliveries);
@@ -259,7 +259,7 @@ public sealed class EventProcessorTests
actor: "policy-engine",
version: "1");
var deliveries = await processor.ProcessAsync(notifyEvent, "worker-1", TestContext.Current.CancellationToken);
var deliveries = await processor.ProcessAsync(notifyEvent, "worker-1", CancellationToken.None);
Assert.Equal(1, deliveries);
var record = Assert.Single(deliveryRepository.Records("tenant-a"));

View File

@@ -37,10 +37,10 @@ public class InMemoryFallbackHandlerTests
public async Task GetFallbackAsync_FirstFailure_ReturnsNextChannel()
{
// Arrange
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Connection timeout");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Connection timeout", CancellationToken.None);
// Act
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1");
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1", CancellationToken.None);
// Assert
Assert.True(result.HasFallback);
@@ -53,13 +53,13 @@ public class InMemoryFallbackHandlerTests
public async Task GetFallbackAsync_SecondFailure_ReturnsThirdChannel()
{
// Arrange
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Connection timeout");
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Connection timeout", CancellationToken.None);
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1", CancellationToken.None);
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Teams, "Rate limited");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Teams, "Rate limited", CancellationToken.None);
// Act
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Teams, "delivery1");
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Teams, "delivery1", CancellationToken.None);
// Assert
Assert.True(result.HasFallback);
@@ -71,16 +71,16 @@ public class InMemoryFallbackHandlerTests
public async Task GetFallbackAsync_AllChannelsFailed_ReturnsExhausted()
{
// Arrange - exhaust all channels (Slack -> Teams -> Email)
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed");
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed", CancellationToken.None);
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1", CancellationToken.None);
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Teams, "Failed");
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Teams, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Teams, "Failed", CancellationToken.None);
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Teams, "delivery1", CancellationToken.None);
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Email, "Failed");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Email, "Failed", CancellationToken.None);
// Act
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Email, "delivery1");
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Email, "delivery1", CancellationToken.None);
// Assert
Assert.False(result.HasFallback);
@@ -93,8 +93,8 @@ public class InMemoryFallbackHandlerTests
public async Task GetFallbackAsync_NoFallbackConfigured_ReturnsNoFallback()
{
// Act - Webhook has no fallback chain
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Webhook, "Failed");
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Webhook, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Webhook, "Failed", CancellationToken.None);
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Webhook, "delivery1", CancellationToken.None);
// Assert
Assert.False(result.HasFallback);
@@ -112,7 +112,7 @@ public class InMemoryFallbackHandlerTests
NullLogger<InMemoryFallbackHandler>.Instance);
// Act
var result = await disabledHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1");
var result = await disabledHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1", CancellationToken.None);
// Assert
Assert.False(result.HasFallback);
@@ -122,14 +122,14 @@ public class InMemoryFallbackHandlerTests
public async Task RecordSuccessAsync_MarksDeliveryAsSucceeded()
{
// Arrange
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed");
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed", CancellationToken.None);
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1", CancellationToken.None);
// Act
await _fallbackHandler.RecordSuccessAsync("tenant1", "delivery1", NotifyChannelType.Teams);
await _fallbackHandler.RecordSuccessAsync("tenant1", "delivery1", NotifyChannelType.Teams, CancellationToken.None);
// Assert
var stats = await _fallbackHandler.GetStatisticsAsync("tenant1");
var stats = await _fallbackHandler.GetStatisticsAsync("tenant1", cancellationToken: CancellationToken.None);
Assert.Equal(1, stats.FallbackSuccesses);
}
@@ -137,7 +137,7 @@ public class InMemoryFallbackHandlerTests
public async Task GetFallbackChainAsync_ReturnsDefaultChain()
{
// Act
var chain = await _fallbackHandler.GetFallbackChainAsync("tenant1", NotifyChannelType.Slack);
var chain = await _fallbackHandler.GetFallbackChainAsync("tenant1", NotifyChannelType.Slack, CancellationToken.None);
// Assert
Assert.Equal(2, chain.Count);
@@ -149,13 +149,9 @@ public class InMemoryFallbackHandlerTests
public async Task SetFallbackChainAsync_CreatesTenantSpecificChain()
{
// Act
await _fallbackHandler.SetFallbackChainAsync(
"tenant1",
NotifyChannelType.Slack,
[NotifyChannelType.Webhook, NotifyChannelType.Email],
"admin");
await _fallbackHandler.SetFallbackChainAsync("tenant1", NotifyChannelType.Slack, [NotifyChannelType.Webhook, NotifyChannelType.Email], "admin", CancellationToken.None);
var chain = await _fallbackHandler.GetFallbackChainAsync("tenant1", NotifyChannelType.Slack);
var chain = await _fallbackHandler.GetFallbackChainAsync("tenant1", NotifyChannelType.Slack, CancellationToken.None);
// Assert
Assert.Equal(2, chain.Count);
@@ -167,15 +163,11 @@ public class InMemoryFallbackHandlerTests
public async Task SetFallbackChainAsync_DoesNotAffectOtherTenants()
{
// Arrange
await _fallbackHandler.SetFallbackChainAsync(
"tenant1",
NotifyChannelType.Slack,
[NotifyChannelType.Webhook],
"admin");
await _fallbackHandler.SetFallbackChainAsync("tenant1", NotifyChannelType.Slack, [NotifyChannelType.Webhook], "admin", CancellationToken.None);
// Act
var tenant1Chain = await _fallbackHandler.GetFallbackChainAsync("tenant1", NotifyChannelType.Slack);
var tenant2Chain = await _fallbackHandler.GetFallbackChainAsync("tenant2", NotifyChannelType.Slack);
var tenant1Chain = await _fallbackHandler.GetFallbackChainAsync("tenant1", NotifyChannelType.Slack, CancellationToken.None);
var tenant2Chain = await _fallbackHandler.GetFallbackChainAsync("tenant2", NotifyChannelType.Slack, CancellationToken.None);
// Assert
Assert.Single(tenant1Chain);
@@ -190,18 +182,18 @@ public class InMemoryFallbackHandlerTests
{
// Arrange - Create various delivery scenarios
// Delivery 1: Primary success
await _fallbackHandler.RecordSuccessAsync("tenant1", "delivery1", NotifyChannelType.Slack);
await _fallbackHandler.RecordSuccessAsync("tenant1", "delivery1", NotifyChannelType.Slack, CancellationToken.None);
// Delivery 2: Fallback success
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery2", NotifyChannelType.Slack, "Failed");
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery2");
await _fallbackHandler.RecordSuccessAsync("tenant1", "delivery2", NotifyChannelType.Teams);
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery2", NotifyChannelType.Slack, "Failed", CancellationToken.None);
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery2", CancellationToken.None);
await _fallbackHandler.RecordSuccessAsync("tenant1", "delivery2", NotifyChannelType.Teams, CancellationToken.None);
// Delivery 3: Exhausted
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery3", NotifyChannelType.Webhook, "Failed");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery3", NotifyChannelType.Webhook, "Failed", CancellationToken.None);
// Act
var stats = await _fallbackHandler.GetStatisticsAsync("tenant1");
var stats = await _fallbackHandler.GetStatisticsAsync("tenant1", cancellationToken: CancellationToken.None);
// Assert
Assert.Equal("tenant1", stats.TenantId);
@@ -215,14 +207,14 @@ public class InMemoryFallbackHandlerTests
public async Task GetStatisticsAsync_FiltersWithinWindow()
{
// Arrange
await _fallbackHandler.RecordSuccessAsync("tenant1", "old-delivery", NotifyChannelType.Slack);
await _fallbackHandler.RecordSuccessAsync("tenant1", "old-delivery", NotifyChannelType.Slack, CancellationToken.None);
_timeProvider.Advance(TimeSpan.FromHours(25));
await _fallbackHandler.RecordSuccessAsync("tenant1", "recent-delivery", NotifyChannelType.Slack);
await _fallbackHandler.RecordSuccessAsync("tenant1", "recent-delivery", NotifyChannelType.Slack, CancellationToken.None);
// Act - Get stats for last 24 hours
var stats = await _fallbackHandler.GetStatisticsAsync("tenant1", TimeSpan.FromHours(24));
var stats = await _fallbackHandler.GetStatisticsAsync("tenant1", TimeSpan.FromHours(24), CancellationToken.None);
// Assert
Assert.Equal(1, stats.TotalDeliveries);
@@ -232,15 +224,15 @@ public class InMemoryFallbackHandlerTests
public async Task ClearDeliveryStateAsync_RemovesDeliveryTracking()
{
// Arrange
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed");
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed", CancellationToken.None);
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1", CancellationToken.None);
// Act
await _fallbackHandler.ClearDeliveryStateAsync("tenant1", "delivery1");
await _fallbackHandler.ClearDeliveryStateAsync("tenant1", "delivery1", CancellationToken.None);
// Get fallback again - should start fresh
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed again");
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed again", CancellationToken.None);
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1", CancellationToken.None);
// Assert - Should be back to first fallback attempt
Assert.Equal(NotifyChannelType.Teams, result.NextChannelType);
@@ -252,23 +244,19 @@ public class InMemoryFallbackHandlerTests
{
// Arrange - MaxAttempts is 3, but chain has 4 channels (Slack + 3 fallbacks would exceed)
// Add a longer chain
await _fallbackHandler.SetFallbackChainAsync(
"tenant1",
NotifyChannelType.Slack,
[NotifyChannelType.Teams, NotifyChannelType.Email, NotifyChannelType.Webhook, NotifyChannelType.Custom],
"admin");
await _fallbackHandler.SetFallbackChainAsync("tenant1", NotifyChannelType.Slack, [NotifyChannelType.Teams, NotifyChannelType.Email, NotifyChannelType.Webhook, NotifyChannelType.Custom], "admin", CancellationToken.None);
// Fail through 3 attempts (max)
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed");
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Failed", CancellationToken.None);
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1", CancellationToken.None);
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Teams, "Failed");
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Teams, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Teams, "Failed", CancellationToken.None);
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Teams, "delivery1", CancellationToken.None);
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Email, "Failed");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Email, "Failed", CancellationToken.None);
// Act - 4th attempt should be blocked by MaxAttempts
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Email, "delivery1");
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Email, "delivery1", CancellationToken.None);
// Assert
Assert.True(result.IsExhausted);
@@ -278,11 +266,11 @@ public class InMemoryFallbackHandlerTests
public async Task RecordFailureAsync_TracksMultipleFailures()
{
// Arrange & Act
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Timeout");
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Slack, "Timeout", CancellationToken.None);
await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Slack, "delivery1", CancellationToken.None);
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Teams, "Rate limited");
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Teams, "delivery1");
await _fallbackHandler.RecordFailureAsync("tenant1", "delivery1", NotifyChannelType.Teams, "Rate limited", CancellationToken.None);
var result = await _fallbackHandler.GetFallbackAsync("tenant1", NotifyChannelType.Teams, "delivery1", CancellationToken.None);
// Assert
Assert.Equal(2, result.FailedChannels.Count);
@@ -294,12 +282,12 @@ public class InMemoryFallbackHandlerTests
public async Task GetStatisticsAsync_TracksFailuresByChannel()
{
// Arrange
await _fallbackHandler.RecordFailureAsync("tenant1", "d1", NotifyChannelType.Slack, "Failed");
await _fallbackHandler.RecordFailureAsync("tenant1", "d2", NotifyChannelType.Slack, "Failed");
await _fallbackHandler.RecordFailureAsync("tenant1", "d3", NotifyChannelType.Teams, "Failed");
await _fallbackHandler.RecordFailureAsync("tenant1", "d1", NotifyChannelType.Slack, "Failed", CancellationToken.None);
await _fallbackHandler.RecordFailureAsync("tenant1", "d2", NotifyChannelType.Slack, "Failed", CancellationToken.None);
await _fallbackHandler.RecordFailureAsync("tenant1", "d3", NotifyChannelType.Teams, "Failed", CancellationToken.None);
// Act
var stats = await _fallbackHandler.GetStatisticsAsync("tenant1");
var stats = await _fallbackHandler.GetStatisticsAsync("tenant1", cancellationToken: CancellationToken.None);
// Assert
Assert.Equal(2, stats.FailuresByChannel[NotifyChannelType.Slack]);

View File

@@ -33,7 +33,7 @@ public class InMemoryLocalizationServiceTests
public async Task GetStringAsync_SystemBundle_ReturnsValue()
{
// Act - system bundles are seeded automatically
var value = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "en-US");
var value = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "en-US", CancellationToken.None);
// Assert
Assert.NotNull(value);
@@ -44,7 +44,7 @@ public class InMemoryLocalizationServiceTests
public async Task GetStringAsync_GermanLocale_ReturnsGermanValue()
{
// Act
var value = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "de-DE");
var value = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "de-DE", CancellationToken.None);
// Assert
Assert.NotNull(value);
@@ -55,7 +55,7 @@ public class InMemoryLocalizationServiceTests
public async Task GetStringAsync_FrenchLocale_ReturnsFrenchValue()
{
// Act
var value = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "fr-FR");
var value = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "fr-FR", CancellationToken.None);
// Assert
Assert.NotNull(value);
@@ -66,7 +66,7 @@ public class InMemoryLocalizationServiceTests
public async Task GetStringAsync_UnknownKey_ReturnsKey()
{
// Act
var value = await _localizationService.GetStringAsync("tenant1", "unknown.key", "en-US");
var value = await _localizationService.GetStringAsync("tenant1", "unknown.key", "en-US", CancellationToken.None);
// Assert (when ReturnKeyWhenMissing = true)
Assert.Equal("unknown.key", value);
@@ -76,7 +76,7 @@ public class InMemoryLocalizationServiceTests
public async Task GetStringAsync_LocaleFallback_UsesDefaultLocale()
{
// Act - Japanese locale (not configured) should fall back to en-US
var value = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "ja-JP");
var value = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "ja-JP", CancellationToken.None);
// Assert - should get en-US value
Assert.Equal("Notification Storm Detected", value);
@@ -92,8 +92,7 @@ public class InMemoryLocalizationServiceTests
["count"] = 50,
["window"] = "5 minutes"
};
var value = await _localizationService.GetFormattedStringAsync(
"tenant1", "storm.detected.body", "en-US", parameters);
var value = await _localizationService.GetFormattedStringAsync("tenant1", "storm.detected.body", "en-US", parameters, CancellationToken.None);
// Assert
Assert.NotNull(value);
@@ -120,7 +119,7 @@ public class InMemoryLocalizationServiceTests
};
// Act
var result = await _localizationService.UpsertBundleAsync(bundle, "admin");
var result = await _localizationService.UpsertBundleAsync(bundle, "admin", CancellationToken.None);
// Assert
Assert.True(result.Success);
@@ -128,7 +127,7 @@ public class InMemoryLocalizationServiceTests
Assert.Equal("tenant-bundle", result.BundleId);
// Verify string is accessible
var greeting = await _localizationService.GetStringAsync("tenant1", "custom.greeting", "en-US");
var greeting = await _localizationService.GetStringAsync("tenant1", "custom.greeting", "en-US", CancellationToken.None);
Assert.Equal("Hello, World!", greeting);
}
@@ -146,7 +145,7 @@ public class InMemoryLocalizationServiceTests
["test.key"] = "Original value"
}
};
await _localizationService.UpsertBundleAsync(bundle, "admin");
await _localizationService.UpsertBundleAsync(bundle, "admin", CancellationToken.None);
// Act - update with new value
var updatedBundle = bundle with
@@ -156,13 +155,13 @@ public class InMemoryLocalizationServiceTests
["test.key"] = "Updated value"
}
};
var result = await _localizationService.UpsertBundleAsync(updatedBundle, "admin");
var result = await _localizationService.UpsertBundleAsync(updatedBundle, "admin", CancellationToken.None);
// Assert
Assert.True(result.Success);
Assert.False(result.IsNew);
var value = await _localizationService.GetStringAsync("tenant1", "test.key", "en-US");
var value = await _localizationService.GetStringAsync("tenant1", "test.key", "en-US", CancellationToken.None);
Assert.Equal("Updated value", value);
}
@@ -180,15 +179,15 @@ public class InMemoryLocalizationServiceTests
["delete.key"] = "Will be deleted"
}
};
await _localizationService.UpsertBundleAsync(bundle, "admin");
await _localizationService.UpsertBundleAsync(bundle, "admin", CancellationToken.None);
// Act
var deleted = await _localizationService.DeleteBundleAsync("tenant1", "delete-test", "admin");
var deleted = await _localizationService.DeleteBundleAsync("tenant1", "delete-test", "admin", CancellationToken.None);
// Assert
Assert.True(deleted);
var bundles = await _localizationService.ListBundlesAsync("tenant1");
var bundles = await _localizationService.ListBundlesAsync("tenant1", CancellationToken.None);
Assert.DoesNotContain(bundles, b => b.BundleId == "delete-test");
}
@@ -218,12 +217,12 @@ public class InMemoryLocalizationServiceTests
Strings = new Dictionary<string, string> { ["key3"] = "value3" }
};
await _localizationService.UpsertBundleAsync(bundle1, "admin");
await _localizationService.UpsertBundleAsync(bundle2, "admin");
await _localizationService.UpsertBundleAsync(bundle3, "admin");
await _localizationService.UpsertBundleAsync(bundle1, "admin", CancellationToken.None);
await _localizationService.UpsertBundleAsync(bundle2, "admin", CancellationToken.None);
await _localizationService.UpsertBundleAsync(bundle3, "admin", CancellationToken.None);
// Act
var tenant1Bundles = await _localizationService.ListBundlesAsync("tenant1");
var tenant1Bundles = await _localizationService.ListBundlesAsync("tenant1", CancellationToken.None);
// Assert
Assert.Equal(2, tenant1Bundles.Count);
@@ -236,7 +235,7 @@ public class InMemoryLocalizationServiceTests
public async Task GetSupportedLocalesAsync_ReturnsAvailableLocales()
{
// Act
var locales = await _localizationService.GetSupportedLocalesAsync("tenant1");
var locales = await _localizationService.GetSupportedLocalesAsync("tenant1", CancellationToken.None);
// Assert - should include seeded system locales
Assert.Contains("en-US", locales);
@@ -260,10 +259,10 @@ public class InMemoryLocalizationServiceTests
["tenant.custom"] = "Custom Value"
}
};
await _localizationService.UpsertBundleAsync(tenantBundle, "admin");
await _localizationService.UpsertBundleAsync(tenantBundle, "admin", CancellationToken.None);
// Act
var bundle = await _localizationService.GetBundleAsync("tenant1", "en-US");
var bundle = await _localizationService.GetBundleAsync("tenant1", "en-US", CancellationToken.None);
// Assert - should have both system and tenant strings, with tenant override
Assert.True(bundle.ContainsKey("storm.detected.title"));
@@ -359,13 +358,13 @@ public class InMemoryLocalizationServiceTests
public async Task GetStringAsync_CachesResults()
{
// Act - first call
var value1 = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "en-US");
var value1 = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "en-US", CancellationToken.None);
// Advance time slightly (within cache duration)
_timeProvider.Advance(TimeSpan.FromMinutes(5));
// Second call should hit cache
var value2 = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "en-US");
var value2 = await _localizationService.GetStringAsync("tenant1", "storm.detected.title", "en-US", CancellationToken.None);
// Assert
Assert.Equal(value1, value2);
@@ -385,12 +384,11 @@ public class InMemoryLocalizationServiceTests
["number.test"] = "Total: {{count}} items"
}
};
await _localizationService.UpsertBundleAsync(bundle, "admin");
await _localizationService.UpsertBundleAsync(bundle, "admin", CancellationToken.None);
// Act
var parameters = new Dictionary<string, object> { ["count"] = 1234567 };
var value = await _localizationService.GetFormattedStringAsync(
"tenant1", "number.test", "de-DE", parameters);
var value = await _localizationService.GetFormattedStringAsync("tenant1", "number.test", "de-DE", parameters, CancellationToken.None);
// Assert - German number formatting uses periods as thousands separator
Assert.Contains("1.234.567", value);

View File

@@ -41,7 +41,7 @@ public class ChaosTestRunnerTests
};
// Act
var experiment = await _runner.StartExperimentAsync(config);
var experiment = await _runner.StartExperimentAsync(config, CancellationToken.None);
// Assert
Assert.NotNull(experiment);
@@ -68,7 +68,7 @@ public class ChaosTestRunnerTests
};
// Act & Assert
await Assert.ThrowsAsync<InvalidOperationException>(() => runner.StartExperimentAsync(config));
await Assert.ThrowsAsync<InvalidOperationException>(() => runner.StartExperimentAsync(config, CancellationToken.None));
}
[Fact]
@@ -84,7 +84,7 @@ public class ChaosTestRunnerTests
};
// Act & Assert
await Assert.ThrowsAsync<InvalidOperationException>(() => _runner.StartExperimentAsync(config));
await Assert.ThrowsAsync<InvalidOperationException>(() => _runner.StartExperimentAsync(config, CancellationToken.None));
}
[Fact]
@@ -98,7 +98,7 @@ public class ChaosTestRunnerTests
Name = $"Experiment {i}",
InitiatedBy = "test-user",
FaultType = ChaosFaultType.Outage
});
}, CancellationToken.None);
}
// Act & Assert
@@ -108,7 +108,7 @@ public class ChaosTestRunnerTests
Name = "One too many",
InitiatedBy = "test-user",
FaultType = ChaosFaultType.Outage
}));
}, CancellationToken.None));
}
[Fact]
@@ -120,13 +120,13 @@ public class ChaosTestRunnerTests
Name = "Test",
InitiatedBy = "test-user",
FaultType = ChaosFaultType.Outage
});
}, CancellationToken.None);
// Act
await _runner.StopExperimentAsync(experiment.Id);
await _runner.StopExperimentAsync(experiment.Id, CancellationToken.None);
// Assert
var stopped = await _runner.GetExperimentAsync(experiment.Id);
var stopped = await _runner.GetExperimentAsync(experiment.Id, CancellationToken.None);
Assert.NotNull(stopped);
Assert.Equal(ChaosExperimentStatus.Stopped, stopped.Status);
Assert.NotNull(stopped.EndedAt);
@@ -143,10 +143,10 @@ public class ChaosTestRunnerTests
TenantId = "tenant1",
TargetChannelTypes = ["email"],
FaultType = ChaosFaultType.Outage
});
}, CancellationToken.None);
// Act
var decision = await _runner.ShouldFailAsync("tenant1", "email");
var decision = await _runner.ShouldFailAsync("tenant1", "email", ct: CancellationToken.None);
// Assert
Assert.True(decision.ShouldFail);
@@ -165,10 +165,10 @@ public class ChaosTestRunnerTests
TenantId = "tenant1",
TargetChannelTypes = ["email"],
FaultType = ChaosFaultType.Outage
});
}, CancellationToken.None);
// Act - different tenant
var decision = await _runner.ShouldFailAsync("tenant2", "email");
var decision = await _runner.ShouldFailAsync("tenant2", "email", ct: CancellationToken.None);
// Assert
Assert.False(decision.ShouldFail);
@@ -185,10 +185,10 @@ public class ChaosTestRunnerTests
TenantId = "tenant1",
TargetChannelTypes = ["email"],
FaultType = ChaosFaultType.Outage
});
}, CancellationToken.None);
// Act - different channel type
var decision = await _runner.ShouldFailAsync("tenant1", "slack");
var decision = await _runner.ShouldFailAsync("tenant1", "slack", ct: CancellationToken.None);
// Assert
Assert.False(decision.ShouldFail);
@@ -210,10 +210,10 @@ public class ChaosTestRunnerTests
MinLatency = TimeSpan.FromSeconds(1),
MaxLatency = TimeSpan.FromSeconds(5)
}
});
}, CancellationToken.None);
// Act
var decision = await _runner.ShouldFailAsync("tenant1", "email");
var decision = await _runner.ShouldFailAsync("tenant1", "email", ct: CancellationToken.None);
// Assert
Assert.False(decision.ShouldFail); // Latency doesn't cause failure
@@ -237,13 +237,13 @@ public class ChaosTestRunnerTests
FailureRate = 0.5,
Seed = 42 // Fixed seed for reproducibility
}
});
}, CancellationToken.None);
// Act - run multiple times
var failures = 0;
for (var i = 0; i < 100; i++)
{
var decision = await _runner.ShouldFailAsync("tenant1", "email");
var decision = await _runner.ShouldFailAsync("tenant1", "email", ct: CancellationToken.None);
if (decision.ShouldFail) failures++;
}
@@ -266,17 +266,17 @@ public class ChaosTestRunnerTests
{
RateLimitPerMinute = 5
}
});
}, CancellationToken.None);
// Act - first 5 should pass
for (var i = 0; i < 5; i++)
{
var decision = await _runner.ShouldFailAsync("tenant1", "email");
var decision = await _runner.ShouldFailAsync("tenant1", "email", ct: CancellationToken.None);
Assert.False(decision.ShouldFail);
}
// 6th should fail
var failedDecision = await _runner.ShouldFailAsync("tenant1", "email");
var failedDecision = await _runner.ShouldFailAsync("tenant1", "email", ct: CancellationToken.None);
// Assert
Assert.True(failedDecision.ShouldFail);
@@ -295,11 +295,11 @@ public class ChaosTestRunnerTests
TargetChannelTypes = ["email"],
FaultType = ChaosFaultType.Outage,
Duration = TimeSpan.FromMinutes(5)
});
}, CancellationToken.None);
// Act - advance time past duration
_timeProvider.Advance(TimeSpan.FromMinutes(10));
var decision = await _runner.ShouldFailAsync("tenant1", "email");
var decision = await _runner.ShouldFailAsync("tenant1", "email", ct: CancellationToken.None);
// Assert
Assert.False(decision.ShouldFail);
@@ -317,17 +317,17 @@ public class ChaosTestRunnerTests
TargetChannelTypes = ["email"],
FaultType = ChaosFaultType.Outage,
MaxAffectedOperations = 3
});
}, CancellationToken.None);
// Act - consume all operations
for (var i = 0; i < 3; i++)
{
var d = await _runner.ShouldFailAsync("tenant1", "email");
var d = await _runner.ShouldFailAsync("tenant1", "email", ct: CancellationToken.None);
Assert.True(d.ShouldFail);
}
// 4th should not match
var decision = await _runner.ShouldFailAsync("tenant1", "email");
var decision = await _runner.ShouldFailAsync("tenant1", "email", ct: CancellationToken.None);
// Assert
Assert.False(decision.ShouldFail);
@@ -342,7 +342,7 @@ public class ChaosTestRunnerTests
Name = "Test",
InitiatedBy = "test-user",
FaultType = ChaosFaultType.Outage
});
}, CancellationToken.None);
// Act
await _runner.RecordOutcomeAsync(experiment.Id, new ChaosOutcome
@@ -351,9 +351,9 @@ public class ChaosTestRunnerTests
ChannelType = "email",
TenantId = "tenant1",
FallbackTriggered = true
});
}, CancellationToken.None);
var results = await _runner.GetResultsAsync(experiment.Id);
var results = await _runner.GetResultsAsync(experiment.Id, CancellationToken.None);
// Assert
Assert.Equal(1, results.TotalAffected);
@@ -370,7 +370,7 @@ public class ChaosTestRunnerTests
Name = "Test",
InitiatedBy = "test-user",
FaultType = ChaosFaultType.Latency
});
}, CancellationToken.None);
// Record various outcomes
await _runner.RecordOutcomeAsync(experiment.Id, new ChaosOutcome
@@ -378,22 +378,22 @@ public class ChaosTestRunnerTests
Type = ChaosOutcomeType.LatencyInjected,
ChannelType = "email",
Duration = TimeSpan.FromMilliseconds(100)
});
}, CancellationToken.None);
await _runner.RecordOutcomeAsync(experiment.Id, new ChaosOutcome
{
Type = ChaosOutcomeType.LatencyInjected,
ChannelType = "email",
Duration = TimeSpan.FromMilliseconds(200)
});
}, CancellationToken.None);
await _runner.RecordOutcomeAsync(experiment.Id, new ChaosOutcome
{
Type = ChaosOutcomeType.FaultInjected,
ChannelType = "slack",
FallbackTriggered = true
});
}, CancellationToken.None);
// Act
var results = await _runner.GetResultsAsync(experiment.Id);
var results = await _runner.GetResultsAsync(experiment.Id, CancellationToken.None);
// Assert
Assert.Equal(3, results.TotalAffected);
@@ -414,19 +414,19 @@ public class ChaosTestRunnerTests
Name = "Running",
InitiatedBy = "test-user",
FaultType = ChaosFaultType.Outage
});
}, CancellationToken.None);
var toStop = await _runner.StartExperimentAsync(new ChaosExperimentConfig
{
Name = "To Stop",
InitiatedBy = "test-user",
FaultType = ChaosFaultType.Outage
});
await _runner.StopExperimentAsync(toStop.Id);
}, CancellationToken.None);
await _runner.StopExperimentAsync(toStop.Id, CancellationToken.None);
// Act
var runningList = await _runner.ListExperimentsAsync(ChaosExperimentStatus.Running);
var stoppedList = await _runner.ListExperimentsAsync(ChaosExperimentStatus.Stopped);
var runningList = await _runner.ListExperimentsAsync(ChaosExperimentStatus.Running, ct: CancellationToken.None);
var stoppedList = await _runner.ListExperimentsAsync(ChaosExperimentStatus.Stopped, ct: CancellationToken.None);
// Assert
Assert.Single(runningList);
@@ -445,21 +445,21 @@ public class ChaosTestRunnerTests
InitiatedBy = "test-user",
FaultType = ChaosFaultType.Outage,
Duration = TimeSpan.FromMinutes(5)
});
}, CancellationToken.None);
// Complete the experiment
_timeProvider.Advance(TimeSpan.FromMinutes(10));
await _runner.GetExperimentAsync(experiment.Id); // Triggers status update
await _runner.GetExperimentAsync(experiment.Id, CancellationToken.None); // Triggers status update
// Advance time beyond cleanup threshold
_timeProvider.Advance(TimeSpan.FromDays(10));
// Act
var removed = await _runner.CleanupAsync(TimeSpan.FromDays(7));
var removed = await _runner.CleanupAsync(TimeSpan.FromDays(7), CancellationToken.None);
// Assert
Assert.Equal(1, removed);
var result = await _runner.GetExperimentAsync(experiment.Id);
var result = await _runner.GetExperimentAsync(experiment.Id, CancellationToken.None);
Assert.Null(result);
}
@@ -479,10 +479,10 @@ public class ChaosTestRunnerTests
ErrorStatusCode = 503,
ErrorMessage = "Service Unavailable"
}
});
}, CancellationToken.None);
// Act
var decision = await _runner.ShouldFailAsync("tenant1", "email");
var decision = await _runner.ShouldFailAsync("tenant1", "email", ct: CancellationToken.None);
// Assert
Assert.True(decision.ShouldFail);

View File

@@ -20,13 +20,13 @@ public sealed class DeadLetterHandlerTests
[Fact]
public async Task DeadLetterAsync_AddsEntryAndUpdatesStats()
{
var entry = await _handler.DeadLetterAsync("tenant1", "delivery-001", DeadLetterReason.InvalidPayload, "webhook");
var entry = await _handler.DeadLetterAsync("tenant1", "delivery-001", DeadLetterReason.InvalidPayload, "webhook", cancellationToken: CancellationToken.None);
Assert.NotNull(entry);
Assert.Equal("tenant1", entry.TenantId);
Assert.Equal(DeadLetterStatus.Pending, entry.Status);
var stats = await _handler.GetStatsAsync("tenant1");
var stats = await _handler.GetStatsAsync("tenant1", CancellationToken.None);
Assert.Equal(1, stats.PendingCount);
Assert.Equal(1, stats.TotalCount);
}
@@ -34,38 +34,38 @@ public sealed class DeadLetterHandlerTests
[Fact]
public async Task RetryAsync_TransitionsStatus()
{
var entry = await _handler.DeadLetterAsync("tenant1", "delivery-002", DeadLetterReason.ChannelUnavailable, "email");
var entry = await _handler.DeadLetterAsync("tenant1", "delivery-002", DeadLetterReason.ChannelUnavailable, "email", cancellationToken: CancellationToken.None);
var result = await _handler.RetryAsync("tenant1", entry.DeadLetterId);
var result = await _handler.RetryAsync("tenant1", entry.DeadLetterId, CancellationToken.None);
Assert.True(result.Success);
var list = await _handler.GetAsync("tenant1");
var list = await _handler.GetAsync("tenant1", cancellationToken: CancellationToken.None);
Assert.Equal(DeadLetterStatus.Retried, list.Single().Status);
}
[Fact]
public async Task DiscardAsync_RemovesFromPending()
{
var entry = await _handler.DeadLetterAsync("tenant1", "delivery-003", DeadLetterReason.ChannelUnavailable, "email");
var entry = await _handler.DeadLetterAsync("tenant1", "delivery-003", DeadLetterReason.ChannelUnavailable, "email", cancellationToken: CancellationToken.None);
var discarded = await _handler.DiscardAsync("tenant1", entry.DeadLetterId, "manual");
var discarded = await _handler.DiscardAsync("tenant1", entry.DeadLetterId, "manual", CancellationToken.None);
Assert.True(discarded);
var list = await _handler.GetAsync("tenant1");
var list = await _handler.GetAsync("tenant1", cancellationToken: CancellationToken.None);
Assert.Equal(DeadLetterStatus.Discarded, list.Single().Status);
}
[Fact]
public async Task PurgeAsync_RemovesOlderThanCutoff()
{
await _handler.DeadLetterAsync("tenant1", "delivery-004", DeadLetterReason.ChannelUnavailable, "email");
await _handler.DeadLetterAsync("tenant1", "delivery-004", DeadLetterReason.ChannelUnavailable, "email", cancellationToken: CancellationToken.None);
_timeProvider.Advance(TimeSpan.FromDays(10));
await _handler.DeadLetterAsync("tenant1", "delivery-005", DeadLetterReason.ChannelUnavailable, "email");
await _handler.DeadLetterAsync("tenant1", "delivery-005", DeadLetterReason.ChannelUnavailable, "email", cancellationToken: CancellationToken.None);
var purged = await _handler.PurgeAsync("tenant1", TimeSpan.FromDays(7));
var purged = await _handler.PurgeAsync("tenant1", TimeSpan.FromDays(7), CancellationToken.None);
Assert.Equal(1, purged);
var remaining = await _handler.GetAsync("tenant1");
var remaining = await _handler.GetAsync("tenant1", cancellationToken: CancellationToken.None);
Assert.Single(remaining);
Assert.Equal("delivery-005", remaining[0].DeliveryId);
}

View File

@@ -26,7 +26,7 @@ public class RetentionPolicyServiceTests
[Fact]
public async Task GetPolicyAsync_ReturnsDefault_WhenNoPolicySet()
{
var policy = await _service.GetPolicyAsync("tenant-default");
var policy = await _service.GetPolicyAsync("tenant-default", CancellationToken.None);
Assert.Equal(RetentionPolicy.Default.DeadLetterRetention, policy.DeadLetterRetention);
Assert.Equal(RetentionPolicy.Default.DeliveryRetention, policy.DeliveryRetention);
@@ -41,9 +41,9 @@ public class RetentionPolicyServiceTests
DeliveryRetention = TimeSpan.FromDays(45)
};
await _service.SetPolicyAsync("tenant-42", policy);
await _service.SetPolicyAsync("tenant-42", policy, CancellationToken.None);
var fetched = await _service.GetPolicyAsync("tenant-42");
var fetched = await _service.GetPolicyAsync("tenant-42", CancellationToken.None);
Assert.Equal(TimeSpan.FromDays(3), fetched.DeadLetterRetention);
Assert.Equal(TimeSpan.FromDays(45), fetched.DeliveryRetention);
}
@@ -56,9 +56,9 @@ public class RetentionPolicyServiceTests
await EnqueueDeadLetterAsync("tenant-1", "delivery-002", "event-002");
var policy = RetentionPolicy.Default with { DeadLetterRetention = TimeSpan.FromDays(1) };
await _service.SetPolicyAsync("tenant-1", policy);
await _service.SetPolicyAsync("tenant-1", policy, CancellationToken.None);
var result = await _service.ExecuteCleanupAsync("tenant-1");
var result = await _service.ExecuteCleanupAsync("tenant-1", CancellationToken.None);
Assert.True(result.Success);
Assert.Equal("tenant-1", result.TenantId);

View File

@@ -24,7 +24,7 @@ public sealed class OpenApiEndpointTests : IClassFixture<NotifierApplicationFact
[Fact]
public async Task OpenApi_endpoint_serves_yaml_with_scope_header()
{
var response = await _client.GetAsync("/.well-known/openapi", TestContext.Current.CancellationToken);
var response = await _client.GetAsync("/.well-known/openapi", CancellationToken.None);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
#endif
@@ -32,7 +32,7 @@ public sealed class OpenApiEndpointTests : IClassFixture<NotifierApplicationFact
[Fact(Explicit = true, Skip = "Pending test host wiring")]
public async Task Deprecation_headers_emitted_for_api_surface()
{
var response = await _client.GetAsync("/api/v1/notify/rules", TestContext.Current.CancellationToken);
var response = await _client.GetAsync("/api/v1/notify/rules", CancellationToken.None);
Assert.True(response.Headers.TryGetValues("Deprecation", out var depValues) &&
depValues.Contains("true"));
@@ -46,7 +46,7 @@ public sealed class OpenApiEndpointTests : IClassFixture<NotifierApplicationFact
public async Task PackApprovals_endpoint_validates_missing_headers()
{
var content = new StringContent("""{"eventId":"00000000-0000-0000-0000-000000000001","issuedAt":"2025-11-17T16:00:00Z","kind":"pack.approval.granted","packId":"offline-kit","decision":"approved","actor":"task-runner"}""", Encoding.UTF8, "application/json");
var response = await _client.PostAsync("/api/v1/notify/pack-approvals", content, TestContext.Current.CancellationToken);
var response = await _client.PostAsync("/api/v1/notify/pack-approvals", content, CancellationToken.None);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
@@ -62,7 +62,7 @@ public sealed class OpenApiEndpointTests : IClassFixture<NotifierApplicationFact
request.Headers.Add("X-StellaOps-Tenant", "tenant-a");
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await _client.SendAsync(request, TestContext.Current.CancellationToken);
var response = await _client.SendAsync(request, CancellationToken.None);
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
Assert.True(response.Headers.TryGetValues("X-Resume-After", out var resumeValues) &&
@@ -74,7 +74,7 @@ public sealed class OpenApiEndpointTests : IClassFixture<NotifierApplicationFact
public async Task PackApprovals_acknowledgement_requires_tenant_and_token()
{
var ackContent = new StringContent("""{"ackToken":"token-123"}""", Encoding.UTF8, "application/json");
var ackResponse = await _client.PostAsync("/api/v1/notify/pack-approvals/offline-kit/ack", ackContent, TestContext.Current.CancellationToken);
var ackResponse = await _client.PostAsync("/api/v1/notify/pack-approvals/offline-kit/ack", ackContent, CancellationToken.None);
Assert.Equal(HttpStatusCode.BadRequest, ackResponse.StatusCode);
var ackReq = new HttpRequestMessage(HttpMethod.Post, "/api/v1/notify/pack-approvals/offline-kit/ack")
@@ -82,7 +82,7 @@ public sealed class OpenApiEndpointTests : IClassFixture<NotifierApplicationFact
Content = ackContent
};
ackReq.Headers.Add("X-StellaOps-Tenant", "tenant-a");
var goodResponse = await _client.SendAsync(ackReq, TestContext.Current.CancellationToken);
var goodResponse = await _client.SendAsync(ackReq, CancellationToken.None);
Assert.Equal(HttpStatusCode.NoContent, goodResponse.StatusCode);
}
}

View File

@@ -23,25 +23,25 @@ public sealed class PackApprovalTemplateSeederTests
templateRepo,
contentRoot,
logger,
cancellationToken: TestContext.Current.CancellationToken);
cancellationToken: CancellationToken.None);
var routed = await PackApprovalTemplateSeeder.SeedRoutingAsync(
channelRepo,
ruleRepo,
logger,
cancellationToken: TestContext.Current.CancellationToken);
cancellationToken: CancellationToken.None);
Assert.True(count >= 2, "Expected at least two templates to be seeded.");
Assert.Equal(3, routed);
var templates = await templateRepo.ListAsync("tenant-sample", TestContext.Current.CancellationToken);
var templates = await templateRepo.ListAsync("tenant-sample", CancellationToken.None);
Assert.Contains(templates, t => t.TemplateId == "tmpl-pack-approval-slack-en");
Assert.Contains(templates, t => t.TemplateId == "tmpl-pack-approval-email-en");
var channels = await channelRepo.ListAsync("tenant-sample", cancellationToken: TestContext.Current.CancellationToken);
var channels = await channelRepo.ListAsync("tenant-sample", cancellationToken: CancellationToken.None);
Assert.Contains(channels, c => c.ChannelId == "chn-pack-approvals-slack");
Assert.Contains(channels, c => c.ChannelId == "chn-pack-approvals-email");
var rules = await ruleRepo.ListAsync("tenant-sample", TestContext.Current.CancellationToken);
var rules = await ruleRepo.ListAsync("tenant-sample", CancellationToken.None);
Assert.Contains(rules, r => r.RuleId == "rule-pack-approvals-default");
}

View File

@@ -1,4 +1,4 @@
using System.Text.Json;
using System.Text.Json;
using Xunit;
@@ -56,7 +56,6 @@ public sealed class PackApprovalTemplateTests
var path = LocatePackApprovalTemplatesPath();
var json = File.ReadAllText(path);
using var doc = JsonDocument.Parse(json);
using StellaOps.TestKit;
return doc.RootElement.Clone();
}

View File

@@ -60,7 +60,7 @@ public sealed class RiskEventEndpointTests : IClassFixture<NotifierApplicationFa
};
message.Headers.Add("X-StellaOps-Tenant", "tenant-sample");
var response = await client.SendAsync(message, TestContext.Current.CancellationToken);
var response = await client.SendAsync(message, CancellationToken.None);
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
Assert.Single(recordingQueue.Published);

View File

@@ -24,23 +24,23 @@ public sealed class RiskTemplateSeederTests
templateRepo,
contentRoot,
logger,
TestContext.Current.CancellationToken);
CancellationToken.None);
var seededRouting = await RiskTemplateSeeder.SeedRoutingAsync(
channelRepo,
ruleRepo,
contentRoot,
logger,
TestContext.Current.CancellationToken);
CancellationToken.None);
Assert.True(seededTemplates >= 4, "Expected risk templates to be seeded.");
Assert.True(seededRouting >= 0, $"Expected risk routing seed to create channels and rules but got {seededRouting}.");
var templates = await templateRepo.ListAsync("bootstrap", TestContext.Current.CancellationToken);
var templates = await templateRepo.ListAsync("bootstrap", CancellationToken.None);
Assert.Contains(templates, t => t.Key == "tmpl-risk-severity-change");
Assert.Contains(templates, t => t.Key == "tmpl-risk-profile-state");
var rules = await ruleRepo.ListAsync("bootstrap", TestContext.Current.CancellationToken);
var rules = await ruleRepo.ListAsync("bootstrap", CancellationToken.None);
Assert.Contains(rules, r => r.Match.EventKinds.Contains("risk.profile.severity.changed"));
Assert.Contains(rules, r => r.Match.EventKinds.Contains("risk.profile.published"));
}

View File

@@ -45,7 +45,7 @@ public class SigningServiceTests
};
// Act
var token = await _signingService.SignAsync(payload);
var token = await _signingService.SignAsync(payload, CancellationToken.None);
// Assert
Assert.NotNull(token);
@@ -66,10 +66,10 @@ public class SigningServiceTests
Subject = "incident-123",
ExpiresAt = _timeProvider.GetUtcNow().AddHours(24)
};
var token = await _signingService.SignAsync(payload);
var token = await _signingService.SignAsync(payload, CancellationToken.None);
// Act
var result = await _signingService.VerifyAsync(token);
var result = await _signingService.VerifyAsync(token, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -92,13 +92,13 @@ public class SigningServiceTests
Subject = "incident-123",
ExpiresAt = _timeProvider.GetUtcNow().AddHours(1)
};
var token = await _signingService.SignAsync(payload);
var token = await _signingService.SignAsync(payload, CancellationToken.None);
// Advance time past expiry
_timeProvider.Advance(TimeSpan.FromHours(2));
// Act
var result = await _signingService.VerifyAsync(token);
var result = await _signingService.VerifyAsync(token, CancellationToken.None);
// Assert
Assert.False(result.IsValid);
@@ -117,14 +117,14 @@ public class SigningServiceTests
Subject = "incident-123",
ExpiresAt = _timeProvider.GetUtcNow().AddHours(24)
};
var token = await _signingService.SignAsync(payload);
var token = await _signingService.SignAsync(payload, CancellationToken.None);
// Tamper with the token
var parts = token.Split('.');
var tamperedToken = $"{parts[0]}.{parts[1]}.tampered_signature";
// Act
var result = await _signingService.VerifyAsync(tamperedToken);
var result = await _signingService.VerifyAsync(tamperedToken, CancellationToken.None);
// Assert
Assert.False(result.IsValid);
@@ -135,7 +135,7 @@ public class SigningServiceTests
public async Task VerifyAsync_MalformedToken_ReturnsInvalidFormat()
{
// Act
var result = await _signingService.VerifyAsync("not-a-valid-token");
var result = await _signingService.VerifyAsync("not-a-valid-token", CancellationToken.None);
// Assert
Assert.False(result.IsValid);
@@ -154,7 +154,7 @@ public class SigningServiceTests
Subject = "incident-123",
ExpiresAt = _timeProvider.GetUtcNow().AddHours(24)
};
var token = await _signingService.SignAsync(payload);
var token = await _signingService.SignAsync(payload, CancellationToken.None);
// Act
var info = _signingService.GetTokenInfo(token);
@@ -180,14 +180,14 @@ public class SigningServiceTests
public async Task RotateKeyAsync_CreatesNewKey()
{
// Arrange
var keysBefore = await _keyProvider.ListKeyIdsAsync();
var keysBefore = await _keyProvider.ListKeyIdsAsync(CancellationToken.None);
// Act
var success = await _signingService.RotateKeyAsync();
var success = await _signingService.RotateKeyAsync(CancellationToken.None);
// Assert
Assert.True(success);
var keysAfter = await _keyProvider.ListKeyIdsAsync();
var keysAfter = await _keyProvider.ListKeyIdsAsync(CancellationToken.None);
Assert.True(keysAfter.Count > keysBefore.Count);
}
@@ -210,8 +210,8 @@ public class SigningServiceTests
};
// Act
var token = await _signingService.SignAsync(payload);
var result = await _signingService.VerifyAsync(token);
var token = await _signingService.SignAsync(payload, CancellationToken.None);
var result = await _signingService.VerifyAsync(token, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -233,13 +233,13 @@ public class SigningServiceTests
Subject = "incident-123",
ExpiresAt = _timeProvider.GetUtcNow().AddHours(24)
};
var token = await _signingService.SignAsync(payload);
var token = await _signingService.SignAsync(payload, CancellationToken.None);
// Rotate key
await _signingService.RotateKeyAsync();
await _signingService.RotateKeyAsync(CancellationToken.None);
// Act - verify with new current key (but old key should still be available)
var result = await _signingService.VerifyAsync(token);
var result = await _signingService.VerifyAsync(token, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -269,7 +269,7 @@ public class LocalSigningKeyProviderTests
public async Task GetCurrentKeyAsync_ReturnsKey()
{
// Act
var key = await _keyProvider.GetCurrentKeyAsync();
var key = await _keyProvider.GetCurrentKeyAsync(CancellationToken.None);
// Assert
Assert.NotNull(key);
@@ -281,10 +281,10 @@ public class LocalSigningKeyProviderTests
public async Task GetKeyByIdAsync_ExistingKey_ReturnsKey()
{
// Arrange
var currentKey = await _keyProvider.GetCurrentKeyAsync();
var currentKey = await _keyProvider.GetCurrentKeyAsync(CancellationToken.None);
// Act
var key = await _keyProvider.GetKeyByIdAsync(currentKey.KeyId);
var key = await _keyProvider.GetKeyByIdAsync(currentKey.KeyId, CancellationToken.None);
// Assert
Assert.NotNull(key);
@@ -295,7 +295,7 @@ public class LocalSigningKeyProviderTests
public async Task GetKeyByIdAsync_NonExistentKey_ReturnsNull()
{
// Act
var key = await _keyProvider.GetKeyByIdAsync("non-existent-key");
var key = await _keyProvider.GetKeyByIdAsync("non-existent-key", CancellationToken.None);
// Assert
Assert.Null(key);
@@ -305,16 +305,16 @@ public class LocalSigningKeyProviderTests
public async Task RotateAsync_CreatesNewCurrentKey()
{
// Arrange
var oldKey = await _keyProvider.GetCurrentKeyAsync();
var oldKey = await _keyProvider.GetCurrentKeyAsync(CancellationToken.None);
// Act
var newKey = await _keyProvider.RotateAsync();
var newKey = await _keyProvider.RotateAsync(CancellationToken.None);
// Assert
Assert.NotEqual(oldKey.KeyId, newKey.KeyId);
Assert.True(newKey.IsCurrent);
var currentKey = await _keyProvider.GetCurrentKeyAsync();
var currentKey = await _keyProvider.GetCurrentKeyAsync(CancellationToken.None);
Assert.Equal(newKey.KeyId, currentKey.KeyId);
}
@@ -322,13 +322,13 @@ public class LocalSigningKeyProviderTests
public async Task RotateAsync_KeepsOldKeyForVerification()
{
// Arrange
var oldKey = await _keyProvider.GetCurrentKeyAsync();
var oldKey = await _keyProvider.GetCurrentKeyAsync(CancellationToken.None);
// Act
await _keyProvider.RotateAsync();
await _keyProvider.RotateAsync(CancellationToken.None);
// Assert - old key should still be retrievable
var retrievedOldKey = await _keyProvider.GetKeyByIdAsync(oldKey.KeyId);
var retrievedOldKey = await _keyProvider.GetKeyByIdAsync(oldKey.KeyId, CancellationToken.None);
Assert.NotNull(retrievedOldKey);
Assert.False(retrievedOldKey.IsCurrent);
}
@@ -337,11 +337,11 @@ public class LocalSigningKeyProviderTests
public async Task ListKeyIdsAsync_ReturnsAllKeys()
{
// Arrange
await _keyProvider.RotateAsync();
await _keyProvider.RotateAsync();
await _keyProvider.RotateAsync(CancellationToken.None);
await _keyProvider.RotateAsync(CancellationToken.None);
// Act
var keyIds = await _keyProvider.ListKeyIdsAsync();
var keyIds = await _keyProvider.ListKeyIdsAsync(CancellationToken.None);
// Assert
Assert.Equal(3, keyIds.Count); // Initial + 2 rotations

View File

@@ -33,11 +33,10 @@ public class TenantIsolationValidatorTests
public async Task ValidateResourceAccessAsync_SameTenant_Allowed()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
// Act
var result = await _validator.ValidateResourceAccessAsync(
"tenant1", "delivery", "delivery-001", TenantAccessOperation.Read);
var result = await _validator.ValidateResourceAccessAsync("tenant1", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -48,11 +47,10 @@ public class TenantIsolationValidatorTests
public async Task ValidateResourceAccessAsync_DifferentTenant_Denied()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
// Act
var result = await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Read);
var result = await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
// Assert
Assert.False(result.IsAllowed);
@@ -63,11 +61,10 @@ public class TenantIsolationValidatorTests
public async Task ValidateResourceAccessAsync_AdminTenant_AlwaysAllowed()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
// Act
var result = await _validator.ValidateResourceAccessAsync(
"admin", "delivery", "delivery-001", TenantAccessOperation.Read);
var result = await _validator.ValidateResourceAccessAsync("admin", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -78,11 +75,10 @@ public class TenantIsolationValidatorTests
public async Task ValidateResourceAccessAsync_SystemResource_AlwaysAllowed()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "system-template", "template-001");
await _validator.RegisterResourceAsync("tenant1", "system-template", "template-001", CancellationToken.None);
// Act
var result = await _validator.ValidateResourceAccessAsync(
"tenant2", "system-template", "template-001", TenantAccessOperation.Read);
var result = await _validator.ValidateResourceAccessAsync("tenant2", "system-template", "template-001", TenantAccessOperation.Read, CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -93,8 +89,7 @@ public class TenantIsolationValidatorTests
public async Task ValidateResourceAccessAsync_UnregisteredResource_Allowed()
{
// Act - resource not registered
var result = await _validator.ValidateResourceAccessAsync(
"tenant1", "delivery", "unregistered-delivery", TenantAccessOperation.Read);
var result = await _validator.ValidateResourceAccessAsync("tenant1", "delivery", "unregistered-delivery", TenantAccessOperation.Read, CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -105,10 +100,10 @@ public class TenantIsolationValidatorTests
public async Task ValidateDeliveryAsync_SameTenant_Allowed()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
// Act
var result = await _validator.ValidateDeliveryAsync("tenant1", "delivery-001");
var result = await _validator.ValidateDeliveryAsync("tenant1", "delivery-001", CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -118,10 +113,10 @@ public class TenantIsolationValidatorTests
public async Task ValidateChannelAsync_SameTenant_Allowed()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "channel", "channel-001");
await _validator.RegisterResourceAsync("tenant1", "channel", "channel-001", CancellationToken.None);
// Act
var result = await _validator.ValidateChannelAsync("tenant1", "channel-001");
var result = await _validator.ValidateChannelAsync("tenant1", "channel-001", CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -131,10 +126,10 @@ public class TenantIsolationValidatorTests
public async Task ValidateTemplateAsync_SameTenant_Allowed()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "template", "template-001");
await _validator.RegisterResourceAsync("tenant1", "template", "template-001", CancellationToken.None);
// Act
var result = await _validator.ValidateTemplateAsync("tenant1", "template-001");
var result = await _validator.ValidateTemplateAsync("tenant1", "template-001", CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -144,10 +139,10 @@ public class TenantIsolationValidatorTests
public async Task ValidateSubscriptionAsync_SameTenant_Allowed()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "subscription", "subscription-001");
await _validator.RegisterResourceAsync("tenant1", "subscription", "subscription-001", CancellationToken.None);
// Act
var result = await _validator.ValidateSubscriptionAsync("tenant1", "subscription-001");
var result = await _validator.ValidateSubscriptionAsync("tenant1", "subscription-001", CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -157,15 +152,12 @@ public class TenantIsolationValidatorTests
public async Task GrantCrossTenantAccessAsync_EnablesAccess()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
// Act
await _validator.GrantCrossTenantAccessAsync(
"tenant1", "tenant2", "delivery", "delivery-001",
TenantAccessOperation.Read, null, "admin");
await _validator.GrantCrossTenantAccessAsync("tenant1", "tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, null, "admin", CancellationToken.None);
var result = await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Read);
var result = await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -177,17 +169,13 @@ public class TenantIsolationValidatorTests
public async Task RevokeCrossTenantAccessAsync_DisablesAccess()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.GrantCrossTenantAccessAsync(
"tenant1", "tenant2", "delivery", "delivery-001",
TenantAccessOperation.Read, null, "admin");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
await _validator.GrantCrossTenantAccessAsync("tenant1", "tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, null, "admin", CancellationToken.None);
// Act
await _validator.RevokeCrossTenantAccessAsync(
"tenant1", "tenant2", "delivery", "delivery-001", "admin");
await _validator.RevokeCrossTenantAccessAsync("tenant1", "tenant2", "delivery", "delivery-001", "admin", CancellationToken.None);
var result = await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Read);
var result = await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
// Assert
Assert.False(result.IsAllowed);
@@ -197,24 +185,20 @@ public class TenantIsolationValidatorTests
public async Task GrantCrossTenantAccessAsync_WithExpiry_ExpiresCorrectly()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
var expiresAt = _timeProvider.GetUtcNow().AddHours(1);
await _validator.GrantCrossTenantAccessAsync(
"tenant1", "tenant2", "delivery", "delivery-001",
TenantAccessOperation.Read, expiresAt, "admin");
await _validator.GrantCrossTenantAccessAsync("tenant1", "tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, expiresAt, "admin", CancellationToken.None);
// Verify access before expiry
var resultBefore = await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Read);
var resultBefore = await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
Assert.True(resultBefore.IsAllowed);
// Advance time past expiry
_timeProvider.Advance(TimeSpan.FromHours(2));
// Act
var resultAfter = await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Read);
var resultAfter = await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
// Assert
Assert.False(resultAfter.IsAllowed);
@@ -224,18 +208,14 @@ public class TenantIsolationValidatorTests
public async Task GrantCrossTenantAccessAsync_OperationRestrictions_Enforced()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.GrantCrossTenantAccessAsync(
"tenant1", "tenant2", "delivery", "delivery-001",
TenantAccessOperation.Read, null, "admin");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
await _validator.GrantCrossTenantAccessAsync("tenant1", "tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, null, "admin", CancellationToken.None);
// Act - Read should be allowed
var readResult = await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Read);
var readResult = await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
// Write should be denied (not in granted operations)
var writeResult = await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Write);
var writeResult = await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Write, CancellationToken.None);
// Assert
Assert.True(readResult.IsAllowed);
@@ -246,14 +226,13 @@ public class TenantIsolationValidatorTests
public async Task GetViolationsAsync_ReturnsRecordedViolations()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
// Trigger a violation
await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Read);
await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
// Act
var violations = await _validator.GetViolationsAsync("tenant2");
var violations = await _validator.GetViolationsAsync("tenant2", cancellationToken: CancellationToken.None);
// Assert
Assert.Single(violations);
@@ -265,19 +244,17 @@ public class TenantIsolationValidatorTests
public async Task GetViolationsAsync_FiltersBySince()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Read);
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
_timeProvider.Advance(TimeSpan.FromHours(2));
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-002");
await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-002", TenantAccessOperation.Read);
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-002", CancellationToken.None);
await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-002", TenantAccessOperation.Read, CancellationToken.None);
// Act
var since = _timeProvider.GetUtcNow().AddHours(-1);
var violations = await _validator.GetViolationsAsync(null, since);
var violations = await _validator.GetViolationsAsync(null, since, CancellationToken.None);
// Assert
Assert.Single(violations);
@@ -288,8 +265,8 @@ public class TenantIsolationValidatorTests
public async Task RegisterResourceAsync_AddsResource()
{
// Act
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
var resources = await _validator.GetTenantResourcesAsync("tenant1");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
var resources = await _validator.GetTenantResourcesAsync("tenant1", cancellationToken: CancellationToken.None);
// Assert
Assert.Single(resources);
@@ -302,11 +279,11 @@ public class TenantIsolationValidatorTests
public async Task UnregisterResourceAsync_RemovesResource()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
// Act
await _validator.UnregisterResourceAsync("delivery", "delivery-001");
var resources = await _validator.GetTenantResourcesAsync("tenant1");
await _validator.UnregisterResourceAsync("delivery", "delivery-001", CancellationToken.None);
var resources = await _validator.GetTenantResourcesAsync("tenant1", cancellationToken: CancellationToken.None);
// Assert
Assert.Empty(resources);
@@ -316,11 +293,11 @@ public class TenantIsolationValidatorTests
public async Task GetTenantResourcesAsync_FiltersByResourceType()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "channel", "channel-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
await _validator.RegisterResourceAsync("tenant1", "channel", "channel-001", CancellationToken.None);
// Act
var deliveries = await _validator.GetTenantResourcesAsync("tenant1", "delivery");
var deliveries = await _validator.GetTenantResourcesAsync("tenant1", "delivery", CancellationToken.None);
// Assert
Assert.Single(deliveries);
@@ -342,7 +319,7 @@ public class TenantIsolationValidatorTests
};
// Act
var result = await _validator.RunFuzzTestAsync(config);
var result = await _validator.RunFuzzTestAsync(config, CancellationToken.None);
// Assert
Assert.True(result.AllPassed);
@@ -355,8 +332,7 @@ public class TenantIsolationValidatorTests
public async Task ValidateCrossTenantAccessAsync_SameTenant_Allowed()
{
// Act
var result = await _validator.ValidateCrossTenantAccessAsync(
"tenant1", "tenant1", "delivery", "delivery-001");
var result = await _validator.ValidateCrossTenantAccessAsync("tenant1", "tenant1", "delivery", "delivery-001", CancellationToken.None);
// Assert
Assert.True(result.IsAllowed);
@@ -367,18 +343,16 @@ public class TenantIsolationValidatorTests
public async Task ViolationSeverity_ReflectsOperation()
{
// Arrange
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001");
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-001", CancellationToken.None);
// Trigger different violations
await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-001", TenantAccessOperation.Read);
await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-001", TenantAccessOperation.Read, CancellationToken.None);
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-002");
await _validator.ValidateResourceAccessAsync(
"tenant2", "delivery", "delivery-002", TenantAccessOperation.Delete);
await _validator.RegisterResourceAsync("tenant1", "delivery", "delivery-002", CancellationToken.None);
await _validator.ValidateResourceAccessAsync("tenant2", "delivery", "delivery-002", TenantAccessOperation.Delete, CancellationToken.None);
// Act
var violations = await _validator.GetViolationsAsync("tenant2");
var violations = await _validator.GetViolationsAsync("tenant2", cancellationToken: CancellationToken.None);
// Assert
var readViolation = violations.FirstOrDefault(v => v.ResourceId == "delivery-001");

View File

@@ -38,7 +38,7 @@ public class WebhookSecurityServiceTests
};
// Act
var result = await _webhookService.ValidateAsync(request);
var result = await _webhookService.ValidateAsync(request, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -58,7 +58,7 @@ public class WebhookSecurityServiceTests
Algorithm = "SHA256",
RequireSignature = true
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
var body = "{\"test\": \"data\"}";
var signature = _webhookService.GenerateSignature(body, config.SecretKey);
@@ -72,7 +72,7 @@ public class WebhookSecurityServiceTests
};
// Act
var result = await _webhookService.ValidateAsync(request);
var result = await _webhookService.ValidateAsync(request, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -91,7 +91,7 @@ public class WebhookSecurityServiceTests
SecretKey = "test-secret-key",
RequireSignature = true
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
var request = new WebhookValidationRequest
{
@@ -102,7 +102,7 @@ public class WebhookSecurityServiceTests
};
// Act
var result = await _webhookService.ValidateAsync(request);
var result = await _webhookService.ValidateAsync(request, CancellationToken.None);
// Assert
Assert.False(result.IsValid);
@@ -121,7 +121,7 @@ public class WebhookSecurityServiceTests
SecretKey = "test-secret-key",
RequireSignature = true
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
var request = new WebhookValidationRequest
{
@@ -131,7 +131,7 @@ public class WebhookSecurityServiceTests
};
// Act
var result = await _webhookService.ValidateAsync(request);
var result = await _webhookService.ValidateAsync(request, CancellationToken.None);
// Assert
Assert.False(result.IsValid);
@@ -152,7 +152,7 @@ public class WebhookSecurityServiceTests
EnforceIpAllowlist = true,
AllowedIps = ["192.168.1.0/24"]
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
var request = new WebhookValidationRequest
{
@@ -163,7 +163,7 @@ public class WebhookSecurityServiceTests
};
// Act
var result = await _webhookService.ValidateAsync(request);
var result = await _webhookService.ValidateAsync(request, CancellationToken.None);
// Assert
Assert.False(result.IsValid);
@@ -184,7 +184,7 @@ public class WebhookSecurityServiceTests
EnforceIpAllowlist = true,
AllowedIps = ["192.168.1.0/24"]
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
var request = new WebhookValidationRequest
{
@@ -195,7 +195,7 @@ public class WebhookSecurityServiceTests
};
// Act
var result = await _webhookService.ValidateAsync(request);
var result = await _webhookService.ValidateAsync(request, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -215,7 +215,7 @@ public class WebhookSecurityServiceTests
RequireSignature = false,
MaxRequestAge = TimeSpan.FromMinutes(5)
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
var request = new WebhookValidationRequest
{
@@ -226,7 +226,7 @@ public class WebhookSecurityServiceTests
};
// Act
var result = await _webhookService.ValidateAsync(request);
var result = await _webhookService.ValidateAsync(request, CancellationToken.None);
// Assert
Assert.False(result.IsValid);
@@ -245,7 +245,7 @@ public class WebhookSecurityServiceTests
SecretKey = "test-secret-key",
RequireSignature = true
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
var body = "{\"test\": \"data\"}";
var signature = _webhookService.GenerateSignature(body, config.SecretKey);
@@ -260,11 +260,11 @@ public class WebhookSecurityServiceTests
};
// First request should succeed
var result1 = await _webhookService.ValidateAsync(request);
var result1 = await _webhookService.ValidateAsync(request, CancellationToken.None);
Assert.True(result1.IsValid);
// Act - second request with same signature should fail
var result2 = await _webhookService.ValidateAsync(request);
var result2 = await _webhookService.ValidateAsync(request, CancellationToken.None);
// Assert
Assert.False(result2.IsValid);
@@ -299,14 +299,13 @@ public class WebhookSecurityServiceTests
EnforceIpAllowlist = true,
AllowedIps = ["192.168.1.0/24"]
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
// Act
await _webhookService.UpdateAllowlistAsync(
"tenant1", "channel1", ["10.0.0.0/8"], "admin");
await _webhookService.UpdateAllowlistAsync("tenant1", "channel1", ["10.0.0.0/8"], "admin", CancellationToken.None);
// Assert
var updatedConfig = await _webhookService.GetConfigAsync("tenant1", "channel1");
var updatedConfig = await _webhookService.GetConfigAsync("tenant1", "channel1", CancellationToken.None);
Assert.NotNull(updatedConfig);
Assert.Single(updatedConfig.AllowedIps);
Assert.Equal("10.0.0.0/8", updatedConfig.AllowedIps[0]);
@@ -316,7 +315,7 @@ public class WebhookSecurityServiceTests
public async Task IsIpAllowedAsync_NoConfig_ReturnsTrue()
{
// Act
var allowed = await _webhookService.IsIpAllowedAsync("tenant1", "channel1", "192.168.1.1");
var allowed = await _webhookService.IsIpAllowedAsync("tenant1", "channel1", "192.168.1.1", CancellationToken.None);
// Assert
Assert.True(allowed);
@@ -335,10 +334,10 @@ public class WebhookSecurityServiceTests
EnforceIpAllowlist = true,
AllowedIps = ["192.168.1.0/24"]
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
// Act
var allowed = await _webhookService.IsIpAllowedAsync("tenant1", "channel1", "192.168.1.50");
var allowed = await _webhookService.IsIpAllowedAsync("tenant1", "channel1", "192.168.1.50", CancellationToken.None);
// Assert
Assert.True(allowed);
@@ -357,10 +356,10 @@ public class WebhookSecurityServiceTests
EnforceIpAllowlist = true,
AllowedIps = ["192.168.1.100"]
};
await _webhookService.RegisterWebhookAsync(config);
await _webhookService.RegisterWebhookAsync(config, CancellationToken.None);
// Act
var allowed = await _webhookService.IsIpAllowedAsync("tenant1", "channel1", "192.168.1.100");
var allowed = await _webhookService.IsIpAllowedAsync("tenant1", "channel1", "192.168.1.100", CancellationToken.None);
// Assert
Assert.True(allowed);

View File

@@ -64,7 +64,7 @@ public class SimulationEngineTests
};
// Act
var result = await _engine.SimulateAsync(request);
var result = await _engine.SimulateAsync(request, CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -98,7 +98,7 @@ public class SimulationEngineTests
};
// Act
var result = await _engine.SimulateAsync(request);
var result = await _engine.SimulateAsync(request, CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -130,14 +130,15 @@ public class SimulationEngineTests
};
// Act
var result = await _engine.SimulateAsync(request);
var result = await _engine.SimulateAsync(request, CancellationToken.None);
// Assert
Assert.NotNull(result);
Assert.Single(result.EventResults);
Assert.NotNull(result.EventResults[0].NonMatchedRules);
Assert.Single(result.EventResults[0].NonMatchedRules);
Assert.Equal("severity_below_threshold", result.EventResults[0].NonMatchedRules[0].Reason);
var nonMatchedRules = result.EventResults[0].NonMatchedRules!;
Assert.Single(nonMatchedRules);
Assert.Equal("severity_below_threshold", nonMatchedRules[0].Reason);
}
[Fact]
@@ -164,7 +165,7 @@ public class SimulationEngineTests
};
// Act
var result = await _engine.SimulateAsync(request);
var result = await _engine.SimulateAsync(request, CancellationToken.None);
// Assert
Assert.Equal(2, result.TotalRules);
@@ -188,7 +189,7 @@ public class SimulationEngineTests
};
// Act
var result = await _engine.SimulateAsync(request);
var result = await _engine.SimulateAsync(request, CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -213,7 +214,7 @@ public class SimulationEngineTests
};
// Act
var result = await _engine.SimulateAsync(request);
var result = await _engine.SimulateAsync(request, CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -264,7 +265,7 @@ public class SimulationEngineTests
};
// Act
var result = await _engine.SimulateAsync(request);
var result = await _engine.SimulateAsync(request, CancellationToken.None);
// Assert
Assert.Equal(2, result.RuleSummaries.Count);
@@ -305,7 +306,7 @@ public class SimulationEngineTests
};
// Act
var result = await _engine.SimulateAsync(request);
var result = await _engine.SimulateAsync(request, CancellationToken.None);
// Assert
Assert.Equal(1, result.TotalRules);
@@ -318,7 +319,7 @@ public class SimulationEngineTests
var rule = CreateTestRule("valid-rule");
// Act
var result = await _engine.ValidateRuleAsync(rule);
var result = await _engine.ValidateRuleAsync(rule, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -338,7 +339,7 @@ public class SimulationEngineTests
enabled: true);
// Act
var result = await _engine.ValidateRuleAsync(rule);
var result = await _engine.ValidateRuleAsync(rule, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -352,7 +353,7 @@ public class SimulationEngineTests
var rule = CreateTestRule("disabled-rule", enabled: false);
// Act
var result = await _engine.ValidateRuleAsync(rule);
var result = await _engine.ValidateRuleAsync(rule, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -372,7 +373,7 @@ public class SimulationEngineTests
enabled: true);
// Act
var result = await _engine.ValidateRuleAsync(rule);
var result = await _engine.ValidateRuleAsync(rule, CancellationToken.None);
// Assert
Assert.True(result.IsValid);
@@ -392,7 +393,7 @@ public class SimulationEngineTests
enabled: true);
// Act
var result = await _engine.ValidateRuleAsync(rule);
var result = await _engine.ValidateRuleAsync(rule, CancellationToken.None);
// Assert
Assert.True(result.IsValid);

View File

@@ -1,27 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<UseXunitV3>true</UseXunitV3>
<OutputType>Exe</OutputType>
<IsPackable>false</IsPackable>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseConcelierTestInfra>false</UseConcelierTestInfra>
<LangVersion>preview</LangVersion>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" Version="10.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="FluentAssertions" Version="7.0.0" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit.v3" Version="3.0.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3" />
</ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Options" />
<PackageReference Include="FluentAssertions" />
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" />
<PackageReference Include="Moq" />
<PackageReference Include="xunit.v3" />
</ItemGroup>
<ItemGroup>
<Compile Remove="OpenApiEndpointTests.cs" />
@@ -41,4 +38,4 @@
<ProjectReference Include="..\..\..\Notify\__Libraries\StellaOps.Notify.Queue\StellaOps.Notify.Queue.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.TestKit/StellaOps.TestKit.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@@ -34,7 +34,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("pack.approval", "test-user");
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.Contains("Hello test-user", result.Body);
@@ -57,7 +57,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("pack.approval", "user", payload);
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.Equal("Pack pkg-001 version 1.2.3", result.Body);
@@ -75,7 +75,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("test.event", "user", payload);
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.Equal("Items: [a][b][c]", result.Body);
@@ -97,7 +97,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("scan.complete", "scanner", payload);
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.Equal("CVE-001: high CVE-002: low ", result.Body);
@@ -124,7 +124,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("test.event", "user", payload);
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.Contains("[REDACTED]", result.Body);
@@ -153,7 +153,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("test.event", "user", payload);
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.Contains("Name: John", result.Body);
@@ -168,7 +168,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("test.event", "user");
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.Contains("https://stellaops.local/notify/events/", result.Body);
@@ -183,7 +183,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("test.event", "user", payload);
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.Contains("Upper: TEST", result.Body);
@@ -199,7 +199,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("test.event", "user", payload);
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.DoesNotContain("<script>", result.Body);
@@ -218,7 +218,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("security.alert", "scanner");
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.NotNull(result.Subject);
@@ -234,8 +234,8 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("test.event", "user");
// Act
var result1 = await _renderer.RenderAsync(template, notifyEvent);
var result2 = await _renderer.RenderAsync(template, notifyEvent);
var result1 = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
var result2 = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.NotNull(result1.BodyHash);
@@ -260,7 +260,7 @@ public sealed class EnhancedTemplateRendererTests
var notifyEvent = CreateEvent("test.event", "user");
// Act
var result = await _renderer.RenderAsync(template, notifyEvent);
var result = await _renderer.RenderAsync(template, notifyEvent, CancellationToken.None);
// Assert
Assert.Contains("<h1>", result.Body);
@@ -279,8 +279,8 @@ public sealed class EnhancedTemplateRendererTests
var eventFalse = CreateEvent("test", "user", payloadFalse);
// Act
var resultTrue = await _renderer.RenderAsync(template, eventTrue);
var resultFalse = await _renderer.RenderAsync(template, eventFalse);
var resultTrue = await _renderer.RenderAsync(template, eventTrue, CancellationToken.None);
var resultFalse = await _renderer.RenderAsync(template, eventFalse, CancellationToken.None);
// Assert
Assert.Contains("CRITICAL:", resultTrue.Body);

View File

@@ -27,11 +27,10 @@ public sealed class NotifyTemplateServiceTests
{
// Arrange
var template = CreateTemplate("tmpl-001", "pack.approval", "en-us");
await _templateRepository.UpsertAsync(template);
await _templateRepository.UpsertAsync(template, CancellationToken.None);
// Act
var result = await _service.ResolveAsync(
"test-tenant", "pack.approval", NotifyChannelType.Webhook, "en-US");
var result = await _service.ResolveAsync("test-tenant", "pack.approval", NotifyChannelType.Webhook, "en-US", CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -43,11 +42,10 @@ public sealed class NotifyTemplateServiceTests
{
// Arrange
var template = CreateTemplate("tmpl-en", "pack.approval", "en");
await _templateRepository.UpsertAsync(template);
await _templateRepository.UpsertAsync(template, CancellationToken.None);
// Act - request en-GB but only en exists
var result = await _service.ResolveAsync(
"test-tenant", "pack.approval", NotifyChannelType.Webhook, "en-GB");
var result = await _service.ResolveAsync("test-tenant", "pack.approval", NotifyChannelType.Webhook, "en-GB", CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -59,11 +57,10 @@ public sealed class NotifyTemplateServiceTests
{
// Arrange
var template = CreateTemplate("tmpl-default", "pack.approval", "en-us");
await _templateRepository.UpsertAsync(template);
await _templateRepository.UpsertAsync(template, CancellationToken.None);
// Act - request de-DE but only en-us exists (default)
var result = await _service.ResolveAsync(
"test-tenant", "pack.approval", NotifyChannelType.Webhook, "de-DE");
var result = await _service.ResolveAsync("test-tenant", "pack.approval", NotifyChannelType.Webhook, "de-DE", CancellationToken.None);
// Assert
Assert.NotNull(result);
@@ -74,8 +71,7 @@ public sealed class NotifyTemplateServiceTests
public async Task ResolveAsync_NoMatch_ReturnsNull()
{
// Act
var result = await _service.ResolveAsync(
"test-tenant", "nonexistent.key", NotifyChannelType.Webhook, "en-US");
var result = await _service.ResolveAsync("test-tenant", "nonexistent.key", NotifyChannelType.Webhook, "en-US", CancellationToken.None);
// Assert
Assert.Null(result);
@@ -88,7 +84,7 @@ public sealed class NotifyTemplateServiceTests
var template = CreateTemplate("tmpl-new", "pack.approval", "en-us");
// Act
var result = await _service.UpsertAsync(template, "test-actor");
var result = await _service.UpsertAsync(template, "test-actor", CancellationToken.None);
// Assert
Assert.True(result.Success);
@@ -112,12 +108,12 @@ public sealed class NotifyTemplateServiceTests
NullLogger<NotifyTemplateService>.Instance);
var original = CreateTemplate("tmpl-existing", "pack.approval", "en-us", "Original body");
await templateRepository.UpsertAsync(original);
await templateRepository.UpsertAsync(original, CancellationToken.None);
var updated = CreateTemplate("tmpl-existing", "pack.approval", "en-us", "Updated body");
// Act
var result = await service.UpsertAsync(updated, "another-actor");
var result = await service.UpsertAsync(updated, "another-actor", CancellationToken.None);
// Assert
Assert.True(result.Success);
@@ -141,7 +137,7 @@ public sealed class NotifyTemplateServiceTests
body: "Hello {{name} - missing closing brace");
// Act
var result = await _service.UpsertAsync(template, "test-actor");
var result = await _service.UpsertAsync(template, "test-actor", CancellationToken.None);
// Assert
Assert.False(result.Success);
@@ -153,14 +149,14 @@ public sealed class NotifyTemplateServiceTests
{
// Arrange
var template = CreateTemplate("tmpl-delete", "pack.approval", "en-us");
await _templateRepository.UpsertAsync(template);
await _templateRepository.UpsertAsync(template, CancellationToken.None);
// Act
var deleted = await _service.DeleteAsync("test-tenant", "tmpl-delete", "delete-actor");
var deleted = await _service.DeleteAsync("test-tenant", "tmpl-delete", "delete-actor", CancellationToken.None);
// Assert
Assert.True(deleted);
Assert.Null(await _templateRepository.GetAsync("test-tenant", "tmpl-delete"));
Assert.Null(await _templateRepository.GetAsync("test-tenant", "tmpl-delete", CancellationToken.None));
var audit = _auditRepository.Entries.Last();
Assert.Equal("template.deleted", audit.Action);
@@ -170,7 +166,7 @@ public sealed class NotifyTemplateServiceTests
public async Task DeleteAsync_NonexistentTemplate_ReturnsFalse()
{
// Act
var deleted = await _service.DeleteAsync("test-tenant", "nonexistent", "actor");
var deleted = await _service.DeleteAsync("test-tenant", "nonexistent", "actor", CancellationToken.None);
// Assert
Assert.False(deleted);
@@ -180,16 +176,16 @@ public sealed class NotifyTemplateServiceTests
public async Task ListAsync_WithFilters_ReturnsFilteredResults()
{
// Arrange
await _templateRepository.UpsertAsync(CreateTemplate("tmpl-1", "pack.approval", "en-us"));
await _templateRepository.UpsertAsync(CreateTemplate("tmpl-2", "pack.approval", "de-de"));
await _templateRepository.UpsertAsync(CreateTemplate("tmpl-3", "risk.alert", "en-us"));
await _templateRepository.UpsertAsync(CreateTemplate("tmpl-1", "pack.approval", "en-us"), CancellationToken.None);
await _templateRepository.UpsertAsync(CreateTemplate("tmpl-2", "pack.approval", "de-de"), CancellationToken.None);
await _templateRepository.UpsertAsync(CreateTemplate("tmpl-3", "risk.alert", "en-us"), CancellationToken.None);
// Act
var results = await _service.ListAsync("test-tenant", new TemplateListOptions
{
KeyPrefix = "pack.",
Locale = "en-us"
});
}, CancellationToken.None);
// Assert
Assert.Single(results);

View File

@@ -43,13 +43,13 @@ public sealed class TenantNotificationEnricherTests
var result = enricher.Enrich(payload);
// Assert
result.Should().ContainKey("_tenant");
result.ContainsKey("_tenant").Should().BeTrue();
var tenant = result["_tenant"]!.AsObject();
tenant["id"]!.GetValue<string>().Should().Be("tenant-123");
tenant["actor"]!.GetValue<string>().Should().Be("user@test.com");
tenant["correlationId"]!.GetValue<string>().Should().Be("corr-456");
tenant["source"]!.GetValue<string>().Should().Be("HttpHeader");
tenant.Should().ContainKey("timestamp");
tenant.ContainsKey("timestamp").Should().BeTrue();
}
[Fact]
@@ -68,7 +68,7 @@ public sealed class TenantNotificationEnricherTests
var result = enricher.Enrich(payload);
// Assert
result.Should().NotContainKey("_tenant");
result.ContainsKey("_tenant").Should().BeFalse();
result["eventType"]!.GetValue<string>().Should().Be("test.event");
}
@@ -87,7 +87,7 @@ public sealed class TenantNotificationEnricherTests
var result = enricher.Enrich(payload);
// Assert
result.Should().NotContainKey("_tenant");
result.ContainsKey("_tenant").Should().BeFalse();
}
[Fact]
@@ -105,8 +105,8 @@ public sealed class TenantNotificationEnricherTests
var result = enricher.Enrich(payload);
// Assert
result.Should().ContainKey("tenantContext");
result.Should().NotContainKey("_tenant");
result.ContainsKey("tenantContext").Should().BeTrue();
result.ContainsKey("_tenant").Should().BeFalse();
}
[Fact]
@@ -125,7 +125,7 @@ public sealed class TenantNotificationEnricherTests
// Assert
var tenant = result["_tenant"]!.AsObject();
tenant.Should().NotContainKey("actor");
tenant.ContainsKey("actor").Should().BeFalse();
}
[Fact]
@@ -144,7 +144,7 @@ public sealed class TenantNotificationEnricherTests
// Assert
var tenant = result["_tenant"]!.AsObject();
tenant.Should().NotContainKey("correlationId");
tenant.ContainsKey("correlationId").Should().BeFalse();
}
[Fact]
@@ -163,7 +163,7 @@ public sealed class TenantNotificationEnricherTests
// Assert
var tenant = result["_tenant"]!.AsObject();
tenant.Should().NotContainKey("timestamp");
tenant.ContainsKey("timestamp").Should().BeFalse();
}
[Fact]
@@ -206,7 +206,7 @@ public sealed class TenantNotificationEnricherTests
// Assert
var tenant = result["_tenant"]!.AsObject();
tenant.Should().ContainKey("claims");
tenant.ContainsKey("claims").Should().BeTrue();
var claims = tenant["claims"]!.AsObject();
claims["role"]!.GetValue<string>().Should().Be("admin");
claims["department"]!.GetValue<string>().Should().Be("engineering");
@@ -462,9 +462,9 @@ public sealed class TenantNotificationEnricherExtensionsTests
var result = enricher.EnrichFromDictionary(data);
// Assert
result.Should().ContainKey("eventType");
result.Should().ContainKey("value");
result.Should().ContainKey("_tenant");
result.ContainsKey("eventType").Should().BeTrue();
result.ContainsKey("value").Should().BeTrue();
result.ContainsKey("_tenant").Should().BeTrue();
}
[Fact]

View File

@@ -3049,9 +3049,6 @@ paths:
/api/v2/notify/retention/cleanup: {}
/api/v2/notify/retention/cleanup/preview: {}
/api/v2/notify/retention/cleanup/last: {}
/api/v2/notify/rules: {}
/api/v2/notify/templates: {}
/api/v2/notify/incidents: {}
/api/v2/rules: {}
/api/v2/templates: {}
/api/v2/incidents: {}
@@ -3076,4 +3073,5 @@ app.TryRefreshStellaRouterEndpoints(routerOptions);
app.Run();
// Make Program class accessible to test projects using WebApplicationFactory
public partial class Program;

View File

@@ -9,10 +9,10 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../../../Notify/__Libraries/StellaOps.Notify.Storage.Postgres/StellaOps.Notify.Storage.Postgres.csproj" />
<ProjectReference Include="../../../Notify/__Libraries/StellaOps.Notify.Persistence/StellaOps.Notify.Persistence.csproj" />
<ProjectReference Include="../../../Notify/__Libraries/StellaOps.Notify.Queue/StellaOps.Notify.Queue.csproj" />
<ProjectReference Include="../../../Notify/__Libraries/StellaOps.Notify.Engine/StellaOps.Notify.Engine.csproj" />
<ProjectReference Include="../StellaOps.Notifier.Worker/StellaOps.Notifier.Worker.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Router.AspNet/StellaOps.Router.AspNet.csproj" />
<ProjectReference Include="../../../Router/__Libraries/StellaOps.Router.AspNet/StellaOps.Router.AspNet.csproj" />
</ItemGroup>
</Project>

View File

@@ -6,7 +6,8 @@ using StellaOps.AirGap.Policy;
using StellaOps.Notifier.Worker.Channels;
using StellaOps.Notify.Engine;
using StellaOps.Notify.Queue;
using StellaOps.Notify.Storage.Postgres;
using StellaOps.Notify.Persistence.Extensions;
using StellaOps.Notify.Persistence.Postgres;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notifier.Worker.Dispatch;
using StellaOps.Notifier.Worker.Options;
@@ -30,7 +31,7 @@ builder.Services.Configure<NotifierWorkerOptions>(builder.Configuration.GetSecti
builder.Services.AddSingleton(TimeProvider.System);
var postgresSection = builder.Configuration.GetSection("notifier:storage:postgres");
builder.Services.AddNotifyPostgresStorage(builder.Configuration, postgresSection.Path);
builder.Services.AddNotifyPersistence(builder.Configuration, postgresSection.Path);
builder.Services.AddAirGapEgressPolicy(builder.Configuration);

View File

@@ -10,18 +10,18 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Cronos" Version="0.9.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.0" />
<PackageReference Include="Cronos" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
<PackageReference Include="Microsoft.Extensions.Http" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../../Notify/__Libraries/StellaOps.Notify.Models/StellaOps.Notify.Models.csproj" />
<ProjectReference Include="../../../Notify/__Libraries/StellaOps.Notify.Queue/StellaOps.Notify.Queue.csproj" />
<ProjectReference Include="../../../Notify/__Libraries/StellaOps.Notify.Storage.Postgres/StellaOps.Notify.Storage.Postgres.csproj" />
<ProjectReference Include="../../../Notify/__Libraries/StellaOps.Notify.Persistence/StellaOps.Notify.Persistence.csproj" />
<ProjectReference Include="../../../Notify/__Libraries/StellaOps.Notify.Engine/StellaOps.Notify.Engine.csproj" />
<ProjectReference Include="../../../AirGap/StellaOps.AirGap.Policy/StellaOps.AirGap.Policy/StellaOps.AirGap.Policy.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography/StellaOps.Cryptography.csproj" />

View File

@@ -1,62 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notifier.WebService", "StellaOps.Notifier.WebService\StellaOps.Notifier.WebService.csproj", "{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notifier.Worker", "StellaOps.Notifier.Worker\StellaOps.Notifier.Worker.csproj", "{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Notifier.Tests", "StellaOps.Notifier.Tests\StellaOps.Notifier.Tests.csproj", "{1DFEC971-61F4-4E63-A903-C04062C84967}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Debug|x64.ActiveCfg = Debug|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Debug|x64.Build.0 = Debug|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Debug|x86.ActiveCfg = Debug|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Debug|x86.Build.0 = Debug|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Release|Any CPU.Build.0 = Release|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Release|x64.ActiveCfg = Release|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Release|x64.Build.0 = Release|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Release|x86.ActiveCfg = Release|Any CPU
{D14281B8-BC8E-4D31-B1FC-E3C9565F7482}.Release|x86.Build.0 = Release|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Debug|x64.ActiveCfg = Debug|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Debug|x64.Build.0 = Debug|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Debug|x86.ActiveCfg = Debug|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Debug|x86.Build.0 = Debug|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Release|Any CPU.Build.0 = Release|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Release|x64.ActiveCfg = Release|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Release|x64.Build.0 = Release|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Release|x86.ActiveCfg = Release|Any CPU
{A134A9AE-CC9E-4AC7-8CD7-8C7BBF45CD02}.Release|x86.Build.0 = Release|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Debug|x64.ActiveCfg = Debug|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Debug|x64.Build.0 = Debug|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Debug|x86.ActiveCfg = Debug|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Debug|x86.Build.0 = Debug|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Release|Any CPU.Build.0 = Release|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Release|x64.ActiveCfg = Release|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Release|x64.Build.0 = Release|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Release|x86.ActiveCfg = Release|Any CPU
{1DFEC971-61F4-4E63-A903-C04062C84967}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal