using Microsoft.Extensions.Logging.Abstractions; using MongoDB.Entities; using PrivaPub.Infrastructure.Geo; using PrivaPub.Infrastructure.Statistics; using PrivaPub.Models.Jobs; using PrivaPub.Tests.Support; using System.Net; namespace PrivaPub.Tests.Infrastructure { [Trait("Category", "Integration")] public sealed class CdnUpdaterTests : IAsyncLifetime { Peer _peer; CdnRanges _ranges; CdnUpdater _updater; string _key; public async ValueTask InitializeAsync() { Assert.SkipUnless(MongoFixture.Enabled, MongoFixture.Skip); _peer = await Peer.Start(); _ranges = new CdnRanges(); _updater = new CdnUpdater(new Clients(), new StaticOptions(new StatisticsOptions()), _ranges, NullLogger.Instance); _key = $"edge{Guid.NewGuid():N}.example"; } public async ValueTask DisposeAsync() { if (_peer != default) await _peer.DisposeAsync(); } sealed class Clients : IHttpClientFactory { public HttpClient CreateClient(string name) => new(); } CdnProvider Provider() => new("Test Edge", _key, Array.Empty(), new[] { new CdnList($"{_peer.A}/edge/v4", CdnListFormat.Lines), new CdnList($"{_peer.A}/edge/v6", CdnListFormat.StringArray) }, _ => false); static CancellationToken Token => TestContext.Current.CancellationToken; [Fact] public async Task The_published_ranges_are_downloaded_stored_and_used() { _peer.ServeText("/edge/v4", "198.51.100.0/24\n", "text/plain"); _peer.ServeText("/edge/v6", """["2001:db8::/32","192.0.2.9"]""", "application/json"); Assert.Equal(1, await _updater.Update(new[] { Provider() }, Token)); var stored = await DB.Default.Find().Match(s => s.Key == _key).ExecuteSingleAsync(Token); Assert.Equal(new[] { "198.51.100.0/24", "2001:db8::/32", "192.0.2.9/32" }, stored.Ranges); Assert.Equal("Test Edge", _ranges.Of(IPAddress.Parse("198.51.100.20"))?.Name); Assert.Equal("Test Edge", _ranges.Of(IPAddress.Parse("192.0.2.9"))?.Name); var restarted = new CdnRanges(); await restarted.Load(Token); Assert.Equal("Test Edge", restarted.Of(IPAddress.Parse("2001:db8::7"))?.Name); } [Theory] [InlineData("not a network")] [InlineData("")] public async Task A_broken_or_empty_list_keeps_the_stored_ranges(string broken) { _peer.ServeText("/edge/v4", "198.51.100.0/24", "text/plain"); _peer.ServeText("/edge/v6", "[]", "application/json"); Assert.Equal(1, await _updater.Update(new[] { Provider() }, Token)); _peer.ServeText("/edge/v4", broken, "text/plain"); Assert.Equal(0, await _updater.Update(new[] { Provider() }, Token)); Assert.Equal(new[] { "198.51.100.0/24" }, (await DB.Default.Find().Match(s => s.Key == _key).ExecuteSingleAsync(Token)).Ranges); Assert.Equal("Test Edge", _ranges.Of(IPAddress.Parse("198.51.100.1"))?.Name); } // The real lists, from the CDNs themselves: set PRIVAPUB_TEST_CDN_LIVE=1 to check that every format still parses. [Fact] public async Task Every_cdns_real_list_still_parses() { Assert.SkipUnless(Environment.GetEnvironmentVariable("PRIVAPUB_TEST_CDN_LIVE") == "1", "set PRIVAPUB_TEST_CDN_LIVE=1 to download the real lists"); var listed = CdnCatalog.All.Where(p => p.Lists.Length > 0).ToList(); Assert.Equal(listed.Count, await _updater.Update(listed, Token)); Assert.Equal("Cloudflare", _ranges.Of(IPAddress.Parse("104.16.0.1"))?.Name); foreach (var provider in listed) Assert.True(_ranges.Status[provider.Key].Ranges > 0, provider.Name); } [Fact] public async Task An_unreachable_list_changes_nothing() { Assert.Equal(0, await _updater.Update(new[] { Provider() }, Token)); Assert.False(await DB.Default.Find().Match(s => s.Key == _key).ExecuteAnyAsync(Token)); } } }