From f52bb92dfc1f85b8646d007c5654e10e43ae45e6 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Tue, 26 Dec 2023 21:56:40 +0100 Subject: [PATCH 1/8] - add rate limiting support for license downloads - do actually download licenses in tests - use different profiles for test and for app code --- .github/workflows/action.yml | 12 ++++++- .../workflows/assets/App/allowedLicenses.json | 1 + .../assets/{ => App}/ignorePackages.json | 0 .../App/overwritePackageInformation.json | 1 + .../assets/{ => App}/projectsToCheck.json | 0 .../assets/App/urlToLicenseMapping.json | 2 ++ .../assets/{ => Tests}/allowedLicenses.json | 0 .../assets/Tests/ignorePackages.json | 1 + .../overwritePackageInformation.json | 0 .../assets/Tests/projectsToCheck.json | 1 + .../{ => Tests}/urlToLicenseMapping.json | 0 .../HttpClientWrapper/FileDownloader.cs | 33 ++++++++++++++++--- 12 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/assets/App/allowedLicenses.json rename .github/workflows/assets/{ => App}/ignorePackages.json (100%) create mode 100644 .github/workflows/assets/App/overwritePackageInformation.json rename .github/workflows/assets/{ => App}/projectsToCheck.json (100%) create mode 100644 .github/workflows/assets/App/urlToLicenseMapping.json rename .github/workflows/assets/{ => Tests}/allowedLicenses.json (100%) create mode 100644 .github/workflows/assets/Tests/ignorePackages.json rename .github/workflows/assets/{ => Tests}/overwritePackageInformation.json (100%) create mode 100644 .github/workflows/assets/Tests/projectsToCheck.json rename .github/workflows/assets/{ => Tests}/urlToLicenseMapping.json (100%) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 0bdba9e2..f5f1102e 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -65,6 +65,7 @@ jobs: strategy: matrix: targetFramework: [net6.0, net7.0, net8.0] + project: [App, Tests] include: - targetFramework: net6.0 @@ -90,4 +91,13 @@ jobs: run: dotnet publish ./src/NuGetUtility/NuGetUtility.csproj --configuration Release -o ./release -f ${{ matrix.targetFramework }} --no-restore - name: check - run: dotnet ./release/NuGetUtility.dll -ji ./.github/workflows/assets/projectsToCheck.json -t -a ./.github/workflows/assets/allowedLicenses.json -o JsonPretty -override ./.github/workflows/assets/overwritePackageInformation.json -ignore ./.github/workflows/assets/ignorePackages.json -mapping ./.github/workflows/assets/urlToLicenseMapping.json + run: dotnet ./release/NuGetUtility.dll -ji ./.github/workflows/assets/${{ matrix.project }}/projectsToCheck.json -t -a ./.github/workflows/assets/${{ matrix.project }}/allowedLicenses.json -o JsonPretty -override ./.github/workflows/assets/${{ matrix.project }}/overwritePackageInformation.json -ignore ./.github/workflows/assets/${{ matrix.project }}/ignorePackages.json -mapping ./.github/workflows/assets/${{ matrix.project }}/urlToLicenseMapping.json -d ./licenses/${{ matrix.project }}/${{ matrix.targetFramework }} + + - name: show downloaded licenses + shell: pwsh + run: | + foreach($file in Get-ChildItem -Path ./licenses/${{ matrix.project }}/${{ matrix.targetFramework }}) + { + $file.FullName + Get-Content $file.FullName + } diff --git a/.github/workflows/assets/App/allowedLicenses.json b/.github/workflows/assets/App/allowedLicenses.json new file mode 100644 index 00000000..790c6abc --- /dev/null +++ b/.github/workflows/assets/App/allowedLicenses.json @@ -0,0 +1 @@ +["MIT","Apache-2.0","MS-EULA"] diff --git a/.github/workflows/assets/ignorePackages.json b/.github/workflows/assets/App/ignorePackages.json similarity index 100% rename from .github/workflows/assets/ignorePackages.json rename to .github/workflows/assets/App/ignorePackages.json diff --git a/.github/workflows/assets/App/overwritePackageInformation.json b/.github/workflows/assets/App/overwritePackageInformation.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/.github/workflows/assets/App/overwritePackageInformation.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/.github/workflows/assets/projectsToCheck.json b/.github/workflows/assets/App/projectsToCheck.json similarity index 100% rename from .github/workflows/assets/projectsToCheck.json rename to .github/workflows/assets/App/projectsToCheck.json diff --git a/.github/workflows/assets/App/urlToLicenseMapping.json b/.github/workflows/assets/App/urlToLicenseMapping.json new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/.github/workflows/assets/App/urlToLicenseMapping.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/.github/workflows/assets/allowedLicenses.json b/.github/workflows/assets/Tests/allowedLicenses.json similarity index 100% rename from .github/workflows/assets/allowedLicenses.json rename to .github/workflows/assets/Tests/allowedLicenses.json diff --git a/.github/workflows/assets/Tests/ignorePackages.json b/.github/workflows/assets/Tests/ignorePackages.json new file mode 100644 index 00000000..6628f6d6 --- /dev/null +++ b/.github/workflows/assets/Tests/ignorePackages.json @@ -0,0 +1 @@ +["NETStandard.Library"] diff --git a/.github/workflows/assets/overwritePackageInformation.json b/.github/workflows/assets/Tests/overwritePackageInformation.json similarity index 100% rename from .github/workflows/assets/overwritePackageInformation.json rename to .github/workflows/assets/Tests/overwritePackageInformation.json diff --git a/.github/workflows/assets/Tests/projectsToCheck.json b/.github/workflows/assets/Tests/projectsToCheck.json new file mode 100644 index 00000000..4315b4c6 --- /dev/null +++ b/.github/workflows/assets/Tests/projectsToCheck.json @@ -0,0 +1 @@ +["./tests/NuGetUtility.Test/NuGetUtility.Test.csproj"] diff --git a/.github/workflows/assets/urlToLicenseMapping.json b/.github/workflows/assets/Tests/urlToLicenseMapping.json similarity index 100% rename from .github/workflows/assets/urlToLicenseMapping.json rename to .github/workflows/assets/Tests/urlToLicenseMapping.json diff --git a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs index 6f580369..192b221f 100644 --- a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs +++ b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs @@ -1,9 +1,14 @@ -namespace NuGetUtility.Wrapper.HttpClientWrapper +using System; + +namespace NuGetUtility.Wrapper.HttpClientWrapper { public class FileDownloader : IFileDownloader { + private readonly SemaphoreSlim _parallelDownloadLimiter = new SemaphoreSlim(10, 10); private readonly HttpClient _client; private readonly string _downloadDirectory; + private const int EXPONENTIAL_BACKOFF_WAIT_TIME_MILLISECONDS = 200; + private const int MAX_RETRIES = 5; public FileDownloader(HttpClient client, string downloadDirectory) { @@ -13,10 +18,30 @@ public FileDownloader(HttpClient client, string downloadDirectory) public async Task DownloadFile(Uri url, string fileName) { - await using FileStream file = File.OpenWrite(Path.Combine(_downloadDirectory, fileName)); - await using Stream downloadStream = await _client.GetStreamAsync(url); + await _parallelDownloadLimiter.WaitAsync(); + try + { + for (int i = 0; i < MAX_RETRIES; i++) + { + await using FileStream file = File.OpenWrite(Path.Combine(_downloadDirectory, fileName)); + var request = new HttpRequestMessage(HttpMethod.Get, url); + + HttpResponseMessage response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + response.EnsureSuccessStatusCode(); + if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests) + { + await Task.Delay((int)Math.Pow(EXPONENTIAL_BACKOFF_WAIT_TIME_MILLISECONDS, i + 1)); + continue; + } + using Stream downloadStream = await response.Content.ReadAsStreamAsync(); - await downloadStream.CopyToAsync(file); + await downloadStream.CopyToAsync(file); + } + } + finally + { + _parallelDownloadLimiter.Release(); + } } } } From 6c3dd5b5e4249f812c8b735757ed79f2f44b5783 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Tue, 26 Dec 2023 22:01:32 +0100 Subject: [PATCH 2/8] add fare to the overwrite packages, as it's license url is no longer available --- .../workflows/assets/App/overwritePackageInformation.json | 8 +++++++- .github/workflows/assets/App/urlToLicenseMapping.json | 2 +- .../assets/Tests/overwritePackageInformation.json | 2 +- .github/workflows/assets/Tests/urlToLicenseMapping.json | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/assets/App/overwritePackageInformation.json b/.github/workflows/assets/App/overwritePackageInformation.json index 0637a088..d003c890 100644 --- a/.github/workflows/assets/App/overwritePackageInformation.json +++ b/.github/workflows/assets/App/overwritePackageInformation.json @@ -1 +1,7 @@ -[] \ No newline at end of file +[ + { + "Id": "Fare", + "Version": "2.1.1", + "License": "MIT" + } +] diff --git a/.github/workflows/assets/App/urlToLicenseMapping.json b/.github/workflows/assets/App/urlToLicenseMapping.json index 7a73a41b..2c63c085 100644 --- a/.github/workflows/assets/App/urlToLicenseMapping.json +++ b/.github/workflows/assets/App/urlToLicenseMapping.json @@ -1,2 +1,2 @@ { -} \ No newline at end of file +} diff --git a/.github/workflows/assets/Tests/overwritePackageInformation.json b/.github/workflows/assets/Tests/overwritePackageInformation.json index ea0673ef..e8574574 100644 --- a/.github/workflows/assets/Tests/overwritePackageInformation.json +++ b/.github/workflows/assets/Tests/overwritePackageInformation.json @@ -79,4 +79,4 @@ "Version": "2.1.1", "License": "MIT" } -] \ No newline at end of file +] diff --git a/.github/workflows/assets/Tests/urlToLicenseMapping.json b/.github/workflows/assets/Tests/urlToLicenseMapping.json index 6452f9c5..ba847950 100644 --- a/.github/workflows/assets/Tests/urlToLicenseMapping.json +++ b/.github/workflows/assets/Tests/urlToLicenseMapping.json @@ -1,3 +1,3 @@ { "https://raw.githubusercontent.com/bchavez/Bogus/master/LICENSE": "MIT" -} \ No newline at end of file +} From 63e6b16b81f7e949bd2098939d1acd39a477821a Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Tue, 26 Dec 2023 22:04:02 +0100 Subject: [PATCH 3/8] fix project selection --- .github/workflows/assets/App/projectsToCheck.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/assets/App/projectsToCheck.json b/.github/workflows/assets/App/projectsToCheck.json index 5b4093b9..dea169f2 100644 --- a/.github/workflows/assets/App/projectsToCheck.json +++ b/.github/workflows/assets/App/projectsToCheck.json @@ -1 +1 @@ -["./src/NuGetUtility/NuGetUtility.csproj", "./tests/NuGetUtility.Test/NuGetUtility.Test.csproj"] +["./src/NuGetUtility/NuGetUtility.csproj"] From d7c011061b0993d491c2663c46c2e7dec325b5a7 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Tue, 26 Dec 2023 22:10:03 +0100 Subject: [PATCH 4/8] colorize downloaded file name to distinguish from file content --- .github/workflows/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index f5f1102e..22020b5a 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -98,6 +98,6 @@ jobs: run: | foreach($file in Get-ChildItem -Path ./licenses/${{ matrix.project }}/${{ matrix.targetFramework }}) { - $file.FullName + Write-Host $file.FullName -ForegroundColor Yellow Get-Content $file.FullName } From 599b8f6c8ed912d24f0e445fbd8957f7e031c108 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Tue, 26 Dec 2023 22:19:07 +0100 Subject: [PATCH 5/8] organize output --- .github/workflows/action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 22020b5a..19596b6e 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -98,6 +98,7 @@ jobs: run: | foreach($file in Get-ChildItem -Path ./licenses/${{ matrix.project }}/${{ matrix.targetFramework }}) { - Write-Host $file.FullName -ForegroundColor Yellow + Write-Host ::group::$file Get-Content $file.FullName + Write-Host ::endgroup:: } From 7b6ad68eeb3e00cf59bd70f6f95ae6e8aed15e67 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Tue, 26 Dec 2023 22:29:24 +0100 Subject: [PATCH 6/8] don't overwrite Fare in the app check, as it is not needed --- .../workflows/assets/App/overwritePackageInformation.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/assets/App/overwritePackageInformation.json b/.github/workflows/assets/App/overwritePackageInformation.json index d003c890..0d4f101c 100644 --- a/.github/workflows/assets/App/overwritePackageInformation.json +++ b/.github/workflows/assets/App/overwritePackageInformation.json @@ -1,7 +1,2 @@ [ - { - "Id": "Fare", - "Version": "2.1.1", - "License": "MIT" - } ] From 427aa8a146336f97b238494e0c65c4e3e3081bea Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Thu, 28 Dec 2023 09:20:43 +0100 Subject: [PATCH 7/8] Properly break out of download loop --- src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs index 192b221f..5d33d397 100644 --- a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs +++ b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace NuGetUtility.Wrapper.HttpClientWrapper { @@ -36,6 +36,7 @@ public async Task DownloadFile(Uri url, string fileName) using Stream downloadStream = await response.Content.ReadAsStreamAsync(); await downloadStream.CopyToAsync(file); + return; } } finally From 3e68d25831b9f7ba3f190c753342b083de495fb4 Mon Sep 17 00:00:00 2001 From: Simon Ensslen Date: Thu, 28 Dec 2023 19:27:02 +0100 Subject: [PATCH 8/8] make file downloading cancellable --- .../LicenseValidator/LicenseValidator.cs | 17 ++++-- src/NuGetUtility/Program.cs | 2 +- .../HttpClientWrapper/FileDownloader.cs | 12 ++-- .../HttpClientWrapper/IFileDownloader.cs | 2 +- .../HttpClientWrapper/NopFileDownloader.cs | 2 +- .../LicenseValidator/LicenseValidatorTest.cs | 57 +++++++++++-------- 6 files changed, 54 insertions(+), 38 deletions(-) diff --git a/src/NuGetUtility/LicenseValidator/LicenseValidator.cs b/src/NuGetUtility/LicenseValidator/LicenseValidator.cs index a851321a..d2c63983 100644 --- a/src/NuGetUtility/LicenseValidator/LicenseValidator.cs +++ b/src/NuGetUtility/LicenseValidator/LicenseValidator.cs @@ -28,7 +28,8 @@ public LicenseValidator(IImmutableDictionary licenseMapping, } public async Task> Validate( - IAsyncEnumerable packages) + IAsyncEnumerable packages, + CancellationToken token) { var result = new ConcurrentDictionary(); await foreach (ReferencedPackageWithContext info in packages) @@ -45,7 +46,7 @@ public async Task> Validate( } else if (info.PackageInfo.LicenseUrl != null) { - await ValidateLicenseByUrl(info.PackageInfo, info.Context, result); + await ValidateLicenseByUrl(info.PackageInfo, info.Context, result, token); } else { @@ -150,14 +151,20 @@ private void ValidateLicenseByMetadata(IPackageMetadata info, private async Task ValidateLicenseByUrl(IPackageMetadata info, string context, - ConcurrentDictionary result) + ConcurrentDictionary result, + CancellationToken token) { if (info.LicenseUrl!.IsAbsoluteUri) { try { await _fileDownloader.DownloadFile(info.LicenseUrl, - $"{info.Identity.Id}__{info.Identity.Version}.html"); + $"{info.Identity.Id}__{info.Identity.Version}.html", + token); + } + catch (OperationCanceledException) + { + // swallow cancellation } catch (Exception e) { @@ -207,7 +214,7 @@ private bool IsLicenseValid(string licenseId) return true; } - return _allowedLicenses.Any(l => l.Equals(licenseId)); + return _allowedLicenses.Any(allowedLicense => allowedLicense.Equals(licenseId)); } private string GetLicenseNotAllowedMessage(string license) diff --git a/src/NuGetUtility/Program.cs b/src/NuGetUtility/Program.cs index cd2f4cea..3ac42afe 100644 --- a/src/NuGetUtility/Program.cs +++ b/src/NuGetUtility/Program.cs @@ -124,7 +124,7 @@ private async Task OnExecuteAsync(CancellationToken cancellationToken) }); IAsyncEnumerable downloadedLicenseInformation = packagesForProject.SelectMany(p => GetPackageInfos(p, overridePackageInformation, cancellationToken)); - var results = (await validator.Validate(downloadedLicenseInformation)).ToList(); + var results = (await validator.Validate(downloadedLicenseInformation, cancellationToken)).ToList(); if (projectReaderExceptions.Any()) { diff --git a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs index 5d33d397..a62edc6f 100644 --- a/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs +++ b/src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs @@ -16,9 +16,9 @@ public FileDownloader(HttpClient client, string downloadDirectory) _downloadDirectory = downloadDirectory; } - public async Task DownloadFile(Uri url, string fileName) + public async Task DownloadFile(Uri url, string fileName, CancellationToken token) { - await _parallelDownloadLimiter.WaitAsync(); + await _parallelDownloadLimiter.WaitAsync(token); try { for (int i = 0; i < MAX_RETRIES; i++) @@ -26,16 +26,16 @@ public async Task DownloadFile(Uri url, string fileName) await using FileStream file = File.OpenWrite(Path.Combine(_downloadDirectory, fileName)); var request = new HttpRequestMessage(HttpMethod.Get, url); - HttpResponseMessage response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + HttpResponseMessage response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token); response.EnsureSuccessStatusCode(); if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests) { - await Task.Delay((int)Math.Pow(EXPONENTIAL_BACKOFF_WAIT_TIME_MILLISECONDS, i + 1)); + await Task.Delay((int)Math.Pow(EXPONENTIAL_BACKOFF_WAIT_TIME_MILLISECONDS, i + 1), token); continue; } - using Stream downloadStream = await response.Content.ReadAsStreamAsync(); + using Stream downloadStream = await response.Content.ReadAsStreamAsync(token); - await downloadStream.CopyToAsync(file); + await downloadStream.CopyToAsync(file, token); return; } } diff --git a/src/NuGetUtility/Wrapper/HttpClientWrapper/IFileDownloader.cs b/src/NuGetUtility/Wrapper/HttpClientWrapper/IFileDownloader.cs index f5e0324c..a60e8a82 100644 --- a/src/NuGetUtility/Wrapper/HttpClientWrapper/IFileDownloader.cs +++ b/src/NuGetUtility/Wrapper/HttpClientWrapper/IFileDownloader.cs @@ -2,6 +2,6 @@ { public interface IFileDownloader { - public Task DownloadFile(Uri url, string fileName); + public Task DownloadFile(Uri url, string fileName, CancellationToken token); } } diff --git a/src/NuGetUtility/Wrapper/HttpClientWrapper/NopFileDownloader.cs b/src/NuGetUtility/Wrapper/HttpClientWrapper/NopFileDownloader.cs index b37264fe..11eebf9d 100644 --- a/src/NuGetUtility/Wrapper/HttpClientWrapper/NopFileDownloader.cs +++ b/src/NuGetUtility/Wrapper/HttpClientWrapper/NopFileDownloader.cs @@ -2,7 +2,7 @@ { public class NopFileDownloader : IFileDownloader { - public Task DownloadFile(Uri url, string fileName) + public Task DownloadFile(Uri url, string fileName, CancellationToken token) { return Task.CompletedTask; } diff --git a/tests/NuGetUtility.Test/LicenseValidator/LicenseValidatorTest.cs b/tests/NuGetUtility.Test/LicenseValidator/LicenseValidatorTest.cs index c3157fb4..7747e755 100644 --- a/tests/NuGetUtility.Test/LicenseValidator/LicenseValidatorTest.cs +++ b/tests/NuGetUtility.Test/LicenseValidator/LicenseValidatorTest.cs @@ -27,6 +27,7 @@ public void SetUp() _context = fixture.Create(); _projectUrl = fixture.Create(); _ignoredLicenses = fixture.Create(); + _token = new CancellationTokenSource(); _uut = new NuGetUtility.LicenseValidator.LicenseValidator(_licenseMapping, _allowedLicenses, @@ -34,6 +35,12 @@ public void SetUp() _ignoredLicenses); } + [TearDown] + public void TearDown() + { + _token.Dispose(); + } + private NuGetUtility.LicenseValidator.LicenseValidator _uut = null!; private IImmutableDictionary _licenseMapping = null!; private IEnumerable _allowedLicenses = null!; @@ -41,12 +48,13 @@ public void SetUp() private IFileDownloader _fileDownloader = null!; private Uri _projectUrl = null!; private string[] _ignoredLicenses = null!; + private CancellationTokenSource _token = null!; [Test] public async Task ValidatingEmptyList_Should_ReturnEmptyValidatedLicenses() { IAsyncEnumerable emptyListToValidate = Enumerable.Empty().AsAsyncEnumerable(); - IEnumerable results = await _uut.Validate(emptyListToValidate); + IEnumerable results = await _uut.Validate(emptyListToValidate, _token.Token); CollectionAssert.AreEqual(Enumerable.Empty(), results); } @@ -101,7 +109,7 @@ public async Task ValidatingLicenses_Should_IgnorePackage_If_PackageNameMatchesE IPackageMetadata package = SetupPackage(packageId, packageVersion); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -129,7 +137,7 @@ public async Task ValidatingLicenses_Should_NotIgnorePackage_If_PackageNameDoesN IPackageMetadata package = SetupPackageWithExpressionLicenseInformation(packageId, packageVersion, license); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -159,7 +167,7 @@ public async Task ValidatingLicenses_Should_IgnorePackage_If_IgnoreWildcardMatch IPackageMetadata package = SetupPackage(packageId, packageVersion); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -189,7 +197,7 @@ public async Task ValidatingLicenses_Should_IgnorePackage_If_IgnoreWildcardMatch IPackageMetadata package = SetupPackage(packageId, packageVersion); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -220,7 +228,7 @@ public async Task ValidatingLicenses_Should_IgnorePackage_If_IgnoreWildcardMatch IPackageMetadata package = SetupPackage(packageId, packageVersion); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -247,7 +255,7 @@ public async Task ValidatingLicenses_Should_IgnorePackage_If_IgnoreWildcardMatch IPackageMetadata package = SetupPackage(packageId, packageVersion); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -275,7 +283,7 @@ public async Task ValidatingLicensesWithExpressionLicenseInformation_Should_Give IPackageMetadata package = SetupPackageWithExpressionLicenseInformation(packageId, packageVersion, license); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -303,7 +311,7 @@ public async Task ValidatingLicensesWithOverwriteLicenseInformation_Should_GiveC IPackageMetadata package = SetupPackageWithOverwriteLicenseInformation(packageId, packageVersion, license); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -340,7 +348,7 @@ public async Task ValidatingLicensesWithMatchingLicenseUrl_Should_GiveCorrectVal KeyValuePair mappingLicense = _licenseMapping.Shuffle(34561).First(); IPackageMetadata package = SetupPackageWithLicenseUrl(packageId, packageVersion, mappingLicense.Key); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -368,7 +376,7 @@ public async Task ValidatingLicensesWithMatchingLicenseUrl_Should_GiveCorrectVal IPackageMetadata package = SetupPackageWithLicenseUrl(packageId, packageVersion, licenseUrl); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -399,7 +407,7 @@ public async Task ValidatingLicensesWithNotSupportedLicenseMetadata_Should_GiveC IPackageMetadata package = SetupPackageWithLicenseInformationOfType(packageId, packageVersion, license, licenseType); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -431,7 +439,7 @@ public async Task ValidatingLicensesWithoutLicenseInformation_Should_GiveCorrect IPackageMetadata package = SetupPackage(packageId, packageVersion); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -459,7 +467,7 @@ public async Task ValidatingLicensesWithExpressionLicenseInformation_Should_Give { IPackageMetadata package = SetupPackageWithExpressionLicenseInformation(packageId, packageVersion, license); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -487,7 +495,7 @@ public async Task ValidatingLicensesWithOverwriteLicenseInformation_Should_GiveC { IPackageMetadata package = SetupPackageWithOverwriteLicenseInformation(packageId, packageVersion, license); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -515,7 +523,7 @@ public async Task ValidatingLicensesWithExpressionLicenseInformation_Should_Give string validLicense = _allowedLicenses.Shuffle(135643).First(); IPackageMetadata package = SetupPackageWithExpressionLicenseInformation(packageId, packageVersion, validLicense); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -538,7 +546,7 @@ public async Task ValidatingLicensesWithOverwriteLicenseInformation_Should_GiveC string validLicense = _allowedLicenses.Shuffle(135643).First(); IPackageMetadata package = SetupPackageWithOverwriteLicenseInformation(packageId, packageVersion, validLicense); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -561,7 +569,7 @@ public async Task ValidatingLicensesWithMatchingUrlInformation_Should_GiveCorrec KeyValuePair urlMatch = _licenseMapping.Shuffle(765).First(); IPackageMetadata package = SetupPackageWithLicenseUrl(packageId, packageVersion, urlMatch.Key); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -589,10 +597,11 @@ public async Task ValidatingLicensesWithUrlInformation_Should_StartDownloadingSa KeyValuePair urlMatch = _licenseMapping.Shuffle(4567).First(); IPackageMetadata package = SetupPackageWithLicenseUrl(packageId, packageVersion, urlMatch.Key); - _ = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + _ = await _uut.Validate(CreateInput(package, _context), _token.Token); await _fileDownloader.Received(1).DownloadFile(package.LicenseUrl!, - $"{package.Identity.Id}__{package.Identity.Version}.html"); + $"{package.Identity.Id}__{package.Identity.Version}.html", + _token.Token); } [Test] @@ -603,11 +612,11 @@ public void ValidatingLicensesWithUrlInformation_Should_ThrowLicenseDownloadInfo { KeyValuePair urlMatch = _licenseMapping.Shuffle(12345).First(); IPackageMetadata package = SetupPackageWithLicenseUrl(packageId, packageVersion, urlMatch.Key); - _fileDownloader.When(m => m.DownloadFile(package.LicenseUrl!, Arg.Any())) + _fileDownloader.When(m => m.DownloadFile(package.LicenseUrl!, Arg.Any(), Arg.Any())) .Do(_ => throw new Exception()); LicenseDownloadException? exception = - Assert.ThrowsAsync(() => _uut.Validate(LicenseValidatorTest.CreateInput(package, _context))); + Assert.ThrowsAsync(() => _uut.Validate(CreateInput(package, _context), _token.Token)); Assert.IsInstanceOf(exception!.InnerException); Assert.AreEqual( $"Failed to download license for package {packageId} ({packageVersion}).\nContext: {_context}", @@ -627,7 +636,7 @@ public async Task ValidatingLicensesWithMatchingUrlInformation_Should_GiveCorrec _ignoredLicenses); IPackageMetadata package = SetupPackageWithLicenseUrl(packageId, packageVersion, urlMatch.Key); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[] @@ -650,7 +659,7 @@ public async Task ValidatingLicensesWithNotMatchingUrlInformation_Should_GiveCor { IPackageMetadata package = SetupPackageWithLicenseUrl(packageId, packageVersion, licenseUrl); - IEnumerable result = await _uut.Validate(LicenseValidatorTest.CreateInput(package, _context)); + IEnumerable result = await _uut.Validate(CreateInput(package, _context), _token.Token); Assert.That(result, Is.EquivalentTo(new[]