Files
satellite-provider/SatelliteProvider.Tests/RouteImageRendererTests.cs
T
Oleksandr Bezdieniezhnykh 1dcd089d39 [AZ-371] Refactor C18: magic numbers to ProcessingConfig/MapConfig
Promotes 8 operational levers into config keys with defaults that match
the prior source literals byte-for-byte:
  ProcessingConfig: RegionProcessingTimeoutSeconds (300),
  RouteProcessingPollIntervalSeconds (5),
  MaxRoutePointSpacingMeters (200), LatLonTolerance (0.0001).
  MapConfig: TileSizePixels (256), AllowedZoomLevels ([15..19]),
  RetryBaseDelaySeconds (1), RetryMaxDelaySeconds (30).

Sites updated: RegionService, RouteProcessingService,
RoutePointGraphBuilder, RouteValidator, RouteService 4-arg ctor,
RouteImageRenderer, GoogleMapsDownloaderV2, TileService. Closes LF-2 by
forwarding HttpContext.RequestAborted from GetTileByLatLon into the
downloader. appsettings.json gains the 8 new keys at default values.

Tests: 141 / 141 unit + 5 / 5 smoke green. New ConfigDefaultsTests pins
defaults to original literals; new TileService unit test asserts CT
identity from caller to downloader (AZ-371 AC-3).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 03:30:07 +03:00

95 lines
3.1 KiB
C#

using FluentAssertions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq;
using SatelliteProvider.Common.Configs;
using SatelliteProvider.Services.RouteManagement;
namespace SatelliteProvider.Tests;
// AZ-364 / C11: tests moved from RouteProcessingServiceTests when the helper
// migrated to RouteImageRenderer. The four tile-coordinate-parsing tests
// preserve the behavior contract (good name → parsed; malformed → sentinel
// + warning log; null → ArgumentNullException).
public class RouteImageRendererTests
{
private static RouteImageRenderer BuildSut(out Mock<ILogger<RouteImageRenderer>> loggerMock)
{
loggerMock = new Mock<ILogger<RouteImageRenderer>>();
var storageOptions = Options.Create(new StorageConfig());
var mapOptions = Options.Create(new MapConfig { Service = "GoogleMaps", ApiKey = "" });
return new RouteImageRenderer(storageOptions, mapOptions, loggerMock.Object);
}
private static void VerifyWarningLogged(Mock<ILogger<RouteImageRenderer>> loggerMock, string substringInState)
{
loggerMock.Verify(
l => l.Log(
LogLevel.Warning,
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((state, _) => state.ToString()!.Contains(substringInState)),
It.IsAny<Exception?>(),
It.IsAny<Func<It.IsAnyType, Exception?, string>>()),
Times.AtLeastOnce);
}
[Fact]
public void ExtractTileCoordinatesFromFilename_ValidName_ReturnsParsedCoordinates_AZ364_AC1()
{
// Arrange
var sut = BuildSut(out _);
// Act
var (x, y) = sut.ExtractTileCoordinatesFromFilename("/tiles/tile_1700000000_42_99.jpg");
// Assert
x.Should().Be(42);
y.Should().Be(99);
}
[Fact]
public void ExtractTileCoordinatesFromFilename_MalformedName_LogsWarningAndReturnsSentinel_AZ364_AC1()
{
// Arrange
var sut = BuildSut(out var loggerMock);
const string malformed = "/tmp/not_a_tile_filename.jpg";
// Act
var (x, y) = sut.ExtractTileCoordinatesFromFilename(malformed);
// Assert
x.Should().Be(-1);
y.Should().Be(-1);
VerifyWarningLogged(loggerMock, "not_a_tile_filename");
}
[Fact]
public void ExtractTileCoordinatesFromFilename_TilePrefixWithNonNumericCoords_LogsWarningAndReturnsSentinel_AZ364_AC1()
{
// Arrange
var sut = BuildSut(out var loggerMock);
const string nonNumeric = "/tiles/tile_1700000000_alpha_beta.jpg";
// Act
var (x, y) = sut.ExtractTileCoordinatesFromFilename(nonNumeric);
// Assert
x.Should().Be(-1);
y.Should().Be(-1);
VerifyWarningLogged(loggerMock, "tile_1700000000_alpha_beta");
}
[Fact]
public void ExtractTileCoordinatesFromFilename_NullPath_PropagatesArgumentNullException_AZ364_AC1()
{
// Arrange
var sut = BuildSut(out _);
// Act
Action act = () => sut.ExtractTileCoordinatesFromFilename(null!);
// Assert
act.Should().Throw<ArgumentNullException>();
}
}