using FluentAssertions; using SatelliteProvider.Common.Utils; namespace SatelliteProvider.Tests; public class DownloaderRefactorTests { [Fact] public void GoogleMapsDownloaderV2_UsesHashSetForExistingTileLookup_AZ375_AC1() { // Arrange var path = LocateRepoFile(Path.Combine( "SatelliteProvider.Services.TileDownloader", "GoogleMapsDownloaderV2.cs")); path.Should().NotBeNull("GoogleMapsDownloaderV2.cs must be present in the workspace for this assertion"); var content = File.ReadAllText(path!); // Assert content.Should().NotContain("existingTiles.FirstOrDefault", "AZ-375 replaces the per-tile FirstOrDefault scan with a HashSet membership check"); content.Should().NotContain("_processingConfig.LatLonTolerance", "AZ-375 removes the float-tolerance comparison at the existing-tile lookup site"); content.Should().Contain("HashSet<(int X, int Y, int Z)>", "AZ-375 introduces a typed HashSet keyed by tile (X, Y, Z) for O(1) lookup"); content.Should().Contain("existingTileKeys.Contains((x, y, zoomLevel))", "the inner loop must consult the precomputed HashSet for skip decisions"); } [Fact] public void GoogleMapsDownloaderV2_UsesGeoUtilsCircumferenceConstant_AZ377_AC1() { // Arrange var path = LocateRepoFile(Path.Combine( "SatelliteProvider.Services.TileDownloader", "GoogleMapsDownloaderV2.cs")); path.Should().NotBeNull(); var content = File.ReadAllText(path!); // Assert content.Should().NotContain("EARTH_CIRCUMFERENCE_METERS", "AZ-377 removes the duplicated local Earth circumference literal"); content.Should().NotContain("40075016.686", "AZ-377 forbids duplicate Earth circumference literals outside GeoUtils"); content.Should().Contain("GeoUtils.EarthEquatorialCircumferenceMeters", "AZ-377 routes the downloader through the canonical GeoUtils constant"); } [Fact] public void TileRepository_UsesGeoUtilsAndMapConfigConstants_AZ377_AC1() { // Arrange var path = LocateRepoFile(Path.Combine( "SatelliteProvider.DataAccess", "Repositories", "TileRepository.cs")); path.Should().NotBeNull(); var content = File.ReadAllText(path!); // Assert content.Should().NotContain("EARTH_CIRCUMFERENCE_METERS"); content.Should().NotContain("TILE_SIZE_PIXELS = 256"); content.Should().NotContain("40075016.686", "AZ-377 forbids duplicate Earth circumference literals outside GeoUtils"); content.Should().NotContain("111000.0", "AZ-377 forbids duplicate per-degree-latitude literals outside GeoUtils"); content.Should().Contain("GeoUtils.EarthEquatorialCircumferenceMeters"); content.Should().Contain("GeoUtils.MetersPerDegreeLatitude"); content.Should().Contain("MapConfig.DefaultTileSizePixels"); } [Fact] public void GeoUtils_IsTheSoleHolderOfRawEarthLiterals_AZ377_AC1() { // Arrange var geoUtilsPath = LocateRepoFile(Path.Combine( "SatelliteProvider.Common", "Utils", "GeoUtils.cs")); geoUtilsPath.Should().NotBeNull(); var content = File.ReadAllText(geoUtilsPath!); // Assert content.Should().Contain("public const double EarthRadiusMeters = 6378137"); content.Should().Contain("public const double EarthEquatorialCircumferenceMeters = 40075016.686"); content.Should().Contain("public const double MetersPerDegreeLatitude = 111000"); } [Fact] public void HaversineDistance_WithTinyDelta_UsesEarthRadiusConstantConsistently_AZ377_AC2() { // Arrange var p1 = new SatelliteProvider.Common.DTO.GeoPoint(50.4501, 30.5234); var p2 = new SatelliteProvider.Common.DTO.GeoPoint(50.4501, 30.6234); // Act var distance = GeoUtils.CalculateDistance(p1, p2); // Assert var expectedManual = 2d * Math.Asin(Math.Sqrt( Math.Cos(50.4501 * Math.PI / 180.0) * Math.Cos(50.4501 * Math.PI / 180.0) * Math.Pow(Math.Sin(0.05 * Math.PI / 180.0), 2))) * GeoUtils.EarthRadiusMeters; distance.Should().BeApproximately(expectedManual, 0.0001, "AZ-377 must not change the numeric result of CalculateDistance"); } private static string? LocateRepoFile(string relativePath) { var dir = new DirectoryInfo(Directory.GetCurrentDirectory()); while (dir is not null) { var candidate = Path.Combine(dir.FullName, relativePath); if (File.Exists(candidate)) { return candidate; } dir = dir.Parent; } return null; } }