using System; using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; namespace ManagerService.Tests.Infrastructure { /// /// Fabrique d'HttpClient sans réseau, pour les chemins qui sondent le poids d'un blob /// par HEAD (ResourceSizeProbe). Les tailles sont données par URL ; une URL /// absente de la table répond sans Content-Length, ce qui est exactement le cas /// « blob introuvable » que le backfill doit inventorier au lieu de le compter pour zéro. /// public class FakeHttpClientFactory : IHttpClientFactory { private readonly IDictionary _sizesByUrl; private readonly ISet _throwingUrls; public FakeHttpClientFactory(IDictionary sizesByUrl = null, ISet throwingUrls = null) { _sizesByUrl = sizesByUrl ?? new Dictionary(); _throwingUrls = throwingUrls ?? new HashSet(); } public HttpClient CreateClient(string name = "") => new HttpClient(new StubHandler(_sizesByUrl, _throwingUrls)); private class StubHandler : HttpMessageHandler { private readonly IDictionary _sizesByUrl; private readonly ISet _throwingUrls; public StubHandler(IDictionary sizesByUrl, ISet throwingUrls) { _sizesByUrl = sizesByUrl; _throwingUrls = throwingUrls; } protected override Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { var url = request.RequestUri!.ToString(); if (_throwingUrls.Contains(url)) throw new HttpRequestException("hôte injoignable"); var response = new HttpResponseMessage(HttpStatusCode.OK); if (_sizesByUrl.TryGetValue(url, out var size)) { // Content-Length ne se pose que sur un contenu : un HEAD réel renvoie // l'en-tête sans le corps, ce que StringContent + la longueur imite // suffisamment pour la sonde, qui ne lit que l'en-tête. response.Content = new ByteArrayContent(Array.Empty()); response.Content.Headers.ContentLength = size; } else { response.StatusCode = HttpStatusCode.NotFound; response.Content = new ByteArrayContent(Array.Empty()); response.Content.Headers.ContentLength = null; } return Task.FromResult(response); } } } }