dependabot-nuget 0.311.0 → 0.313.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Run.cs +2 -2
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +7 -0
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/BadResponseException.cs +12 -0
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +121 -9
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +64 -17
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/UnknownError.cs +12 -2
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/HttpApiHandler.cs +19 -50
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/IApiHandler.cs +57 -7
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +10 -5
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +13 -1
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +15 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/VersionFinderTests.cs +74 -1
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Clone/CloneWorkerTests.cs +1 -1
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +3 -9
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +1 -2
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +58 -2
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/HttpApiHandlerTests.cs +157 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/JobErrorBaseTests.cs +86 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MessageReportTests.cs +1 -2
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +227 -6
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +40 -11
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/TestApiHandler.cs +2 -39
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestHttpServer.cs +9 -5
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackageReferenceUpdaterTests.cs +99 -1
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +16 -0
  27. metadata +26 -23
@@ -1,9 +1,12 @@
1
1
  using System.Collections.Immutable;
2
+ using System.Text.Json;
2
3
 
3
4
  using NuGet.Frameworks;
4
5
  using NuGet.Versioning;
5
6
 
6
7
  using NuGetUpdater.Core.Analyze;
8
+ using NuGetUpdater.Core.Run;
9
+ using NuGetUpdater.Core.Run.ApiModel;
7
10
  using NuGetUpdater.Core.Test.Update;
8
11
  using NuGetUpdater.Core.Test.Utilities;
9
12
 
@@ -11,7 +14,7 @@ using Xunit;
11
14
 
12
15
  namespace NuGetUpdater.Core.Test.Analyze;
13
16
 
14
- public class VersionFinderTests
17
+ public class VersionFinderTests : TestBase
15
18
  {
16
19
  [Fact]
17
20
  public void VersionFilter_VersionInIgnoredVersions_ReturnsFalse()
@@ -223,4 +226,74 @@ public class VersionFinderTests
223
226
  var expected = new[] { "2.0.0" };
224
227
  AssertEx.Equal(expected, actual);
225
228
  }
229
+
230
+ [Fact]
231
+ public async Task FeedReturnsBadJson()
232
+ {
233
+ // arrange
234
+ using var http = TestHttpServer.CreateTestStringServer(url =>
235
+ {
236
+ var uri = new Uri(url, UriKind.Absolute);
237
+ var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
238
+ return uri.PathAndQuery switch
239
+ {
240
+ // initial and search query are good, update should be possible...
241
+ "/index.json" => (200, $$"""
242
+ {
243
+ "version": "3.0.0",
244
+ "resources": [
245
+ {
246
+ "@id": "{{baseUrl}}/download",
247
+ "@type": "PackageBaseAddress/3.0.0"
248
+ },
249
+ {
250
+ "@id": "{{baseUrl}}/query",
251
+ "@type": "SearchQueryService"
252
+ },
253
+ {
254
+ "@id": "{{baseUrl}}/registrations",
255
+ "@type": "RegistrationsBaseUrl"
256
+ }
257
+ ]
258
+ }
259
+ """),
260
+ _ => (200, "") // empty string instead of expected JSON object
261
+ };
262
+ });
263
+ var feedUrl = $"{http.BaseUrl.TrimEnd('/')}/index.json";
264
+ using var tempDir = await TemporaryDirectory.CreateWithContentsAsync(
265
+ ("NuGet.Config", $"""
266
+ <configuration>
267
+ <packageSources>
268
+ <clear />
269
+ <add key="private_feed" value="{feedUrl}" allowInsecureConnections="true" />
270
+ </packageSources>
271
+ </configuration>
272
+ """)
273
+ );
274
+
275
+ // act
276
+ var tfm = NuGetFramework.Parse("net9.0");
277
+ var dependencyInfo = new DependencyInfo
278
+ {
279
+ Name = "Some.Dependency",
280
+ Version = "1.0.0",
281
+ IsVulnerable = false,
282
+ IgnoredVersions = [],
283
+ Vulnerabilities = [],
284
+ };
285
+ var logger = new TestLogger();
286
+ var nugetContext = new NuGetContext(tempDir.DirectoryPath);
287
+ var exception = await Assert.ThrowsAsync<BadResponseException>(async () =>
288
+ {
289
+ await VersionFinder.GetVersionsAsync([tfm], dependencyInfo, nugetContext, logger, CancellationToken.None);
290
+ });
291
+ var error = JobErrorBase.ErrorFromException(exception, "TEST-JOB-ID", tempDir.DirectoryPath);
292
+
293
+ // assert
294
+ var expected = new PrivateSourceBadResponse([feedUrl]);
295
+ var expectedJson = JsonSerializer.Serialize(expected, RunWorker.SerializerOptions);
296
+ var actualJson = JsonSerializer.Serialize(error, RunWorker.SerializerOptions);
297
+ Assert.Equal(expectedJson, actualJson);
298
+ }
226
299
  }
@@ -111,7 +111,7 @@ public class CloneWorkerTests
111
111
 
112
112
  // assert
113
113
  Assert.Equal(1, result);
114
- var expectedParseErrorObject = testApiHandler.ReceivedMessages.Single(m => m.Type == typeof(UnknownError));
114
+ var expectedParseErrorObject = testApiHandler.ReceivedMessages.First(m => m.Type == typeof(UnknownError));
115
115
  var unknownError = (UnknownError)expectedParseErrorObject.Object;
116
116
  Assert.Equal("JsonException", unknownError.Details["error-class"]);
117
117
  }
@@ -832,10 +832,8 @@ public partial class DiscoveryWorkerTests
832
832
  {
833
833
  FilePath = "myproj.csproj",
834
834
  Dependencies = [
835
- new("Some.Package", "1.2.3.4", DependencyType.PackageReference, TargetFrameworks: ["net7.0"], IsDirect: true),
836
- new("Some.Package", "1.2.3.4", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
837
- new("Transitive.Dependency", "5.6.7.8", DependencyType.Unknown, TargetFrameworks: ["net7.0"], IsTransitive: true),
838
- new("Transitive.Dependency", "5.6.7.8", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true),
835
+ new("Some.Package", "1.2.3.4", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true),
836
+ new("Transitive.Dependency", "5.6.7.8", DependencyType.Unknown, TargetFrameworks: ["net7.0", "net8.0"], IsTransitive: true),
839
837
  ],
840
838
  Properties = [
841
839
  new("TargetFrameworks", "net7.0;net8.0", "myproj.csproj"),
@@ -1191,11 +1189,7 @@ public partial class DiscoveryWorkerTests
1191
1189
  {
1192
1190
  FilePath = "project.csproj",
1193
1191
  Dependencies = [
1194
- new("Some.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0-android"], IsDirect: true),
1195
- new("Some.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0-ios"], IsDirect: true),
1196
- new("Some.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0-maccatalyst"], IsDirect: true),
1197
- new("Some.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0-macos"], IsDirect: true),
1198
- new("Some.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0-windows"], IsDirect: true),
1192
+ new("Some.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0-android", "net8.0-ios", "net8.0-maccatalyst", "net8.0-macos", "net8.0-windows"], IsDirect: true),
1199
1193
  ],
1200
1194
  Properties = [
1201
1195
  new("TargetFrameworks", "net8.0-ios;net8.0-android;net8.0-macos;net8.0-maccatalyst;net8.0-windows", @"src/project.csproj"),
@@ -673,8 +673,7 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
673
673
  FilePath = "src/project.csproj",
674
674
  TargetFrameworks = ["net7.0", "net8.0"],
675
675
  Dependencies = [
676
- new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net7.0"], IsDirect: true),
677
- new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
676
+ new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true),
678
677
  ],
679
678
  Properties = [
680
679
  new("TargetFrameworks", "net7.0;net8.0", "src/project.csproj")
@@ -1,4 +1,5 @@
1
1
  using System.Collections.Immutable;
2
+ using System.Text;
2
3
 
3
4
  using NuGetUpdater.Core.Discover;
4
5
  using NuGetUpdater.Core.Test.Update;
@@ -297,8 +298,7 @@ public class SdkProjectDiscoveryTests : DiscoveryWorkerTestBase
297
298
  FilePath = "library.csproj",
298
299
  Dependencies =
299
300
  [
300
- new("Some.Dependency", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net7.0"], IsDirect: true),
301
- new("Some.Dependency", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
301
+ new("Some.Dependency", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true),
302
302
  ],
303
303
  ImportedFiles = [],
304
304
  Properties =
@@ -524,6 +524,62 @@ public class SdkProjectDiscoveryTests : DiscoveryWorkerTestBase
524
524
  );
525
525
  }
526
526
 
527
+ [Fact]
528
+ public async Task TransitiveDependenciesWithoutAssembliesAreReported()
529
+ {
530
+ await TestDiscoverAsync(
531
+ packages:
532
+ [
533
+ MockNuGetPackage.CreateSimplePackage("Some.Dependency", "1.2.3", "net9.0", [(null, [("Transitive.Dependency", "4.5.6")])]),
534
+ new MockNuGetPackage(
535
+ "Transitive.Dependency",
536
+ "4.5.6",
537
+ Files: [
538
+ ("build/Transitive.Dependency.targets", Encoding.UTF8.GetBytes("<Project />"))
539
+ ],
540
+ DependencyGroups: [(null, [("Super.Transitive.Dependency", "7.8.9")])]
541
+ ),
542
+ MockNuGetPackage.CreateSimplePackage("Super.Transitive.Dependency", "7.8.9", "net9.0"),
543
+ ],
544
+ startingDirectory: "src",
545
+ projectPath: "src/library.csproj",
546
+ files:
547
+ [
548
+ ("src/library.csproj", """
549
+ <Project Sdk="Microsoft.NET.Sdk">
550
+ <PropertyGroup>
551
+ <TargetFramework>net9.0</TargetFramework>
552
+ </PropertyGroup>
553
+ <ItemGroup>
554
+ <PackageReference Include="Some.Dependency" Version="1.2.3" />
555
+ </ItemGroup>
556
+ </Project>
557
+ """)
558
+ ],
559
+ expectedProjects:
560
+ [
561
+ new()
562
+ {
563
+ FilePath = "library.csproj",
564
+ Dependencies =
565
+ [
566
+ new("Some.Dependency", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net9.0"], IsDirect: true),
567
+ new("Transitive.Dependency", "4.5.6", DependencyType.Unknown, TargetFrameworks: ["net9.0"], IsTransitive: true),
568
+ new("Super.Transitive.Dependency", "7.8.9", DependencyType.Unknown, TargetFrameworks: ["net9.0"], IsTransitive: true),
569
+ ],
570
+ ImportedFiles = [],
571
+ Properties =
572
+ [
573
+ new("TargetFramework", "net9.0", "src/library.csproj"),
574
+ ],
575
+ TargetFrameworks = ["net9.0"],
576
+ ReferencedProjectPaths = [],
577
+ AdditionalFiles = [],
578
+ },
579
+ ]
580
+ );
581
+ }
582
+
527
583
  private static async Task TestDiscoverAsync(string startingDirectory, string projectPath, TestFile[] files, ImmutableArray<ExpectedSdkProjectDiscoveryResult> expectedProjects, MockNuGetPackage[]? packages = null)
528
584
  {
529
585
  using var testDirectory = await TemporaryDirectory.CreateWithContentsAsync(files);
@@ -0,0 +1,157 @@
1
+ using NuGetUpdater.Core.Run;
2
+ using NuGetUpdater.Core.Run.ApiModel;
3
+ using NuGetUpdater.Core.Test.Utilities;
4
+
5
+ using Xunit;
6
+
7
+ namespace NuGetUpdater.Core.Test.Run;
8
+
9
+ public class HttpApiHandlerTests
10
+ {
11
+ [Fact]
12
+ public async Task FailedRequestWithContentReportsData()
13
+ {
14
+ // arrange
15
+ // this mimics an error that can be returned by the server
16
+ var errorContent = """{"errors":[{"status":400,"title":"Bad Request","detail":"some-detail"}]}""";
17
+ using var http = TestHttpServer.CreateTestStringServer((method, url) =>
18
+ {
19
+ return (400, errorContent);
20
+ });
21
+ var handler = new HttpApiHandler(http.BaseUrl, "TEST-ID");
22
+
23
+ // act
24
+ var exception = await Assert.ThrowsAsync<HttpRequestException>(() => handler.IncrementMetric(new()
25
+ {
26
+ // body is irrelevant for this test
27
+ Metric = "TEST",
28
+ }));
29
+
30
+ // assert
31
+ var expectedMessage = $"400 (BadRequest): {errorContent}";
32
+ Assert.Equal(expectedMessage, exception.Message);
33
+ }
34
+
35
+ [Fact]
36
+ public async Task FailedRequestWithNoContentOnlyReportsStatusCode()
37
+ {
38
+ // arrange
39
+ using var http = TestHttpServer.CreateTestServer((method, url) =>
40
+ {
41
+ // no error content returned
42
+ return (400, null);
43
+ });
44
+ var handler = new HttpApiHandler(http.BaseUrl, "TEST-ID");
45
+
46
+ // act
47
+ var exception = await Assert.ThrowsAsync<HttpRequestException>(() => handler.IncrementMetric(new()
48
+ {
49
+ // body is irrelevant for this test
50
+ Metric = "TEST",
51
+ }));
52
+
53
+ // assert
54
+ var expectedMessage = $"400 (BadRequest)";
55
+ Assert.Equal(expectedMessage, exception.Message);
56
+ }
57
+
58
+ [Fact]
59
+ public async Task ApiCallsAreAutomaticallyRetriedWhenTheServerThrowsAnError()
60
+ {
61
+ // arrange
62
+ var requestCount = 0;
63
+ using var http = TestHttpServer.CreateTestServer((method, url) =>
64
+ {
65
+ if (requestCount < 2)
66
+ {
67
+ requestCount++;
68
+ return (500, Array.Empty<byte>());
69
+ }
70
+
71
+ return (200, Array.Empty<byte>());
72
+ });
73
+ var handler = new HttpApiHandler(http.BaseUrl, "TEST-ID");
74
+
75
+ // act
76
+ await handler.IncrementMetric(new()
77
+ {
78
+ Metric = "test",
79
+ });
80
+ }
81
+
82
+ [Fact]
83
+ public async Task ApiCallsAreNotRetriedOnABadRequest()
84
+ {
85
+ // arrange
86
+ var requestCount = 0;
87
+ using var http = TestHttpServer.CreateTestServer((method, url) =>
88
+ {
89
+ requestCount++;
90
+ return (400, Array.Empty<byte>());
91
+ });
92
+ var handler = new HttpApiHandler(http.BaseUrl, "TEST-ID");
93
+
94
+ // act
95
+ await Assert.ThrowsAsync<HttpRequestException>(() => handler.IncrementMetric(new() { Metric = "test" }));
96
+ Assert.True(requestCount == 1, $"Expected only 1 request, but received {requestCount}.");
97
+ }
98
+
99
+ [Theory]
100
+ [MemberData(nameof(ErrorsAreSentToTheCorrectEndpointTestData))]
101
+ public async Task ErrorsAreSentToTheCorrectEndpoint(JobErrorBase error, params string[] expectedEndpoints)
102
+ {
103
+ // arrange
104
+ var actualEndpoints = new List<string>();
105
+ using var http = TestHttpServer.CreateTestStringServer((method, url) =>
106
+ {
107
+ var expectedPrefix = "/update_jobs/TEST-ID/";
108
+ var actualPathAndQuery = new Uri(url).PathAndQuery;
109
+ if (!actualPathAndQuery.StartsWith(expectedPrefix))
110
+ {
111
+ throw new Exception($"Didn't find expected prefix: [{expectedPrefix}]");
112
+ }
113
+
114
+ actualEndpoints.Add(actualPathAndQuery[expectedPrefix.Length..]);
115
+ return (200, "ok");
116
+ });
117
+ var handler = new HttpApiHandler(http.BaseUrl, "TEST-ID");
118
+
119
+ // act
120
+ await handler.RecordUpdateJobError(error);
121
+
122
+ // assert
123
+ AssertEx.Equal(expectedEndpoints, actualEndpoints);
124
+ }
125
+
126
+ [Fact]
127
+ public void ErrorsAreSentToTheCorrectEndpoint_AllTypesAreTested()
128
+ {
129
+ var remainingErrorTypes = typeof(JobErrorBase).Assembly
130
+ .GetTypes()
131
+ .Where(t => t.IsSubclassOf(typeof(JobErrorBase)))
132
+ .Select(t => t.Name)
133
+ .ToHashSet();
134
+ foreach (var testData in ErrorsAreSentToTheCorrectEndpointTestData())
135
+ {
136
+ var seenErrorType = testData[0].GetType().Name;
137
+ remainingErrorTypes.Remove(seenErrorType);
138
+ }
139
+
140
+ Assert.Empty(remainingErrorTypes);
141
+ }
142
+
143
+ public static IEnumerable<object[]> ErrorsAreSentToTheCorrectEndpointTestData()
144
+ {
145
+ yield return [new BadRequirement("unused"), "record_update_job_error"];
146
+ yield return [new DependencyFileNotFound("unused"), "record_update_job_error"];
147
+ yield return [new DependencyFileNotParseable("unused"), "record_update_job_error"];
148
+ yield return [new DependencyNotFound("unused"), "record_update_job_error"];
149
+ yield return [new JobRepoNotFound("unused"), "record_update_job_error"];
150
+ yield return [new PrivateSourceAuthenticationFailure(["unused"]), "record_update_job_error"];
151
+ yield return [new PrivateSourceBadResponse(["unused"]), "record_update_job_error"];
152
+ yield return [new PullRequestExistsForLatestVersion("unused", "unused"), "record_update_job_error"];
153
+ yield return [new SecurityUpdateNotNeeded("unused"), "record_update_job_error"];
154
+ yield return [new UnknownError(new Exception("unused"), "unused"), "record_update_job_error", "record_update_job_unknown_error", "increment_metric"];
155
+ yield return [new UpdateNotPossible(["unused"]), "record_update_job_error"];
156
+ }
157
+ }
@@ -0,0 +1,86 @@
1
+ using System.Net;
2
+ using System.Text.Json;
3
+
4
+ using NuGet.Protocol.Core.Types;
5
+
6
+ using NuGetUpdater.Core.Run;
7
+ using NuGetUpdater.Core.Run.ApiModel;
8
+
9
+ using Xunit;
10
+
11
+ namespace NuGetUpdater.Core.Test.Run;
12
+
13
+ public class JobErrorBaseTests : TestBase
14
+ {
15
+ [Theory]
16
+ [MemberData(nameof(GenerateErrorFromExceptionTestData))]
17
+ public async Task GenerateErrorFromException(Exception exception, JobErrorBase expectedError)
18
+ {
19
+ // arrange
20
+ // some error types require a NuGet.Config file to be present
21
+ using var tempDir = await TemporaryDirectory.CreateWithContentsAsync(
22
+ ("NuGet.Config", """
23
+ <configuration>
24
+ <packageSources>
25
+ <clear />
26
+ <add key="some_package_feed" value="http://nuget.example.com/v3/index.json" allowInsecureConnections="true" />
27
+ </packageSources>
28
+ </configuration>
29
+ """)
30
+ );
31
+
32
+ // act
33
+ var actualError = JobErrorBase.ErrorFromException(exception, "TEST-JOB-ID", tempDir.DirectoryPath);
34
+
35
+ // assert
36
+ var actualErrorJson = JsonSerializer.Serialize(actualError, RunWorker.SerializerOptions);
37
+ var expectedErrorJson = JsonSerializer.Serialize(expectedError, RunWorker.SerializerOptions);
38
+ Assert.Equal(expectedErrorJson, actualErrorJson);
39
+ }
40
+
41
+ public static IEnumerable<object[]> GenerateErrorFromExceptionTestData()
42
+ {
43
+ // internal error from package feed
44
+ yield return
45
+ [
46
+ new HttpRequestException("nope", null, HttpStatusCode.InternalServerError),
47
+ new PrivateSourceBadResponse(["http://nuget.example.com/v3/index.json"]),
48
+ ];
49
+
50
+ // inner exception turns into private_source_bad_response; 500
51
+ yield return
52
+ [
53
+ new FatalProtocolException("nope", new HttpRequestException("nope", null, HttpStatusCode.InternalServerError)),
54
+ new PrivateSourceBadResponse(["http://nuget.example.com/v3/index.json"]),
55
+ ];
56
+
57
+ // inner exception turns into private_source_bad_response; ResponseEnded
58
+ yield return
59
+ [
60
+ new FatalProtocolException("nope", new HttpRequestException("nope", new HttpIOException(HttpRequestError.ResponseEnded))),
61
+ new PrivateSourceBadResponse(["http://nuget.example.com/v3/index.json"]),
62
+ ];
63
+
64
+ // top-level exception turns into private_source_authentication_failure
65
+ yield return
66
+ [
67
+ new HttpRequestException("nope", null, HttpStatusCode.Unauthorized),
68
+ new PrivateSourceAuthenticationFailure(["http://nuget.example.com/v3/index.json"]),
69
+ ];
70
+
71
+ // inner exception turns into private_source_authentication_failure
72
+ yield return
73
+ [
74
+ // the NuGet libraries commonly do this
75
+ new FatalProtocolException("nope", new HttpRequestException("nope", null, HttpStatusCode.Unauthorized)),
76
+ new PrivateSourceAuthenticationFailure(["http://nuget.example.com/v3/index.json"]),
77
+ ];
78
+
79
+ // unknown errors all the way down; report the initial top-level error
80
+ yield return
81
+ [
82
+ new Exception("outer", new Exception("inner")),
83
+ new UnknownError(new Exception("outer", new Exception("inner")), "TEST-JOB-ID"),
84
+ ];
85
+ }
86
+ }
@@ -190,8 +190,7 @@ public class MessageReportTests
190
190
  """
191
191
  Error type: unknown_error
192
192
  - error-class: NotImplementedException
193
- - error-message: error message
194
- - error-backtrace: <unknown>
193
+ - error-message: System.NotImplementedException: error message
195
194
  - package-manager: nuget
196
195
  - job-id: TEST-JOB-ID
197
196
  """