Skip to content

Commit

Permalink
add e2e tests for app version and for single package promotion
Browse files Browse the repository at this point in the history
  • Loading branch information
Inok committed Dec 30, 2023
1 parent 92e6d91 commit ed665ba
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 0 deletions.
1 change: 1 addition & 0 deletions tests/Promote.NuGet.Tests/Promote.NuGet.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\src\Promote.NuGet\Promote.NuGet.csproj" />
<ProjectReference Include="..\Promote.NuGet.TestInfrastructure\Promote.NuGet.TestInfrastructure.csproj" />
</ItemGroup>
</Project>
125 changes: 125 additions & 0 deletions tests/Promote.NuGet.Tests/PromoteNugetProcessRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System.Diagnostics;
using System.IO;

namespace Promote.NuGet.Tests;

public static class PromoteNugetProcessRunner
{
public sealed class ProcessWrapper : IAsyncDisposable
{
public Process Process { get; }

public ProcessWrapper(Process process)
{
Process = process;
}

public void WaitForExit()
{
Process.WaitForExit();
}

public bool WaitForExit(int milliseconds)
{
return Process.WaitForExit(milliseconds);
}

public Task WaitForExitAsync(CancellationToken cancellationToken = default)
{
return Process.WaitForExitAsync(cancellationToken);
}

public int ExitCode => Process.ExitCode;

public StreamReader StandardError => Process.StandardError;

public StreamReader StandardOutput => Process.StandardOutput;

public async ValueTask DisposeAsync()
{
if (Process.HasExited == false)
{
TestContext.WriteLine("The process is still running. Dumping its output and killing the process.");
TestContext.WriteLine("Error output:");
TestContext.WriteLine(await Process.StandardError.ReadToEndAsync());
TestContext.WriteLine("Standard output:");
TestContext.WriteLine(await Process.StandardOutput.ReadToEndAsync());

TestContext.WriteLine("Killing...");
Process.Kill();
await Process.WaitForExitAsync();

TestContext.WriteLine("The process is stopped.");
}

Process.Dispose();
}
}

public record ProcessRunResult(int ExitCode, IReadOnlyCollection<string> StdOutput, IReadOnlyCollection<string> StdError);

public static async Task<ProcessRunResult> RunForResultAsync(params string[] arguments)
{
await using var process = await RunToExitAsync(arguments);

var stdOutput = new List<string>();
while (await process.StandardOutput.ReadLineAsync() is { } line)
{
stdOutput.Add(line);
}

var stdError = new List<string>();
while (await process.StandardError.ReadLineAsync() is { } line)
{
stdError.Add(line);
}

return new ProcessRunResult(process.ExitCode, stdOutput, stdError);
}

public static async Task<ProcessWrapper> RunToExitAsync(params string[] arguments)
{
var cancellationToken = TestContext.CurrentContext.CancellationToken;

var process = Run(arguments);

await process.WaitForExitAsync(cancellationToken);

return process;
}

public static ProcessWrapper Run(params string[] arguments)
{
var processStartInfo = new ProcessStartInfo
{
FileName = "dotnet",
ArgumentList = { "Promote.NuGet.dll" },
RedirectStandardOutput = true,
RedirectStandardError = true,
};

foreach (var argument in arguments)
{
processStartInfo.ArgumentList.Add(argument);
}

Process? process = null;
try
{
process = Process.Start(processStartInfo);

if (process == null)
{
Assert.Fail("Failed to run the process");
Environment.FailFast("UNREACHABLE");
}

return new ProcessWrapper(process);
}
catch
{
process?.Dispose();
throw;
}
}
}
66 changes: 66 additions & 0 deletions tests/Promote.NuGet.Tests/PromoteSinglePackageTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
using Promote.NuGet.Feeds;
using Promote.NuGet.TestInfrastructure;

namespace Promote.NuGet.Tests;

[TestFixture]
public class PromoteSinglePackageTests
{
[Test, CancelAfter(30_000)]
public async Task Promotes_a_package_with_its_dependencies_to_destination_feed()
{
await using var destinationFeed = await LocalNugetFeed.Create();

// Act
var result = await PromoteNugetProcessRunner.RunForResultAsync(
"promote",
"package",
"System.Runtime",
"--version", "4.3.0",
"--destination", destinationFeed.FeedUrl,
"--destination-api-key", destinationFeed.ApiKey
);

var destinationFeedDescriptor = new NuGetRepositoryDescriptor(destinationFeed.FeedUrl, destinationFeed.ApiKey);
var destinationRepo = new NuGetRepository(destinationFeedDescriptor, NullSourceCacheContext.Instance, TestNuGetLogger.Instance);

// Assert
result.StdOutput.Should().StartWith(

Check failure on line 30 in tests/Promote.NuGet.Tests/PromoteSinglePackageTests.cs

View workflow job for this annotation

GitHub Actions / .NET Tests

Promote.NuGet.Tests.PromoteSinglePackageTests ► Promotes_a_package_with_its_dependencies_to_destination_feed

Failed test found in: ./test-results/Promote.NuGet.Tests/test-result-7863ddf1ba0745cb8cc622ea842916b2.trx Error: Expected result.StdOutput to start with {"Resolving packages to promote:", "└── System.Runtime 4.3.0"}, but {"\u001b[1;38;5;2mResolving packages to promote:\u001b[0m", "└── System.Runtime 4.3.0", "\u001b[38;5;8mProcessing package System.Runtime 4.3.0\u001b[0m", "\u001b[38;5;8mNew dependency to process: Microsoft.NETCore.Platforms (>= 1.1.0)\u001b[0m", "\u001b[38;5;8mNew dependency to process: Microsoft.NETCore.Targets (>= 1.1.0)\u001b[0m", "\u001b[38;5;8mProcessing dependency Microsoft.NETCore.Platforms (>= 1.1.0)\u001b[0m", "\u001b[38;5;8mNew dependency found: Microsoft.NETCore.Platforms 1.1.0\u001b[0m", "\u001b[38;5;8mProcessing dependency Microsoft.NETCore.Targets (>= 1.1.0)\u001b[0m", "\u001b[38;5;8mNew dependency found: Microsoft.NETCore.Targets 1.1.0\u001b[0m", "\u001b[38;5;8mProcessing package Microsoft.NETCore.Platforms 1.1.0\u001b[0m", "\u001b[38;5;8mProcessing package Microsoft.NETCore.Targets 1.1.0\u001b[0m", "\u001b[1;38;5;2mFound 3 package(s) to promote:\u001b[0m", "├── Microsoft.NETCore.Platforms 1.1.0", "├── Microsoft.NETCore.Targets 1.1.0", "└── System.Runtime 4.3.0", "\u001b[1;38;5;2m(1/3) Promote Microsoft.NETCore.Platforms 1.1.0\u001b[0m", "\u001b[38;5;11mWarning: You are running the 'push' operation with an 'HTTP' source, \u001b[0m", "\u001b[38;5;11m'http://127.0.0.1:32771/api/v2/package/'. Non-HTTPS access will be removed in a \u001b[0m", "\u001b[38;5;11mfuture version. Consider migrating to an 'HTTPS' source.\u001b[0m", "\u001b[1;38;5;2m(2/3) Promote Microsoft.NETCore.Targets 1.1.0\u001b[0m", "\u001b[38;5;11mWarning: You are running the 'push' operation with an 'HTTP' source, \u001b[0m", "\u001b[38;5;11m'http://127.0.0.1:32771/api/v2/package/'. Non-HTTPS access will be removed in a \u001b[0m", "\u001b[38;5;11mfuture version. Consider migrating to an 'HTTPS' source.\u001b[0m", "\u001b[1;38;5;2m(3/3) Promote System.Runtime 4.3.0\u001b[0m", "\u001b[38;5;11mWarning: You are running the 'push' operation with an 'HTTP' source, \u001b[0m", "\u001b[38;5;11m'http://127.0.0.1:32771/api/v2/package/'. Non-HTTPS access will be removed in a \u001b[0m", "\u001b[38;5;11mfuture version. Consider migrating to an 'HTTPS' source.\u001b[0m", "\u001b[1;38;5;2m3 package(s) promoted.\u001b[0m"} differs at index 0.
Raw output
Expected result.StdOutput to start with {"Resolving packages to promote:", "└── System.Runtime 4.3.0"}, but {"\u001b[1;38;5;2mResolving packages to promote:\u001b[0m", "└── System.Runtime 4.3.0", "\u001b[38;5;8mProcessing package System.Runtime 4.3.0\u001b[0m", "\u001b[38;5;8mNew dependency to process: Microsoft.NETCore.Platforms (>= 1.1.0)\u001b[0m", "\u001b[38;5;8mNew dependency to process: Microsoft.NETCore.Targets (>= 1.1.0)\u001b[0m", "\u001b[38;5;8mProcessing dependency Microsoft.NETCore.Platforms (>= 1.1.0)\u001b[0m", "\u001b[38;5;8mNew dependency found: Microsoft.NETCore.Platforms 1.1.0\u001b[0m", "\u001b[38;5;8mProcessing dependency Microsoft.NETCore.Targets (>= 1.1.0)\u001b[0m", "\u001b[38;5;8mNew dependency found: Microsoft.NETCore.Targets 1.1.0\u001b[0m", "\u001b[38;5;8mProcessing package Microsoft.NETCore.Platforms 1.1.0\u001b[0m", "\u001b[38;5;8mProcessing package Microsoft.NETCore.Targets 1.1.0\u001b[0m", "\u001b[1;38;5;2mFound 3 package(s) to promote:\u001b[0m", "├── Microsoft.NETCore.Platforms 1.1.0", "├── Microsoft.NETCore.Targets 1.1.0", "└── System.Runtime 4.3.0", "\u001b[1;38;5;2m(1/3) Promote Microsoft.NETCore.Platforms 1.1.0\u001b[0m", "\u001b[38;5;11mWarning: You are running the 'push' operation with an 'HTTP' source, \u001b[0m", "\u001b[38;5;11m'http://127.0.0.1:32771/api/v2/package/'. Non-HTTPS access will be removed in a \u001b[0m", "\u001b[38;5;11mfuture version. Consider migrating to an 'HTTPS' source.\u001b[0m", "\u001b[1;38;5;2m(2/3) Promote Microsoft.NETCore.Targets 1.1.0\u001b[0m", "\u001b[38;5;11mWarning: You are running the 'push' operation with an 'HTTP' source, \u001b[0m", "\u001b[38;5;11m'http://127.0.0.1:32771/api/v2/package/'. Non-HTTPS access will be removed in a \u001b[0m", "\u001b[38;5;11mfuture version. Consider migrating to an 'HTTPS' source.\u001b[0m", "\u001b[1;38;5;2m(3/3) Promote System.Runtime 4.3.0\u001b[0m", "\u001b[38;5;11mWarning: You are running the 'push' operation with an 'HTTP' source, \u001b[0m", "\u001b[38;5;11m'http://127.0.0.1:32771/api/v2/package/'. Non-HTTPS access will be removed in a \u001b[0m", "\u001b[38;5;11mfuture version. Consider migrating to an 'HTTPS' source.\u001b[0m", "\u001b[1;38;5;2m3 package(s) promoted.\u001b[0m"} differs at index 0.
   at FluentAssertions.Execution.LateBoundTestFramework.Throw(String message)
   at FluentAssertions.Execution.TestFrameworkProvider.Throw(String message)
   at FluentAssertions.Execution.DefaultAssertionStrategy.HandleFailure(String message)
   at FluentAssertions.Execution.AssertionScope.FailWith(Func`1 failReasonFunc)
   at FluentAssertions.Execution.AssertionScope.FailWith(Func`1 failReasonFunc)
   at FluentAssertions.Execution.AssertionScope.FailWith(String message, Object[] args)
   at FluentAssertions.Execution.GivenSelector`1.FailWith(String message, Object[] args)
   at FluentAssertions.Execution.GivenSelector`1.FailWith(String message, Func`2[] args)
   at FluentAssertions.Execution.GivenSelectorExtensions.AssertCollectionsHaveSameItems[TActual,TExpected](GivenSelector`1 givenSelector, ICollection`1 expected, Func`3 findIndex)
   at FluentAssertions.Collections.GenericCollectionAssertions`3.AssertCollectionStartsWith[TActual,TExpectation](IEnumerable`1 actualItems, ICollection`1 expected, Func`3 equalityComparison, String because, Object[] becauseArgs)
   at FluentAssertions.Collections.GenericCollectionAssertions`3.StartWith[TExpectation](IEnumerable`1 expectation, Func`3 equalityComparison, String because, Object[] becauseArgs)
   at FluentAssertions.Collections.GenericCollectionAssertions`3.StartWith(IEnumerable`1 expectation, String because, Object[] becauseArgs)
   at Promote.NuGet.Tests.PromoteSinglePackageTests.Promotes_a_package_with_its_dependencies_to_destination_feed() in /home/runner/work/NuGet.Promoter/NuGet.Promoter/tests/Promote.NuGet.Tests/PromoteSinglePackageTests.cs:line 30
   at Promote.NuGet.Tests.PromoteSinglePackageTests.Promotes_a_package_with_its_dependencies_to_destination_feed() in /home/runner/work/NuGet.Promoter/NuGet.Promoter/tests/Promote.NuGet.Tests/PromoteSinglePackageTests.cs:line 57
   at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted()
   at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter)
   at NUnit.Framework.Internal.AsyncToSyncAdapter.Await[TResult](Func`1 invoke)
   at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
   at NUnit.Framework.Internal.Commands.BeforeTestCommand.Execute(TestExecutionContext context)
   at NUnit.Framework.Internal.Commands.CancelAfterCommand.Execute(TestExecutionContext context)
   at NUnit.Framework.Internal.Execution.SimpleWorkItem.<>c__DisplayClass3_0.<PerformWork>b__0()
   at NUnit.Framework.Internal.ContextUtils.<>c__DisplayClass1_0`1.<DoIsolated>b__0(Object _)

new[]
{
"Resolving packages to promote:",
"└── System.Runtime 4.3.0"
}
);

result.StdOutput.Should().ContainInConsecutiveOrder(
"Found 3 package(s) to promote:",
"├── Microsoft.NETCore.Platforms 1.1.0",
"├── Microsoft.NETCore.Targets 1.1.0",
"└── System.Runtime 4.3.0"
);

result.StdOutput.Should().ContainInOrder(
"(1/3) Promote Microsoft.NETCore.Platforms 1.1.0",
"(2/3) Promote Microsoft.NETCore.Targets 1.1.0",
"(3/3) Promote System.Runtime 4.3.0",
"3 package(s) promoted."
);

result.StdError.Should().BeEmpty();
result.ExitCode.Should().Be(0);

await AssertContainsVersions(destinationRepo, "System.Runtime", new[] { new NuGetVersion(4, 3, 0) });
await AssertContainsVersions(destinationRepo, "Microsoft.NETCore.Platforms", new[] { new NuGetVersion(1, 1, 0) });
await AssertContainsVersions(destinationRepo, "Microsoft.NETCore.Targets", new[] { new NuGetVersion(1, 1, 0) });
}

private static async Task AssertContainsVersions(INuGetRepository repo, string packageId, params NuGetVersion[] expectedVersions)
{
var netCorePlatformsPackages = await repo.Packages.GetAllVersions(packageId);
netCorePlatformsPackages.IsSuccess.Should().BeTrue();
netCorePlatformsPackages.Value.Should().Contain(expectedVersions);
}
}
22 changes: 22 additions & 0 deletions tests/Promote.NuGet.Tests/ToolVersionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Diagnostics;

namespace Promote.NuGet.Tests;

[TestFixture]
public class ToolVersionTests
{
[Test, CancelAfter(10_000)]
public async Task Returns_version_of_the_tool()
{
var expectedVersion = FileVersionInfo.GetVersionInfo(typeof(Program).Assembly.Location).ProductVersion ?? string.Empty;
var expectedVersionLines = expectedVersion.Chunk(80).Select(x => new string(x)).ToList();

// Act
var result = await PromoteNugetProcessRunner.RunForResultAsync("--version");

// Assert
result.StdOutput.Should().BeEquivalentTo(expectedVersionLines);
result.StdError.Should().BeEmpty();
result.ExitCode.Should().Be(0);
}
}

0 comments on commit ed665ba

Please sign in to comment.