mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-21 09:41:15 +00:00
9a53bff92e
Batch 24 of 03-code-quality-refactoring run; closes the run. AZ-375 (C22): GoogleMapsDownloaderV2.DownloadTilesGridAsync now builds a HashSet<(int X, int Y, int Z)> once from existingTiles and tests Contains((x, y, zoomLevel)) per cell. Removes the per-cell FirstOrDefault tolerance scan and the unused _processingConfig .LatLonTolerance reference at this site. AZ-377 (C24): promote Earth + tile-pixel constants to a single home. GeoUtils now exposes EarthRadiusMeters, EarthEquatorial CircumferenceMeters, MetersPerDegreeLatitude as public const. MapConfig adds DefaultTileSizePixels (const) wired as the TileSizePixels property default. TileRepository and Google MapsDownloaderV2 read those constants instead of duplicating the literals 6378137, 40075016.686, 111000.0, and 256. Tests: +6 new (DownloaderRefactorTests, extended GeoUtils RefactorTests). 200/200 unit tests pass. Cumulative K=3 review (batches 22-24): PASS_WITH_WARNINGS, 4 Low findings only — see _docs/03_implementation/reviews/cumulative_review_22-24.md. Tooling fix: scripts/run-tests.sh --unit-only path now restores before testing (was failing on SixLabors resolution in clean container). Stripped stray BOM from MapConfig.cs to satisfy the .editorconfig charset gate. Updates _dependencies_table.md to reflect all 27 03-code-quality- refactoring tasks done; updates _autodev_state.md to refactor phase 5 (test-sync). Co-authored-by: Cursor <cursoragent@cursor.com>
116 lines
4.8 KiB
C#
116 lines
4.8 KiB
C#
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;
|
|
}
|
|
}
|