using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using AwesomeAssertions;
using ICSharpCode.ILSpy.Updates;
using NUnit.Framework;
namespace ICSharpCode.ILSpy.Tests;
[TestFixture]
public class UpdateServiceTests
{
[Test]
public async Task GetLatestVersionAsync_UsesReleaseTag_WhenReleaseTagIsPresent()
{
const string xml = """
10.0.0.0
v10.0
https://example.com/ignored.zip
""";
using var client = new HttpClient(new StubHttpMessageHandler(xml));
var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
result.Version.Should().Be(new Version(10, 0, 0, 0));
result.DownloadUrl.Should().Be("https://github.com/icsharpcode/ILSpy/releases/tag/v10.0");
}
[Test]
public async Task GetLatestVersionAsync_ReturnsNullDownloadUrl_WhenReleaseTagContainsPathTraversalAttempt()
{
const string xml = """
10.0.0.0
../malicious
https://example.com/ignored.zip
""";
using var client = new HttpClient(new StubHttpMessageHandler(xml));
var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
result.Version.Should().Be(new Version(10, 0, 0, 0));
result.DownloadUrl.Should().BeNull();
}
[Test]
public async Task GetLatestVersionAsync_UsesDownloadUrl_WhenReleaseTagIsMissing()
{
const string xml = """
10.0.0.0
https://github.com/icsharpcode/ILSpy/releases/tag/v10.0
""";
using var client = new HttpClient(new StubHttpMessageHandler(xml));
var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
result.Version.Should().Be(new Version(10, 0, 0, 0));
result.DownloadUrl.Should().Be("https://github.com/icsharpcode/ILSpy/releases/tag/v10.0");
}
[Test]
public async Task GetLatestVersionAsync_UsesDownloadUrl_ButFailsBecauseBaseUrlDoesntMatch()
{
const string xml = """
10.0.0.0
https://example.com/ilspy.zip
""";
using var client = new HttpClient(new StubHttpMessageHandler(xml));
var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
result.Version.Should().Be(new Version(10, 0, 0, 0));
result.DownloadUrl.Should().BeNull();
}
sealed class StubHttpMessageHandler(string responseContent) : HttpMessageHandler
{
protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) {
Content = new StringContent(responseContent)
});
}
}
}