| File: FakeCargoMetadataReader.cs | Web Access |
| Project: src\tests\Aspire.Hosting.Rust.Tests\Aspire.Hosting.Rust.Tests.csproj (Aspire.Hosting.Rust.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json; namespace Aspire.Hosting.Rust.Tests; /// <summary> /// Answers <c>cargo metadata</c> queries from a canned document instead of shelling out to cargo, so tests /// can exercise publishing and debugging on machines with no Rust toolchain installed. /// </summary> /// <param name="metadataJson">The document to answer with.</param> internal sealed class FakeCargoMetadataReader(string metadataJson) : ICargoMetadataReader { /// <summary> /// The environment the reader was last asked to query with. /// </summary> public IReadOnlyDictionary<string, string> LastEnvironment { get; private set; } = new Dictionary<string, string>(); /// <summary> /// The directory the reader was last asked to query in. /// </summary> public string? LastWorkingDirectory { get; private set; } /// <summary> /// How many times the reader has been asked for metadata. /// </summary> /// <remarks> /// Each launch request reads current metadata once, so tests use this count to catch duplicate reads /// inside one request without hiding manifest or environment changes from later executable creations. /// </remarks> public int ReadCount => _readCount; /// <summary> /// Optional hook invoked before the canned document is returned, so a test can stand in for a slow cargo. /// </summary> public Func<CancellationToken, Task>? OnRead { get; set; } /// <summary> /// Optional factory for returning different metadata documents on successive reads. /// </summary> public Func<int, string>? MetadataJsonFactory { get; set; } private int _readCount; public async Task<CargoMetadata> ReadAsync(string workingDirectory, string? manifestPath, string resourceName, IReadOnlyDictionary<string, string> environment, CancellationToken cancellationToken) { var readCount = Interlocked.Increment(ref _readCount); LastEnvironment = environment; LastWorkingDirectory = workingDirectory; if (OnRead is { } onRead) { await onRead(cancellationToken).ConfigureAwait(false); } var rebased = MetadataJsonFactory?.Invoke(readCount) ?? metadataJson; // Real cargo honours CARGO_TARGET_DIR when reporting target_directory, and the debug executable path // is derived from it, so the fake reflects it too. if (environment.TryGetValue("CARGO_TARGET_DIR", out var targetDirectory) && targetDirectory.Length > 0) { rebased = rebased.Replace( "\"target_directory\": \"/app/target\"", $"\"target_directory\": {JsonSerializer.Serialize(Path.GetFullPath(targetDirectory, workingDirectory))}", StringComparison.Ordinal); } return CargoMetadata.Parse(rebased); } }