dependabot-nuget 0.265.0 → 0.267.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.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +6 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +173 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalysisResult.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +92 -79
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +21 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +36 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Requirement.cs +88 -45
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +33 -16
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +44 -25
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +9 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/MissingFileException.cs +11 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +45 -42
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +19 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationResult.cs +5 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +70 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +29 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +6 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +450 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/CompatibilityCheckerTests.cs +23 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/RequirementTests.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +148 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +17 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestHttpServer.cs +81 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +27 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +32 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +447 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +88 -0
- data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -0
- data/lib/dependabot/nuget/file_fetcher.rb +30 -11
- data/lib/dependabot/nuget/file_updater.rb +2 -0
- data/lib/dependabot/nuget/metadata_finder.rb +160 -2
- data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +3 -0
- data/lib/dependabot/nuget/native_helpers.rb +36 -3
- data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +1 -0
- data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +3 -0
- metadata +12 -7
@@ -1,3 +1,8 @@
|
|
1
|
+
using System.Text;
|
2
|
+
using System.Text.Json;
|
3
|
+
|
4
|
+
using NuGet;
|
5
|
+
|
1
6
|
using NuGetUpdater.Core.Analyze;
|
2
7
|
|
3
8
|
using Xunit;
|
@@ -301,4 +306,449 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
|
|
301
306
|
}
|
302
307
|
);
|
303
308
|
}
|
309
|
+
|
310
|
+
[Fact]
|
311
|
+
public async Task VersionFinderCanHandle404FromPackageSource_V2()
|
312
|
+
{
|
313
|
+
static (int, byte[]) TestHttpHandler1(string uriString)
|
314
|
+
{
|
315
|
+
// this is a valid nuget package source, but doesn't contain anything
|
316
|
+
var uri = new Uri(uriString, UriKind.Absolute);
|
317
|
+
var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
|
318
|
+
return uri.PathAndQuery switch
|
319
|
+
{
|
320
|
+
"/api/v2/" => (200, Encoding.UTF8.GetBytes($"""
|
321
|
+
<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xml:base="{baseUrl}/api/v2">
|
322
|
+
<workspace>
|
323
|
+
<atom:title type="text">Default</atom:title>
|
324
|
+
<collection href="Packages">
|
325
|
+
<atom:title type="text">Packages</atom:title>
|
326
|
+
</collection>
|
327
|
+
</workspace>
|
328
|
+
</service>
|
329
|
+
""")),
|
330
|
+
_ => (404, Encoding.UTF8.GetBytes("{}")), // nothing else is found
|
331
|
+
};
|
332
|
+
}
|
333
|
+
var desktopAppRefPackage = MockNuGetPackage.WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net8.0");
|
334
|
+
(int, byte[]) TestHttpHandler2(string uriString)
|
335
|
+
{
|
336
|
+
// this contains the actual package
|
337
|
+
var uri = new Uri(uriString, UriKind.Absolute);
|
338
|
+
var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
|
339
|
+
switch (uri.PathAndQuery)
|
340
|
+
{
|
341
|
+
case "/api/v2/":
|
342
|
+
return (200, Encoding.UTF8.GetBytes($"""
|
343
|
+
<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xml:base="{baseUrl}/api/v2">
|
344
|
+
<workspace>
|
345
|
+
<atom:title type="text">Default</atom:title>
|
346
|
+
<collection href="Packages">
|
347
|
+
<atom:title type="text">Packages</atom:title>
|
348
|
+
</collection>
|
349
|
+
</workspace>
|
350
|
+
</service>
|
351
|
+
"""));
|
352
|
+
case "/api/v2/FindPackagesById()?id='Some.Package'&semVerLevel=2.0.0":
|
353
|
+
return (200, Encoding.UTF8.GetBytes($"""
|
354
|
+
<feed xml:base="{baseUrl}/api/v2" xmlns="http://www.w3.org/2005/Atom"
|
355
|
+
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
|
356
|
+
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
|
357
|
+
xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
|
358
|
+
<m:count>2</m:count>
|
359
|
+
<id>http://schemas.datacontract.org/2004/07/</id>
|
360
|
+
<title />
|
361
|
+
<updated>{DateTime.UtcNow:O}</updated>
|
362
|
+
<link rel="self" href="{baseUrl}/api/v2/Packages" />
|
363
|
+
<entry>
|
364
|
+
<id>{baseUrl}/api/v2/Packages(Id='Some.Package',Version='1.0.0')</id>
|
365
|
+
<content type="application/zip" src="{baseUrl}/api/v2/package/Some.Package/1.0.0" />
|
366
|
+
<m:properties>
|
367
|
+
<d:Version>1.0.0</d:Version>
|
368
|
+
</m:properties>
|
369
|
+
</entry>
|
370
|
+
<entry>
|
371
|
+
<id>{baseUrl}/api/v2/Packages(Id='Some.Package',Version='1.2.3')</id>
|
372
|
+
<content type="application/zip" src="{baseUrl}/api/v2/package/Some.Package/1.2.3" />
|
373
|
+
<m:properties>
|
374
|
+
<d:Version>1.2.3</d:Version>
|
375
|
+
</m:properties>
|
376
|
+
</entry>
|
377
|
+
</feed>
|
378
|
+
"""));
|
379
|
+
case "/api/v2/Packages(Id='Some.Package',Version='1.2.3')":
|
380
|
+
return (200, Encoding.UTF8.GetBytes($"""
|
381
|
+
<entry xml:base="{baseUrl}/api/v2" xmlns="http://www.w3.org/2005/Atom"
|
382
|
+
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
|
383
|
+
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
|
384
|
+
xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
|
385
|
+
<id>{baseUrl}/api/v2/Packages(Id='Some.Package',Version='1.2.3')</id>
|
386
|
+
<updated>{DateTime.UtcNow:O}</updated>
|
387
|
+
<content type="application/zip" src="{baseUrl}/api/v2/package/Some.Package/1.2.3" />
|
388
|
+
<m:properties>
|
389
|
+
<d:Version>1.2.3</d:Version>
|
390
|
+
</m:properties>
|
391
|
+
</entry>
|
392
|
+
"""));
|
393
|
+
case "/api/v2/package/Some.Package/1.0.0":
|
394
|
+
return (200, MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0").GetZipStream().ReadAllBytes());
|
395
|
+
case "/api/v2/package/Some.Package/1.2.3":
|
396
|
+
return (200, MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.3", "net8.0").GetZipStream().ReadAllBytes());
|
397
|
+
case "/api/v2/FindPackagesById()?id='Microsoft.WindowsDesktop.App.Ref'&semVerLevel=2.0.0":
|
398
|
+
return (200, Encoding.UTF8.GetBytes($"""
|
399
|
+
<feed xml:base="{baseUrl}/api/v2" xmlns="http://www.w3.org/2005/Atom"
|
400
|
+
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
|
401
|
+
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
|
402
|
+
xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
|
403
|
+
<m:count>1</m:count>
|
404
|
+
<id>http://schemas.datacontract.org/2004/07/</id>
|
405
|
+
<title />
|
406
|
+
<updated>{DateTime.UtcNow:O}</updated>
|
407
|
+
<link rel="self" href="{baseUrl}/api/v2/Packages" />
|
408
|
+
<entry>
|
409
|
+
<id>{baseUrl}/api/v2/Packages(Id='Microsoft.WindowsDesktop.App.Ref',Version='{desktopAppRefPackage.Version}')</id>
|
410
|
+
<content type="application/zip" src="{baseUrl}/api/v2/package/Microsoft.WindowsDesktop.App.Ref/{desktopAppRefPackage.Version}" />
|
411
|
+
<m:properties>
|
412
|
+
<d:Version>{desktopAppRefPackage.Version}</d:Version>
|
413
|
+
</m:properties>
|
414
|
+
</entry>
|
415
|
+
</feed>
|
416
|
+
"""));
|
417
|
+
default:
|
418
|
+
if (uri.PathAndQuery == $"/api/v2/package/Microsoft.WindowsDesktop.App.Ref/{desktopAppRefPackage.Version}")
|
419
|
+
{
|
420
|
+
return (200, desktopAppRefPackage.GetZipStream().ReadAllBytes());
|
421
|
+
}
|
422
|
+
|
423
|
+
// nothing else is found
|
424
|
+
return (404, Encoding.UTF8.GetBytes("{}"));
|
425
|
+
};
|
426
|
+
}
|
427
|
+
using var http1 = TestHttpServer.CreateTestServer(TestHttpHandler1);
|
428
|
+
using var http2 = TestHttpServer.CreateTestServer(TestHttpHandler2);
|
429
|
+
await TestAnalyzeAsync(
|
430
|
+
extraFiles:
|
431
|
+
[
|
432
|
+
("NuGet.Config", $"""
|
433
|
+
<configuration>
|
434
|
+
<packageSources>
|
435
|
+
<clear />
|
436
|
+
<add key="package_feed_1" value="{http1.BaseUrl.TrimEnd('/')}/api/v2/" allowInsecureConnections="true" />
|
437
|
+
<add key="package_feed_2" value="{http2.BaseUrl.TrimEnd('/')}/api/v2/" allowInsecureConnections="true" />
|
438
|
+
</packageSources>
|
439
|
+
</configuration>
|
440
|
+
""")
|
441
|
+
],
|
442
|
+
discovery: new()
|
443
|
+
{
|
444
|
+
Path = "/",
|
445
|
+
Projects =
|
446
|
+
[
|
447
|
+
new()
|
448
|
+
{
|
449
|
+
FilePath = "./project.csproj",
|
450
|
+
TargetFrameworks = ["net8.0"],
|
451
|
+
Dependencies =
|
452
|
+
[
|
453
|
+
new("Some.Package", "1.0.0", DependencyType.PackageReference),
|
454
|
+
]
|
455
|
+
}
|
456
|
+
]
|
457
|
+
},
|
458
|
+
dependencyInfo: new()
|
459
|
+
{
|
460
|
+
Name = "Some.Package",
|
461
|
+
Version = "1.0.0",
|
462
|
+
IgnoredVersions = [],
|
463
|
+
IsVulnerable = false,
|
464
|
+
Vulnerabilities = [],
|
465
|
+
},
|
466
|
+
expectedResult: new()
|
467
|
+
{
|
468
|
+
UpdatedVersion = "1.2.3",
|
469
|
+
CanUpdate = true,
|
470
|
+
VersionComesFromMultiDependencyProperty = false,
|
471
|
+
UpdatedDependencies =
|
472
|
+
[
|
473
|
+
new("Some.Package", "1.2.3", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
|
474
|
+
],
|
475
|
+
}
|
476
|
+
);
|
477
|
+
}
|
478
|
+
|
479
|
+
[Fact]
|
480
|
+
public async Task VersionFinderCanHandle404FromPackageSource_V3()
|
481
|
+
{
|
482
|
+
static (int, byte[]) TestHttpHandler1(string uriString)
|
483
|
+
{
|
484
|
+
// this is a valid nuget package source, but doesn't contain anything
|
485
|
+
var uri = new Uri(uriString, UriKind.Absolute);
|
486
|
+
var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
|
487
|
+
return uri.PathAndQuery switch
|
488
|
+
{
|
489
|
+
"/index.json" => (200, Encoding.UTF8.GetBytes($$"""
|
490
|
+
{
|
491
|
+
"version": "3.0.0",
|
492
|
+
"resources": [
|
493
|
+
{
|
494
|
+
"@id": "{{baseUrl}}/download",
|
495
|
+
"@type": "PackageBaseAddress/3.0.0"
|
496
|
+
},
|
497
|
+
{
|
498
|
+
"@id": "{{baseUrl}}/query",
|
499
|
+
"@type": "SearchQueryService"
|
500
|
+
},
|
501
|
+
{
|
502
|
+
"@id": "{{baseUrl}}/registrations",
|
503
|
+
"@type": "RegistrationsBaseUrl"
|
504
|
+
}
|
505
|
+
]
|
506
|
+
}
|
507
|
+
""")),
|
508
|
+
_ => (404, Encoding.UTF8.GetBytes("{}")), // nothing else is found
|
509
|
+
};
|
510
|
+
}
|
511
|
+
var desktopAppRefPackage = MockNuGetPackage.WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net8.0");
|
512
|
+
(int, byte[]) TestHttpHandler2(string uriString)
|
513
|
+
{
|
514
|
+
// this contains the actual package
|
515
|
+
var uri = new Uri(uriString, UriKind.Absolute);
|
516
|
+
var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
|
517
|
+
switch (uri.PathAndQuery)
|
518
|
+
{
|
519
|
+
case "/index.json":
|
520
|
+
return (200, Encoding.UTF8.GetBytes($$"""
|
521
|
+
{
|
522
|
+
"version": "3.0.0",
|
523
|
+
"resources": [
|
524
|
+
{
|
525
|
+
"@id": "{{baseUrl}}/download",
|
526
|
+
"@type": "PackageBaseAddress/3.0.0"
|
527
|
+
},
|
528
|
+
{
|
529
|
+
"@id": "{{baseUrl}}/query",
|
530
|
+
"@type": "SearchQueryService"
|
531
|
+
},
|
532
|
+
{
|
533
|
+
"@id": "{{baseUrl}}/registrations",
|
534
|
+
"@type": "RegistrationsBaseUrl"
|
535
|
+
}
|
536
|
+
]
|
537
|
+
}
|
538
|
+
"""));
|
539
|
+
case "/registrations/some.package/index.json":
|
540
|
+
return (200, Encoding.UTF8.GetBytes("""
|
541
|
+
{
|
542
|
+
"count": 1,
|
543
|
+
"items": [
|
544
|
+
{
|
545
|
+
"lower": "1.0.0",
|
546
|
+
"upper": "1.2.3",
|
547
|
+
"items": [
|
548
|
+
{
|
549
|
+
"catalogEntry": {
|
550
|
+
"listed": true,
|
551
|
+
"version": "1.0.0"
|
552
|
+
}
|
553
|
+
},
|
554
|
+
{
|
555
|
+
"catalogEntry": {
|
556
|
+
"listed": true,
|
557
|
+
"version": "1.2.3"
|
558
|
+
}
|
559
|
+
}
|
560
|
+
]
|
561
|
+
}
|
562
|
+
]
|
563
|
+
}
|
564
|
+
"""));
|
565
|
+
case "/download/some.package/index.json":
|
566
|
+
return (200, Encoding.UTF8.GetBytes("""
|
567
|
+
{
|
568
|
+
"versions": [
|
569
|
+
"1.0.0",
|
570
|
+
"1.2.3"
|
571
|
+
]
|
572
|
+
}
|
573
|
+
"""));
|
574
|
+
case "/download/microsoft.windowsdesktop.app.ref/index.json":
|
575
|
+
return (200, Encoding.UTF8.GetBytes($$"""
|
576
|
+
{
|
577
|
+
"versions": [
|
578
|
+
"{{desktopAppRefPackage.Version}}"
|
579
|
+
]
|
580
|
+
}
|
581
|
+
"""));
|
582
|
+
case "/download/some.package/1.0.0/some.package.1.0.0.nupkg":
|
583
|
+
return (200, MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0").GetZipStream().ReadAllBytes());
|
584
|
+
case "/download/some.package/1.2.3/some.package.1.2.3.nupkg":
|
585
|
+
return (200, MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.3", "net8.0").GetZipStream().ReadAllBytes());
|
586
|
+
default:
|
587
|
+
if (uri.PathAndQuery == $"/download/microsoft.windowsdesktop.app.ref/{desktopAppRefPackage.Version}/microsoft.windowsdesktop.app.ref.{desktopAppRefPackage.Version}.nupkg")
|
588
|
+
{
|
589
|
+
return (200, desktopAppRefPackage.GetZipStream().ReadAllBytes());
|
590
|
+
}
|
591
|
+
|
592
|
+
// nothing else is found
|
593
|
+
return (404, Encoding.UTF8.GetBytes("{}"));
|
594
|
+
};
|
595
|
+
}
|
596
|
+
using var http1 = TestHttpServer.CreateTestServer(TestHttpHandler1);
|
597
|
+
using var http2 = TestHttpServer.CreateTestServer(TestHttpHandler2);
|
598
|
+
await TestAnalyzeAsync(
|
599
|
+
extraFiles:
|
600
|
+
[
|
601
|
+
("NuGet.Config", $"""
|
602
|
+
<configuration>
|
603
|
+
<packageSources>
|
604
|
+
<clear />
|
605
|
+
<add key="package_feed_1" value="{http1.BaseUrl.TrimEnd('/')}/index.json" allowInsecureConnections="true" />
|
606
|
+
<add key="package_feed_2" value="{http2.BaseUrl.TrimEnd('/')}/index.json" allowInsecureConnections="true" />
|
607
|
+
</packageSources>
|
608
|
+
</configuration>
|
609
|
+
""")
|
610
|
+
],
|
611
|
+
discovery: new()
|
612
|
+
{
|
613
|
+
Path = "/",
|
614
|
+
Projects =
|
615
|
+
[
|
616
|
+
new()
|
617
|
+
{
|
618
|
+
FilePath = "./project.csproj",
|
619
|
+
TargetFrameworks = ["net8.0"],
|
620
|
+
Dependencies =
|
621
|
+
[
|
622
|
+
new("Some.Package", "1.0.0", DependencyType.PackageReference),
|
623
|
+
]
|
624
|
+
}
|
625
|
+
]
|
626
|
+
},
|
627
|
+
dependencyInfo: new()
|
628
|
+
{
|
629
|
+
Name = "Some.Package",
|
630
|
+
Version = "1.0.0",
|
631
|
+
IgnoredVersions = [],
|
632
|
+
IsVulnerable = false,
|
633
|
+
Vulnerabilities = [],
|
634
|
+
},
|
635
|
+
expectedResult: new()
|
636
|
+
{
|
637
|
+
UpdatedVersion = "1.2.3",
|
638
|
+
CanUpdate = true,
|
639
|
+
VersionComesFromMultiDependencyProperty = false,
|
640
|
+
UpdatedDependencies =
|
641
|
+
[
|
642
|
+
new("Some.Package", "1.2.3", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
|
643
|
+
],
|
644
|
+
}
|
645
|
+
);
|
646
|
+
}
|
647
|
+
|
648
|
+
[Fact]
|
649
|
+
public async Task ResultFileHasCorrectShapeForAuthenticationFailure()
|
650
|
+
{
|
651
|
+
using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync([]);
|
652
|
+
await AnalyzeWorker.WriteResultsAsync(temporaryDirectory.DirectoryPath, "Some.Dependency", new()
|
653
|
+
{
|
654
|
+
ErrorType = ErrorType.AuthenticationFailure,
|
655
|
+
ErrorDetails = "<some package feed>",
|
656
|
+
UpdatedVersion = "",
|
657
|
+
UpdatedDependencies = [],
|
658
|
+
}, new Logger(false));
|
659
|
+
var discoveryContents = await File.ReadAllTextAsync(Path.Combine(temporaryDirectory.DirectoryPath, "Some.Dependency.json"));
|
660
|
+
|
661
|
+
// raw result file should look like this:
|
662
|
+
// {
|
663
|
+
// ...
|
664
|
+
// "ErrorType": "AuthenticationFailure",
|
665
|
+
// "ErrorDetails": "<some package feed>",
|
666
|
+
// ...
|
667
|
+
// }
|
668
|
+
var jsonDocument = JsonDocument.Parse(discoveryContents);
|
669
|
+
var errorType = jsonDocument.RootElement.GetProperty("ErrorType");
|
670
|
+
var errorDetails = jsonDocument.RootElement.GetProperty("ErrorDetails");
|
671
|
+
|
672
|
+
Assert.Equal("AuthenticationFailure", errorType.GetString());
|
673
|
+
Assert.Equal("<some package feed>", errorDetails.GetString());
|
674
|
+
}
|
675
|
+
|
676
|
+
[Fact]
|
677
|
+
public async Task ReportsPrivateSourceAuthenticationFailure()
|
678
|
+
{
|
679
|
+
static (int, string) TestHttpHandler(string uriString)
|
680
|
+
{
|
681
|
+
var uri = new Uri(uriString, UriKind.Absolute);
|
682
|
+
var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
|
683
|
+
return uri.PathAndQuery switch
|
684
|
+
{
|
685
|
+
// initial request is good
|
686
|
+
"/index.json" => (200, $$"""
|
687
|
+
{
|
688
|
+
"version": "3.0.0",
|
689
|
+
"resources": [
|
690
|
+
{
|
691
|
+
"@id": "{{baseUrl}}/download",
|
692
|
+
"@type": "PackageBaseAddress/3.0.0"
|
693
|
+
},
|
694
|
+
{
|
695
|
+
"@id": "{{baseUrl}}/query",
|
696
|
+
"@type": "SearchQueryService"
|
697
|
+
},
|
698
|
+
{
|
699
|
+
"@id": "{{baseUrl}}/registrations",
|
700
|
+
"@type": "RegistrationsBaseUrl"
|
701
|
+
}
|
702
|
+
]
|
703
|
+
}
|
704
|
+
"""),
|
705
|
+
// all other requests are unauthorized
|
706
|
+
_ => (401, "{}"),
|
707
|
+
};
|
708
|
+
}
|
709
|
+
using var http = TestHttpServer.CreateTestStringServer(TestHttpHandler);
|
710
|
+
await TestAnalyzeAsync(
|
711
|
+
extraFiles:
|
712
|
+
[
|
713
|
+
("NuGet.Config", $"""
|
714
|
+
<configuration>
|
715
|
+
<packageSources>
|
716
|
+
<clear />
|
717
|
+
<add key="private_feed" value="{http.BaseUrl.TrimEnd('/')}/index.json" allowInsecureConnections="true" />
|
718
|
+
</packageSources>
|
719
|
+
</configuration>
|
720
|
+
""")
|
721
|
+
],
|
722
|
+
discovery: new()
|
723
|
+
{
|
724
|
+
Path = "/",
|
725
|
+
Projects = [
|
726
|
+
new()
|
727
|
+
{
|
728
|
+
FilePath = "./project.csproj",
|
729
|
+
TargetFrameworks = ["net8.0"],
|
730
|
+
Dependencies = [
|
731
|
+
new("Some.Package", "1.2.3", DependencyType.PackageReference),
|
732
|
+
],
|
733
|
+
}
|
734
|
+
]
|
735
|
+
},
|
736
|
+
dependencyInfo: new()
|
737
|
+
{
|
738
|
+
Name = "Some.Package",
|
739
|
+
Version = "1.2.3",
|
740
|
+
IgnoredVersions = [],
|
741
|
+
IsVulnerable = false,
|
742
|
+
Vulnerabilities = [],
|
743
|
+
},
|
744
|
+
expectedResult: new()
|
745
|
+
{
|
746
|
+
ErrorType = ErrorType.AuthenticationFailure,
|
747
|
+
ErrorDetails = $"({http.BaseUrl.TrimEnd('/')}/index.json)",
|
748
|
+
UpdatedVersion = string.Empty,
|
749
|
+
CanUpdate = false,
|
750
|
+
UpdatedDependencies = [],
|
751
|
+
}
|
752
|
+
);
|
753
|
+
}
|
304
754
|
}
|
@@ -142,4 +142,27 @@ public class CompatibilityCheckerTests
|
|
142
142
|
|
143
143
|
Assert.False(result);
|
144
144
|
}
|
145
|
+
|
146
|
+
[Theory]
|
147
|
+
[InlineData("netstandard2.0")]
|
148
|
+
[InlineData("net472")]
|
149
|
+
[InlineData("net6.0")]
|
150
|
+
[InlineData("net7.0")]
|
151
|
+
[InlineData("net8.0")]
|
152
|
+
public void EverythingIsCompatibleWithAnyVersion0Framework(string projectFramework)
|
153
|
+
{
|
154
|
+
var package = new PackageIdentity("Dependency", NuGetVersion.Parse("1.0.0"));
|
155
|
+
ImmutableArray<NuGetFramework> projectFrameworks = [NuGetFramework.Parse(projectFramework)];
|
156
|
+
var isDevDependency = false;
|
157
|
+
ImmutableArray<NuGetFramework> packageFrameworks = [NuGetFramework.Parse("Any,Version=v0.0")];
|
158
|
+
|
159
|
+
var result = CompatibilityChecker.PerformCheck(
|
160
|
+
package,
|
161
|
+
projectFrameworks,
|
162
|
+
isDevDependency,
|
163
|
+
packageFrameworks,
|
164
|
+
new Logger(verbose: false));
|
165
|
+
|
166
|
+
Assert.True(result);
|
167
|
+
}
|
145
168
|
}
|
@@ -32,6 +32,7 @@ public class RequirementTests
|
|
32
32
|
[InlineData("2.0", "~> 1.0", false)]
|
33
33
|
[InlineData("1", "~> 1", true)]
|
34
34
|
[InlineData("2", "~> 1", false)]
|
35
|
+
[InlineData("5.3.8", "< 6, > 5.2.4", true)]
|
35
36
|
public void IsSatisfiedBy(string versionString, string requirementString, bool expected)
|
36
37
|
{
|
37
38
|
var version = NuGetVersion.Parse(versionString);
|
@@ -40,6 +40,8 @@ public class DiscoveryWorkerTestBase
|
|
40
40
|
ValidateResultWithDependencies(expectedResult.DotNetToolsJson, actualResult.DotNetToolsJson);
|
41
41
|
ValidateProjectResults(expectedResult.Projects, actualResult.Projects);
|
42
42
|
Assert.Equal(expectedResult.ExpectedProjectCount ?? expectedResult.Projects.Length, actualResult.Projects.Length);
|
43
|
+
Assert.Equal(expectedResult.ErrorType, actualResult.ErrorType);
|
44
|
+
Assert.Equal(expectedResult.ErrorDetails, actualResult.ErrorDetails);
|
43
45
|
|
44
46
|
return;
|
45
47
|
|
@@ -1,3 +1,7 @@
|
|
1
|
+
using System.Text.Json;
|
2
|
+
|
3
|
+
using NuGetUpdater.Core.Discover;
|
4
|
+
|
1
5
|
using Xunit;
|
2
6
|
|
3
7
|
namespace NuGetUpdater.Core.Test.Discover;
|
@@ -55,6 +59,54 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
|
|
55
59
|
);
|
56
60
|
}
|
57
61
|
|
62
|
+
[Fact]
|
63
|
+
public async Task TestDependencyWithTrailingSpacesInAttribute()
|
64
|
+
{
|
65
|
+
await TestDiscoveryAsync(
|
66
|
+
packages:
|
67
|
+
[
|
68
|
+
MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"),
|
69
|
+
],
|
70
|
+
workspacePath: "src",
|
71
|
+
files: new[]
|
72
|
+
{
|
73
|
+
("src/project.csproj", """
|
74
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
75
|
+
<PropertyGroup>
|
76
|
+
<TargetFramework>net8.0</TargetFramework>
|
77
|
+
<SomePackageVersion>9.0.1</SomePackageVersion>
|
78
|
+
</PropertyGroup>
|
79
|
+
|
80
|
+
<ItemGroup>
|
81
|
+
<PackageReference Include=" Some.Package " Version="$(SomePackageVersion)" />
|
82
|
+
</ItemGroup>
|
83
|
+
</Project>
|
84
|
+
""")
|
85
|
+
},
|
86
|
+
expectedResult: new()
|
87
|
+
{
|
88
|
+
Path = "src",
|
89
|
+
Projects = [
|
90
|
+
new()
|
91
|
+
{
|
92
|
+
FilePath = "project.csproj",
|
93
|
+
TargetFrameworks = ["net8.0"],
|
94
|
+
ReferencedProjectPaths = [],
|
95
|
+
ExpectedDependencyCount = 2,
|
96
|
+
Dependencies = [
|
97
|
+
new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk),
|
98
|
+
new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true)
|
99
|
+
],
|
100
|
+
Properties = [
|
101
|
+
new("SomePackageVersion", "9.0.1", "src/project.csproj"),
|
102
|
+
new("TargetFramework", "net8.0", "src/project.csproj"),
|
103
|
+
]
|
104
|
+
}
|
105
|
+
]
|
106
|
+
}
|
107
|
+
);
|
108
|
+
}
|
109
|
+
|
58
110
|
[Fact]
|
59
111
|
public async Task TestPackageConfig()
|
60
112
|
{
|
@@ -322,4 +374,100 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
|
|
322
374
|
}
|
323
375
|
);
|
324
376
|
}
|
377
|
+
|
378
|
+
[Fact]
|
379
|
+
public async Task ResultFileHasCorrectShapeForAuthenticationFailure()
|
380
|
+
{
|
381
|
+
using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync([]);
|
382
|
+
var discoveryResultPath = Path.Combine(temporaryDirectory.DirectoryPath, DiscoveryWorker.DiscoveryResultFileName);
|
383
|
+
await DiscoveryWorker.WriteResultsAsync(temporaryDirectory.DirectoryPath, discoveryResultPath, new()
|
384
|
+
{
|
385
|
+
ErrorType = ErrorType.AuthenticationFailure,
|
386
|
+
ErrorDetails = "<some package feed>",
|
387
|
+
Path = "/",
|
388
|
+
Projects = [],
|
389
|
+
});
|
390
|
+
var discoveryContents = await File.ReadAllTextAsync(discoveryResultPath);
|
391
|
+
|
392
|
+
// raw result file should look like this:
|
393
|
+
// {
|
394
|
+
// ...
|
395
|
+
// "ErrorType": "AuthenticationFailure",
|
396
|
+
// "ErrorDetails": "<some package feed>",
|
397
|
+
// ...
|
398
|
+
// }
|
399
|
+
var jsonDocument = JsonDocument.Parse(discoveryContents);
|
400
|
+
var errorType = jsonDocument.RootElement.GetProperty("ErrorType");
|
401
|
+
var errorDetails = jsonDocument.RootElement.GetProperty("ErrorDetails");
|
402
|
+
|
403
|
+
Assert.Equal("AuthenticationFailure", errorType.GetString());
|
404
|
+
Assert.Equal("<some package feed>", errorDetails.GetString());
|
405
|
+
}
|
406
|
+
|
407
|
+
[Fact]
|
408
|
+
public async Task ReportsPrivateSourceAuthenticationFailure()
|
409
|
+
{
|
410
|
+
static (int, string) TestHttpHandler(string uriString)
|
411
|
+
{
|
412
|
+
var uri = new Uri(uriString, UriKind.Absolute);
|
413
|
+
var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
|
414
|
+
return uri.PathAndQuery switch
|
415
|
+
{
|
416
|
+
// initial request is good
|
417
|
+
"/index.json" => (200, $$"""
|
418
|
+
{
|
419
|
+
"version": "3.0.0",
|
420
|
+
"resources": [
|
421
|
+
{
|
422
|
+
"@id": "{{baseUrl}}/download",
|
423
|
+
"@type": "PackageBaseAddress/3.0.0"
|
424
|
+
},
|
425
|
+
{
|
426
|
+
"@id": "{{baseUrl}}/query",
|
427
|
+
"@type": "SearchQueryService"
|
428
|
+
},
|
429
|
+
{
|
430
|
+
"@id": "{{baseUrl}}/registrations",
|
431
|
+
"@type": "RegistrationsBaseUrl"
|
432
|
+
}
|
433
|
+
]
|
434
|
+
}
|
435
|
+
"""),
|
436
|
+
// all other requests are unauthorized
|
437
|
+
_ => (401, "{}"),
|
438
|
+
};
|
439
|
+
}
|
440
|
+
using var http = TestHttpServer.CreateTestStringServer(TestHttpHandler);
|
441
|
+
await TestDiscoveryAsync(
|
442
|
+
workspacePath: "",
|
443
|
+
files:
|
444
|
+
[
|
445
|
+
("project.csproj", """
|
446
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
447
|
+
<PropertyGroup>
|
448
|
+
<TargetFramework>net8.0</TargetFramework>
|
449
|
+
</PropertyGroup>
|
450
|
+
<ItemGroup>
|
451
|
+
<PackageReference Include="Some.Package" Version="1.2.3" />
|
452
|
+
</ItemGroup>
|
453
|
+
</Project>
|
454
|
+
"""),
|
455
|
+
("NuGet.Config", $"""
|
456
|
+
<configuration>
|
457
|
+
<packageSources>
|
458
|
+
<clear />
|
459
|
+
<add key="private_feed" value="{http.BaseUrl.TrimEnd('/')}/index.json" allowInsecureConnections="true" />
|
460
|
+
</packageSources>
|
461
|
+
</configuration>
|
462
|
+
"""),
|
463
|
+
],
|
464
|
+
expectedResult: new()
|
465
|
+
{
|
466
|
+
ErrorType = ErrorType.AuthenticationFailure,
|
467
|
+
ErrorDetails = $"({http.BaseUrl.TrimEnd('/')}/index.json)",
|
468
|
+
Path = "",
|
469
|
+
Projects = [],
|
470
|
+
}
|
471
|
+
);
|
472
|
+
}
|
325
473
|
}
|