using System.Collections.Concurrent; using System.Text.RegularExpressions; using Cleanuparr.Domain.Enums; using Cleanuparr.Infrastructure.Features.MalwareBlocker; using Cleanuparr.Infrastructure.Helpers; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NSubstitute; using Shouldly; using Xunit; namespace Cleanuparr.Infrastructure.Tests.Features.MalwareBlocker; public class BlocklistProviderTests : IDisposable { private readonly IMemoryCache _cache; private readonly ILogger _logger; private readonly IServiceScopeFactory _scopeFactory; private readonly BlocklistProvider _provider; public BlocklistProviderTests() { _cache = new MemoryCache(new MemoryCacheOptions()); _logger = Substitute.For>(); _scopeFactory = Substitute.For(); _provider = new BlocklistProvider(_logger, _scopeFactory, _cache); } public void Dispose() { _cache.Dispose(); } [Fact] public void GetBlocklistType_NotInCache_ReturnsDefaultBlacklist() { // Act var result = _provider.GetBlocklistType(InstanceType.Sonarr); // Assert result.ShouldBe(BlocklistType.Blacklist); } [Theory] [InlineData(InstanceType.Sonarr)] [InlineData(InstanceType.Radarr)] [InlineData(InstanceType.Lidarr)] [InlineData(InstanceType.Readarr)] [InlineData(InstanceType.Whisparr)] public void GetBlocklistType_InCache_ReturnsCachedValue(InstanceType instanceType) { // Arrange _cache.Set(CacheKeys.BlocklistType(instanceType), BlocklistType.Whitelist); // Act var result = _provider.GetBlocklistType(instanceType); // Assert result.ShouldBe(BlocklistType.Whitelist); } [Fact] public void GetPatterns_NotInCache_ReturnsEmptyBag() { // Act var result = _provider.GetPatterns(InstanceType.Sonarr); // Assert result.ShouldNotBeNull(); result.ShouldBeEmpty(); } [Fact] public void GetPatterns_InCache_ReturnsCachedPatterns() { // Arrange var patterns = new ConcurrentBag { "*.exe", "*.dll", "malware*" }; _cache.Set(CacheKeys.BlocklistPatterns(InstanceType.Radarr), patterns); // Act var result = _provider.GetPatterns(InstanceType.Radarr); // Assert result.Count.ShouldBe(3); result.ShouldContain("*.exe"); result.ShouldContain("*.dll"); result.ShouldContain("malware*"); } [Fact] public void GetRegexes_NotInCache_ReturnsEmptyBag() { // Act var result = _provider.GetRegexes(InstanceType.Lidarr); // Assert result.ShouldNotBeNull(); result.ShouldBeEmpty(); } [Fact] public void GetRegexes_InCache_ReturnsCachedRegexes() { // Arrange var regexes = new ConcurrentBag { new Regex(@"^\d+$"), new Regex(@"test\d+\.exe") }; _cache.Set(CacheKeys.BlocklistRegexes(InstanceType.Readarr), regexes); // Act var result = _provider.GetRegexes(InstanceType.Readarr); // Assert result.Count.ShouldBe(2); } [Theory] [InlineData(InstanceType.Sonarr)] [InlineData(InstanceType.Radarr)] [InlineData(InstanceType.Lidarr)] [InlineData(InstanceType.Readarr)] [InlineData(InstanceType.Whisparr)] public void GetPatterns_DifferentInstanceTypes_UsesCorrectCacheKey(InstanceType instanceType) { // Arrange - set patterns for each instance type differently var patterns = new ConcurrentBag { $"pattern_for_{instanceType}" }; _cache.Set(CacheKeys.BlocklistPatterns(instanceType), patterns); // Act var result = _provider.GetPatterns(instanceType); // Assert result.ShouldContain($"pattern_for_{instanceType}"); } [Fact] public void GetPatterns_DifferentInstanceTypes_ReturnsDifferentPatterns() { // Arrange var sonarrPatterns = new ConcurrentBag { "sonarr_pattern" }; var radarrPatterns = new ConcurrentBag { "radarr_pattern" }; _cache.Set(CacheKeys.BlocklistPatterns(InstanceType.Sonarr), sonarrPatterns); _cache.Set(CacheKeys.BlocklistPatterns(InstanceType.Radarr), radarrPatterns); // Act var sonarrResult = _provider.GetPatterns(InstanceType.Sonarr); var radarrResult = _provider.GetPatterns(InstanceType.Radarr); // Assert sonarrResult.ShouldContain("sonarr_pattern"); sonarrResult.ShouldNotContain("radarr_pattern"); radarrResult.ShouldContain("radarr_pattern"); radarrResult.ShouldNotContain("sonarr_pattern"); } }