Skip to content

Commit cb9f10e

Browse files
Add tests
1 parent a6ab47a commit cb9f10e

File tree

3 files changed

+97
-2
lines changed

3 files changed

+97
-2
lines changed

ILSpy.Tests/ILSpy.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<Compile Include="Analyzers\TypeUsedByAnalyzerTests.cs" />
5050
<Compile Include="CommandLineArgumentsTests.cs" />
5151
<Compile Include="ResourceReaderWriterTests.cs" />
52+
<Compile Include="UpdateServiceTests.cs" />
5253
</ItemGroup>
5354

5455
<ItemGroup>

ILSpy.Tests/UpdateServiceTests.cs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using System;
2+
using System.Net;
3+
using System.Net.Http;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
7+
using AwesomeAssertions;
8+
9+
using ICSharpCode.ILSpy.Updates;
10+
11+
using NUnit.Framework;
12+
13+
namespace ICSharpCode.ILSpy.Tests;
14+
15+
[TestFixture]
16+
public class UpdateServiceTests
17+
{
18+
[Test]
19+
public async Task GetLatestVersionAsync_UsesReleaseTag_WhenReleaseTagIsPresent()
20+
{
21+
const string xml = """
22+
<root>
23+
<band id="stable">
24+
<latestVersion>10.0.0.0</latestVersion>
25+
<releaseTag>v10.0</releaseTag>
26+
<downloadUrl>https://example.com/ignored.zip</downloadUrl>
27+
</band>
28+
</root>
29+
""";
30+
31+
using var client = new HttpClient(new StubHttpMessageHandler(xml));
32+
33+
var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
34+
35+
result.Version.Should().Be(new Version(10, 0, 0, 0));
36+
result.DownloadUrl.Should().Be("https://github.com/icsharpcode/ILSpy/releases/tag/v10.0");
37+
}
38+
39+
[Test]
40+
public async Task GetLatestVersionAsync_ReturnsNullDownloadUrl_WhenReleaseTagContainsPathTraversalAttempt()
41+
{
42+
const string xml = """
43+
<root>
44+
<band id="stable">
45+
<latestVersion>10.0.0.0</latestVersion>
46+
<releaseTag>../malicious</releaseTag>
47+
<downloadUrl>https://example.com/ignored.zip</downloadUrl>
48+
</band>
49+
</root>
50+
""";
51+
52+
using var client = new HttpClient(new StubHttpMessageHandler(xml));
53+
54+
var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
55+
56+
result.Version.Should().Be(new Version(10, 0, 0, 0));
57+
result.DownloadUrl.Should().BeNull();
58+
}
59+
60+
[Test]
61+
public async Task GetLatestVersionAsync_UsesDownloadUrl_WhenReleaseTagIsMissing()
62+
{
63+
const string xml = """
64+
<root>
65+
<band id="stable">
66+
<latestVersion>10.0.0.0</latestVersion>
67+
<downloadUrl>https://example.com/ilspy.zip</downloadUrl>
68+
</band>
69+
</root>
70+
""";
71+
72+
using var client = new HttpClient(new StubHttpMessageHandler(xml));
73+
74+
var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
75+
76+
result.Version.Should().Be(new Version(10, 0, 0, 0));
77+
result.DownloadUrl.Should().Be("https://example.com/ilspy.zip");
78+
}
79+
80+
sealed class StubHttpMessageHandler(string responseContent) : HttpMessageHandler
81+
{
82+
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
83+
{
84+
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) {
85+
Content = new StringContent(responseContent)
86+
});
87+
}
88+
}
89+
}

ILSpy/Updates/UpdateService.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,18 @@ internal static class UpdateService
3636

3737
public static async Task<AvailableVersionInfo> GetLatestVersionAsync()
3838
{
39-
var client = new HttpClient(new HttpClientHandler() {
39+
using var client = new HttpClient(new HttpClientHandler() {
4040
UseProxy = true,
4141
UseDefaultCredentials = true
4242
});
4343

44+
return await GetLatestVersionAsync(client, UpdateUrl).ConfigureAwait(false);
45+
}
46+
47+
internal static async Task<AvailableVersionInfo> GetLatestVersionAsync(HttpClient client, Uri updateUrl)
48+
{
4449
// Issue #3707: Remove 301 redirect logic once ilspy.net CNAME gone
45-
string data = await GetWithRedirectsAsync(client, UpdateUrl).ConfigureAwait(false);
50+
string data = await GetWithRedirectsAsync(client, updateUrl).ConfigureAwait(false);
4651

4752
XDocument doc = XDocument.Load(new StringReader(data));
4853
var bands = doc.Root.Elements("band").ToList();

0 commit comments

Comments
 (0)