| File: HelmVersionValidatorTests.cs | Web Access |
| Project: src\tests\Aspire.Hosting.Kubernetes.Tests\Aspire.Hosting.Kubernetes.Tests.csproj (Aspire.Hosting.Kubernetes.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace Aspire.Hosting.Kubernetes.Tests; public class HelmVersionValidatorTests { [Theory] [InlineData("v4.2.0+gfa15ec0", 4, 2, 0)] [InlineData("v4.0.0", 4, 0, 0)] [InlineData("v4.5.1+g123abc", 4, 5, 1)] [InlineData("v5.0.0", 5, 0, 0)] [InlineData("v3.18.0+gb88f836", 3, 18, 0)] [InlineData("4.2.0", 4, 2, 0)] public void TryParseHelmVersion_ValidOutput_ReturnsTrueAndVersion(string output, int major, int minor, int patch) { Assert.True(HelmVersionValidator.TryParseHelmVersion(output, out var version)); Assert.Equal(new Version(major, minor, patch), version); } [Theory] [InlineData("")] [InlineData(" ")] [InlineData("not a version")] [InlineData("helm: command not found")] public void TryParseHelmVersion_InvalidOutput_ReturnsFalse(string output) { Assert.False(HelmVersionValidator.TryParseHelmVersion(output, out _)); } [Fact] public async Task EnsureMinimumVersionAsync_AtMinimum_Passes() { var runner = new FakeHelmRunner { VersionOutput = "v4.2.0+gfa15ec0" }; await HelmVersionValidator.EnsureMinimumVersionAsync(runner, CancellationToken.None); } [Fact] public async Task EnsureMinimumVersionAsync_NewerVersion_Passes() { var runner = new FakeHelmRunner { VersionOutput = "v5.1.0+g111111" }; await HelmVersionValidator.EnsureMinimumVersionAsync(runner, CancellationToken.None); } [Theory] [InlineData("v4.1.0+gfa15ec0")] [InlineData("v4.0.0")] [InlineData("v3.18.0+gb88f836")] [InlineData("v3.14.4+gb88f836")] public async Task EnsureMinimumVersionAsync_TooOld_ThrowsWithDetectedAndRequired(string oldVersion) { var runner = new FakeHelmRunner { VersionOutput = oldVersion }; var ex = await Assert.ThrowsAsync<InvalidOperationException>( () => HelmVersionValidator.EnsureMinimumVersionAsync(runner, CancellationToken.None)); // Detected version (without leading 'v' and without build metadata) var trimmed = oldVersion.TrimStart('v').Split('+')[0]; Assert.Contains(trimmed, ex.Message, StringComparison.Ordinal); Assert.Contains(HelmVersionValidator.MinimumHelmVersion.ToString(), ex.Message, StringComparison.Ordinal); Assert.Contains("https://helm.sh/docs/intro/install/", ex.Message, StringComparison.Ordinal); } [Fact] public async Task EnsureMinimumVersionAsync_UnparseableOutput_ThrowsWithRawOutput() { var runner = new FakeHelmRunner { VersionOutput = "garbage banner" }; var ex = await Assert.ThrowsAsync<InvalidOperationException>( () => HelmVersionValidator.EnsureMinimumVersionAsync(runner, CancellationToken.None)); Assert.Contains("garbage banner", ex.Message, StringComparison.Ordinal); Assert.Contains(HelmVersionValidator.MinimumHelmVersion.ToString(), ex.Message, StringComparison.Ordinal); } [Fact] public async Task EnsureMinimumVersionAsync_NonZeroExitCode_ThrowsWithInstallHint() { var runner = new FakeHelmRunner { VersionOutput = string.Empty, VersionExitCode = 1, }; var ex = await Assert.ThrowsAsync<InvalidOperationException>( () => HelmVersionValidator.EnsureMinimumVersionAsync(runner, CancellationToken.None)); Assert.Contains("https://helm.sh/docs/intro/install/", ex.Message, StringComparison.Ordinal); } [Fact] public async Task EnsureMinimumVersionAsync_DoesNotPassClientFlag() { // Regression: --client was removed in Helm 4 (the minimum version Aspire // requires), so passing it makes the validator's own probe fail with // "Error: unknown flag: --client" against the very baseline it is meant // to validate. var runner = new RecordingHelmRunner(); await HelmVersionValidator.EnsureMinimumVersionAsync(runner, CancellationToken.None); Assert.NotNull(runner.LastArguments); Assert.DoesNotContain("--client", runner.LastArguments, StringComparison.Ordinal); Assert.Contains("version", runner.LastArguments, StringComparison.Ordinal); Assert.Contains("--short", runner.LastArguments, StringComparison.Ordinal); } private sealed class RecordingHelmRunner : IHelmRunner { public string? LastArguments { get; private set; } public Task<int> RunAsync( string arguments, string? workingDirectory = null, Action<string>? onOutputData = null, Action<string>? onErrorData = null, CancellationToken cancellationToken = default) { LastArguments = arguments; onOutputData?.Invoke("v4.2.0+gfa15ec0"); return Task.FromResult(0); } } }