123 lines
6.0 KiB
C#
123 lines
6.0 KiB
C#
using System.Reflection;
|
|
using System.Text.Json;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using RutasDBUS.Components.Pages;
|
|
using RutasDBUS.Modelos.Historial;
|
|
using RutasDBUS.Modelos.Planificacion;
|
|
using RutasDBUS.Servicios.Caminata;
|
|
using RutasDBUS.Servicios.Configuracion;
|
|
using RutasDBUS.Servicios.Planificacion;
|
|
|
|
static void Check(bool result, string message)
|
|
{
|
|
if (!result) throw new Exception(message);
|
|
Console.WriteLine("OK " + message);
|
|
}
|
|
|
|
var baseMethod = typeof(PlanificadorRutas).GetMethod("CrearConfiguracionBaseHistorial", BindingFlags.Static | BindingFlags.NonPublic)!;
|
|
var defaults = (ConfiguracionHistorialRuta)baseMethod.Invoke(null, null)!;
|
|
Check(defaults.PesoTransbordoRankingMinutos == 6, "Penalizacion inicial de 6 minutos");
|
|
|
|
var folder = Path.Combine(Path.GetTempPath(), "rutasdbus-regression-" + Guid.NewGuid().ToString("N"));
|
|
IConfiguration Config() => new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string?>
|
|
{
|
|
["ValoresFabrica:Directorio"] = folder
|
|
}).Build();
|
|
ServicioValoresFabrica Service() => new(Config(), NullLogger<ServicioValoresFabrica>.Instance);
|
|
|
|
try
|
|
{
|
|
defaults.PesoTransbordoRankingMinutos = 9;
|
|
defaults.FechaSimulada = null;
|
|
defaults.HoraSimulada = null;
|
|
Directory.CreateDirectory(folder);
|
|
var file = Path.Combine(folder, "configuracion-fabrica.json");
|
|
await File.WriteAllTextAsync(file, JsonSerializer.Serialize(defaults));
|
|
var loaded = await Service().CargarAsync();
|
|
Check(loaded?.PesoTransbordoRankingMinutos == 9, "Valores compartidos entre instancias");
|
|
Check(loaded is { FechaSimulada: null, HoraSimulada: null }, "Los valores de fabrica no fijan la fecha y hora");
|
|
File.WriteAllText(file, "{incompleto");
|
|
Check(await Service().CargarAsync() is null, "JSON danado permite usar valores base");
|
|
}
|
|
finally
|
|
{
|
|
// Solo datos temporales creados por esta prueba.
|
|
if (Directory.Exists(folder)) Directory.Delete(folder, recursive: true);
|
|
}
|
|
|
|
var fake = new FakeValhalla();
|
|
var planner = new PlanificadorRutasServicio(null!, null!, fake, null!, null!, null!, null!);
|
|
var walk = typeof(PlanificadorRutasServicio).GetMethod("WalkValhallaCached", BindingFlags.Instance | BindingFlags.NonPublic)!;
|
|
async Task<(double[,]? linea, double distancia, double duracion)> Walk(List<List<double[]>>? zones = null) =>
|
|
await (Task<(double[,]?, double, double)>)walk.Invoke(planner, new object?[] { 43.31, -1.99, 43.32, -1.98, zones, null })!;
|
|
List<double[]> Ring(double lon, double lat, double size) =>
|
|
new() { new[] { lon, lat }, new[] { lon + size, lat }, new[] { lon + size, lat + size },
|
|
new[] { lon, lat + size }, new[] { lon, lat } };
|
|
|
|
await Walk();
|
|
var far = new List<List<double[]>> { Ring(-2.3, 43.0, .01) };
|
|
await Walk(far);
|
|
Check(fake.Calls == 2 && fake.Zones == 1, "Toda zona activa se envia a V2 aunque este lejos de la ruta previa");
|
|
var near = new List<List<double[]>> { Ring(-1.985, 43.315, .001), Ring(-1.982, 43.317, .001) };
|
|
await Walk(near);
|
|
Check(fake.Zones == 2, "Se envian todos los poligonos");
|
|
await Walk(near);
|
|
Check(fake.Calls == 3, "Mismas zonas reutilizan cache restringida");
|
|
near[0][0][0] += .00001;
|
|
await Walk(near);
|
|
Check(fake.Calls == 4, "Mover un vertice invalida esa entrada de cache");
|
|
await Walk(new() { Ring(-2.2, 43.1, .5) });
|
|
Check(fake.Calls == 5, "Una zona que rodea la ruta no se ignora aunque sus vertices esten lejos");
|
|
fake.Fail = true;
|
|
var retry = new List<List<double[]>> { Ring(-1.984, 43.312, .0002) };
|
|
await Walk(retry);
|
|
fake.Fail = false;
|
|
await Walk(retry);
|
|
Check(fake.Calls == 7, "Un fallo temporal no queda guardado en cache de zonas");
|
|
var puntos = new List<double[]> { new[] { 43.314, -1.984 }, new[] { 43.315, -1.983 } };
|
|
await (Task<(double[,]?, double, double)>)walk.Invoke(planner,
|
|
new object?[] { 43.31, -1.99, 43.32, -1.98, near, puntos })!;
|
|
Check(fake.Zones == 2 && fake.Points == 2, "Se envian juntos todos los poligonos y puntos activos");
|
|
var page = new PlanificadorRutas();
|
|
var flags = BindingFlags.Instance | BindingFlags.NonPublic;
|
|
var options = (List<AlternativaRuta>)typeof(PlanificadorRutas).GetField("_opcionesRuta", flags)!.GetValue(page)!;
|
|
var selected = typeof(PlanificadorRutas).GetField("_indiceAlternativaSeleccionada", flags)!;
|
|
var remember = typeof(PlanificadorRutas).GetMethod("ObtenerProveedorSoloAPieParaRecalculo", flags)!;
|
|
string? Remember(bool keep) => (string?)remember.Invoke(page, new object[] { keep });
|
|
options.Add(new() { EsSoloAPie = true, ProveedorRuta = "v1" });
|
|
options.Add(new() { EsSoloAPie = true, ProveedorRuta = "v2" });
|
|
selected.SetValue(page, 1);
|
|
Check(Remember(true) == "v2", "Se conserva la version andando seleccionada");
|
|
options.Clear();
|
|
Check(Remember(true) == "v2", "Otro cambio de punto durante el calculo conserva v2");
|
|
options.Add(new() { EsSoloAPie = false });
|
|
selected.SetValue(page, 0);
|
|
Check(Remember(true) is null, "Seleccionar bus libera la preferencia andando");
|
|
options.Clear();
|
|
Check(Remember(false) is null, "Nueva seleccion de criterio no hereda la preferencia andando");
|
|
Console.WriteLine("Pruebas completadas.");
|
|
|
|
sealed class FakeValhalla : IClienteValhalla
|
|
{
|
|
public Task<InformacionSueloTramo?> ObtenerInformacionSueloAsync(
|
|
double[,] linea, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult<InformacionSueloTramo?>(null);
|
|
|
|
public int Calls { get; private set; }
|
|
public int Zones { get; private set; }
|
|
public int Points { get; private set; }
|
|
public bool Fail { get; set; }
|
|
public Task<(double[,]? Linea, double DistanciaMetros, double DuracionSegundos)> ObtenerRutaAsync(
|
|
double latitudDesde, double longitudDesde, double latitudHasta, double longitudHasta,
|
|
string costing = "pedestrian", List<List<double[]>>? excludePolygons = null,
|
|
List<double[]>? excludeLocations = null)
|
|
{
|
|
Calls++;
|
|
Zones = excludePolygons?.Count ?? 0;
|
|
Points = excludeLocations?.Count ?? 0;
|
|
return Task.FromResult<(double[,]?, double, double)>(Fail ? (null, 0, 0) :
|
|
(new[,] { { latitudDesde, longitudDesde }, { latitudHasta, longitudHasta } }, 100, 100));
|
|
}
|
|
}
|