mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-26 07:51:13 +00:00
7633134a8a
Extract tile_provision.proto into GrpcContracts, add integration tests and validation hardening for DeliverRouteTiles streaming. Co-authored-by: Cursor <cursoragent@cursor.com>
109 lines
3.5 KiB
C#
109 lines
3.5 KiB
C#
using Grpc.Core;
|
|
using Grpc.Net.Client;
|
|
using Satellite.V1;
|
|
|
|
namespace SatelliteProvider.IntegrationTests;
|
|
|
|
public static class GrpcTestHelpers
|
|
{
|
|
public static GrpcChannel CreateChannel(string apiUrl)
|
|
{
|
|
return GrpcChannel.ForAddress(apiUrl, new GrpcChannelOptions
|
|
{
|
|
HttpHandler = new SocketsHttpHandler
|
|
{
|
|
EnableMultipleHttp2Connections = true,
|
|
},
|
|
});
|
|
}
|
|
|
|
public static RouteTileDelivery.RouteTileDeliveryClient CreateClient(string apiUrl, string jwtToken)
|
|
{
|
|
var channel = CreateChannel(apiUrl);
|
|
var client = new RouteTileDelivery.RouteTileDeliveryClient(channel);
|
|
return client;
|
|
}
|
|
|
|
public static Metadata AuthMetadata(string jwtToken)
|
|
{
|
|
return new Metadata { { "Authorization", $"Bearer {jwtToken}" } };
|
|
}
|
|
|
|
public static DeliverRouteTilesRequest BuildValidRequest(
|
|
Guid? routeId = null,
|
|
double lat1 = 48.276067180586544,
|
|
double lon1 = 37.38445758819581,
|
|
double lat2 = 48.27074009522731,
|
|
double lon2 = 37.374029159545906,
|
|
double regionSizeMeters = 500,
|
|
int zoom = 18)
|
|
{
|
|
return new DeliverRouteTilesRequest
|
|
{
|
|
Route = new RouteSpec
|
|
{
|
|
RouteId = (routeId ?? Guid.NewGuid()).ToString(),
|
|
RegionSizeMeters = regionSizeMeters,
|
|
Zoom = zoom,
|
|
Waypoints =
|
|
{
|
|
new Waypoint { Lat = lat1, Lon = lon1 },
|
|
new Waypoint { Lat = lat2, Lon = lon2 },
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
public static async Task<(RouteManifest? Manifest, List<TilePayload> Tiles, DeliveryComplete? Complete, DeliveryError? Error)>
|
|
CollectStreamAsync(AsyncServerStreamingCall<RouteTileEvent> call, int? delayMsBetweenEvents = null)
|
|
{
|
|
RouteManifest? manifest = null;
|
|
var tiles = new List<TilePayload>();
|
|
DeliveryComplete? complete = null;
|
|
DeliveryError? error = null;
|
|
|
|
await foreach (var evt in call.ResponseStream.ReadAllAsync())
|
|
{
|
|
switch (evt.PayloadCase)
|
|
{
|
|
case RouteTileEvent.PayloadOneofCase.Manifest:
|
|
manifest = evt.Manifest;
|
|
break;
|
|
case RouteTileEvent.PayloadOneofCase.Batch:
|
|
tiles.AddRange(evt.Batch.Tiles);
|
|
break;
|
|
case RouteTileEvent.PayloadOneofCase.Complete:
|
|
complete = evt.Complete;
|
|
break;
|
|
case RouteTileEvent.PayloadOneofCase.Error:
|
|
error = evt.Error;
|
|
break;
|
|
}
|
|
|
|
if (delayMsBetweenEvents.HasValue)
|
|
{
|
|
await Task.Delay(delayMsBetweenEvents.Value);
|
|
}
|
|
}
|
|
|
|
return (manifest, tiles, complete, error);
|
|
}
|
|
|
|
public static async Task ExpectInvalidArgumentAsync(Func<Task> action, string context)
|
|
{
|
|
try
|
|
{
|
|
await action();
|
|
throw new Exception($"{context}: expected RpcException with InvalidArgument, but call succeeded");
|
|
}
|
|
catch (RpcException ex) when (ex.StatusCode == StatusCode.InvalidArgument)
|
|
{
|
|
Console.WriteLine($" ✓ {context}: InvalidArgument — {ex.Status.Detail}");
|
|
}
|
|
catch (RpcException ex)
|
|
{
|
|
throw new Exception($"{context}: expected InvalidArgument, got {ex.StatusCode} — {ex.Status.Detail}");
|
|
}
|
|
}
|
|
}
|