@@ -38,7 +38,7 @@ public SDKLookup(SharedTestState sharedState)
38
38
}
39
39
40
40
[ Fact ]
41
- public void SdkLookup_Global_Json_Single_Digit_Patch_Rollup ( )
41
+ public void GlobalJson_SingleDigitPatch ( )
42
42
{
43
43
// Set specified SDK version = 9999.3.4-global-dummy
44
44
string requestedVersion = "9999.3.4-global-dummy" ;
@@ -133,7 +133,7 @@ public void SdkLookup_Global_Json_Single_Digit_Patch_Rollup()
133
133
}
134
134
135
135
[ Fact ]
136
- public void SdkLookup_Global_Json_Two_Part_Patch_Rollup ( )
136
+ public void GlobalJson_TwoPartPatch ( )
137
137
{
138
138
// Set specified SDK version = 9999.3.304-global-dummy
139
139
string requestedVersion = "9999.3.304-global-dummy" ;
@@ -226,7 +226,7 @@ public void SdkLookup_Global_Json_Two_Part_Patch_Rollup()
226
226
}
227
227
228
228
[ Fact ]
229
- public void SdkLookup_Negative_Version ( )
229
+ public void NegativeVersion ( )
230
230
{
231
231
GlobalJson . CreateEmpty ( SharedState . CurrentWorkingDir ) ;
232
232
@@ -257,7 +257,7 @@ public void SdkLookup_Negative_Version()
257
257
}
258
258
259
259
[ Fact ]
260
- public void SdkLookup_Must_Pick_The_Highest_Semantic_Version ( )
260
+ public void PickHighestSemanticVersion ( )
261
261
{
262
262
GlobalJson . CreateEmpty ( SharedState . CurrentWorkingDir ) ;
263
263
@@ -355,7 +355,7 @@ public void SdkLookup_Must_Pick_The_Highest_Semantic_Version()
355
355
[ InlineData ( "Latestfeature" ) ]
356
356
[ InlineData ( "latestMINOR" ) ]
357
357
[ InlineData ( "latESTMajor" ) ]
358
- public void It_allows_case_insensitive_roll_forward_policy_names ( string rollForward )
358
+ public void RollForwardPolicy_CaseInsensitive ( string rollForward )
359
359
{
360
360
const string Requested = "9999.0.100" ;
361
361
AddAvailableSdkVersions ( Requested ) ;
@@ -369,7 +369,7 @@ public void It_allows_case_insensitive_roll_forward_policy_names(string rollForw
369
369
370
370
[ Theory ]
371
371
[ MemberData ( nameof ( InvalidGlobalJsonData ) ) ]
372
- public void It_falls_back_to_latest_sdk_for_invalid_global_json ( string globalJsonContents , string [ ] messages )
372
+ public void InvalidGlobalJson_FallsBackToLatestSdk ( string globalJsonContents , string [ ] messages )
373
373
{
374
374
AddAvailableSdkVersions ( "9999.0.100" , "9999.0.300-dummy.9" , "9999.1.402" ) ;
375
375
@@ -387,7 +387,7 @@ public void It_falls_back_to_latest_sdk_for_invalid_global_json(string globalJso
387
387
388
388
[ Theory ]
389
389
[ MemberData ( nameof ( SdkRollForwardData ) ) ]
390
- public void It_rolls_forward_as_expected ( string policy , string requested , bool allowPrerelease , string expected , string [ ] installed )
390
+ public void RollForward ( string policy , string requested , bool allowPrerelease , string expected , string [ ] installed )
391
391
{
392
392
AddAvailableSdkVersions ( installed ) ;
393
393
@@ -409,7 +409,7 @@ public void It_rolls_forward_as_expected(string policy, string requested, bool a
409
409
}
410
410
411
411
[ Fact ]
412
- public void It_uses_latest_stable_sdk_if_allow_prerelease_is_false ( )
412
+ public void AllowPrereleaseFalse_UseLatestRelease ( )
413
413
{
414
414
var installed = new string [ ] {
415
415
"9999.1.702" ,
@@ -437,6 +437,172 @@ public void It_uses_latest_stable_sdk_if_allow_prerelease_is_false()
437
437
. And . HaveStdErrContaining ( $ "SDK path resolved to [{ Path . Combine ( ExecutableDotNet . BinPath , "sdk" , ExpectedVersion ) } ]") ;
438
438
}
439
439
440
+ [ Fact ]
441
+ public void GlobalJson_Paths ( )
442
+ {
443
+ GlobalJson . Sdk sdk = new ( ) { Paths = [ ] } ;
444
+ string globalJsonPath = GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
445
+
446
+ // Add SDK versions
447
+ AddAvailableSdkVersions ( "9999.0.4" ) ;
448
+
449
+ // Paths: none
450
+ // Exe: 9999.0.4
451
+ // Expected: no SDKs found
452
+ RunTest ( )
453
+ . Should ( ) . Fail ( )
454
+ . And . FindAnySdk ( false )
455
+ . And . HaveStdErrContaining ( $ "Empty search paths specified in global.json file: { globalJsonPath } ") ;
456
+
457
+ sdk . Paths = [ GlobalJson . HostSdkPath ] ;
458
+ globalJsonPath = GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
459
+
460
+ // Paths: $host$
461
+ // Exe: 9999.0.4
462
+ // Expected: 9999.0.4 from exe dir
463
+ RunTest ( )
464
+ . Should ( ) . Pass ( )
465
+ . And . HaveStdErrContaining ( ExpectedResolvedSdkOutput ( "9999.0.4" ) ) ;
466
+
467
+ using TestArtifact custom = TestArtifact . Create ( "sdkPath" ) ;
468
+ AddSdkToCustomPath ( custom . Location , "9999.0.4" ) ;
469
+ sdk . Paths = [ custom . Location ] ;
470
+ globalJsonPath = GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
471
+
472
+ // Paths: custom (absolute)
473
+ // Custom: 9999.0.4
474
+ // Exe: 9999.0.4
475
+ // Expected: 9999.0.4 from custom dir
476
+ RunTest ( )
477
+ . Should ( ) . Pass ( )
478
+ . And . HaveStdErrContaining ( ExpectedResolvedSdkOutput ( "9999.0.4" , custom . Location ) ) ;
479
+
480
+ string relativePath = Path . GetRelativePath ( SharedState . CurrentWorkingDir , custom . Location ) ;
481
+ sdk . Paths = [ relativePath ] ;
482
+ GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
483
+
484
+ // Paths: custom (relative, outside current directory)
485
+ // Custom: 9999.0.4
486
+ // Exe: 9999.0.4
487
+ // Expected: 9999.0.4 from custom dir
488
+ RunTest ( )
489
+ . Should ( ) . Pass ( )
490
+ . And . HaveStdErrContaining ( ExpectedResolvedSdkOutput ( "9999.0.4" , custom . Location ) ) ;
491
+
492
+ string underCurrent = SharedState . CurrentWorkingDirArtifact . GetUniqueSubdirectory ( "sdkPath" ) ;
493
+ AddSdkToCustomPath ( underCurrent , "9999.0.4" ) ;
494
+
495
+ relativePath = Path . GetRelativePath ( SharedState . CurrentWorkingDir , underCurrent ) ;
496
+ sdk . Paths = [ relativePath ] ;
497
+ GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
498
+
499
+ // Paths: custom (relative, under current directory)
500
+ // Custom: 9999.0.4
501
+ // Exe: 9999.0.4
502
+ // Expected: 9999.0.4 from custom dir
503
+ RunTest ( )
504
+ . Should ( ) . Pass ( )
505
+ . And . HaveStdErrContaining ( ExpectedResolvedSdkOutput ( "9999.0.4" , Path . Combine ( SharedState . CurrentWorkingDir , relativePath ) ) ) ;
506
+ }
507
+
508
+ [ Fact ]
509
+ public void GlobalJson_Paths_Multiple ( )
510
+ {
511
+ using TestArtifact custom = TestArtifact . Create ( "sdkPath" ) ;
512
+ AddSdkToCustomPath ( custom . Location , "9999.0.0" ) ;
513
+
514
+ GlobalJson . Sdk sdk = new ( ) { Paths = [ custom . Location , GlobalJson . HostSdkPath ] } ;
515
+ GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
516
+
517
+ // Add SDK versions
518
+ AddAvailableSdkVersions ( "9999.0.4" ) ;
519
+
520
+ // Specified SDK
521
+ // version: none
522
+ // paths: custom, $host$
523
+ // Custom: 9999.0.0
524
+ // Exe: 9999.0.4
525
+ // Expected: 9999.0.0 from custom dir
526
+ RunTest ( )
527
+ . Should ( ) . Pass ( )
528
+ . And . HaveStdErrContaining ( ExpectedResolvedSdkOutput ( "9999.0.0" , custom . Location ) ) ;
529
+
530
+ sdk . Version = "9999.0.3" ;
531
+ GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
532
+
533
+ // Specified SDK
534
+ // version: 9999.0.3
535
+ // paths: custom, $host$
536
+ // Custom: 9999.0.0
537
+ // Exe: 9999.0.4
538
+ // Expected: 9999.0.4 from exe dir
539
+ RunTest ( )
540
+ . Should ( ) . Pass ( )
541
+ . And . HaveStdErrContaining ( ExpectedResolvedSdkOutput ( "9999.0.4" ) ) ;
542
+
543
+ sdk . Version = "9999.0.5" ;
544
+ string globalJsonPath = GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
545
+
546
+ // Specified SDK
547
+ // version: 9999.0.5
548
+ // paths: custom, $host$
549
+ // Custom: 9999.0.0
550
+ // Exe: 9999.0.4
551
+ // Expected: no compatible version
552
+ RunTest ( )
553
+ . Should ( ) . Fail ( )
554
+ . And . NotFindCompatibleSdk ( globalJsonPath , sdk . Version )
555
+ . And . FindAnySdk ( true ) ;
556
+
557
+ // Verify we have the expected SDK versions
558
+ RunTest ( "--list-sdks" )
559
+ . Should ( ) . Pass ( )
560
+ . And . HaveStdOutContaining ( $ "9999.0.0 [{ custom . Location } ")
561
+ . And . HaveStdOutContaining ( $ "9999.0.4 [{ ExecutableDotNet . BinPath } ") ;
562
+ }
563
+
564
+ [ Fact ]
565
+ public void GlobalJson_Paths_FirstMatch ( )
566
+ {
567
+ using TestArtifact custom1 = TestArtifact . Create ( "sdkPath1" ) ;
568
+ AddSdkToCustomPath ( custom1 . Location , "9999.0.0" ) ;
569
+ using TestArtifact custom2 = TestArtifact . Create ( "sdkPath2" ) ;
570
+ AddSdkToCustomPath ( custom2 . Location , "9999.0.2" ) ;
571
+ AddAvailableSdkVersions ( "9999.0.1" ) ;
572
+
573
+ GlobalJson . Sdk sdk = new ( ) { Version = "9999.0.1" , Paths = [ custom1 . Location , custom2 . Location , GlobalJson . HostSdkPath ] } ;
574
+ GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
575
+
576
+ // Specified SDK
577
+ // version: none
578
+ // paths: custom1, custom2, $host$
579
+ // Custom1: 9999.0.0
580
+ // Custom2: 9999.0.2
581
+ // Exe: 9999.0.1
582
+ // Expected: 9999.0.2 from custom2 - first match is used, not best match (which would be exe which is an exact match)
583
+ RunTest ( )
584
+ . Should ( ) . Pass ( )
585
+ . And . HaveStdErrContaining ( ExpectedResolvedSdkOutput ( "9999.0.2" , custom2 . Location ) ) ;
586
+
587
+ // Verify we have the expected SDK versions
588
+ RunTest ( "--list-sdks" )
589
+ . Should ( ) . Pass ( )
590
+ . And . HaveStdOutContaining ( $ "9999.0.0 [{ custom1 . Location } ")
591
+ . And . HaveStdOutContaining ( $ "9999.0.2 [{ custom2 . Location } ")
592
+ . And . HaveStdOutContaining ( $ "9999.0.1 [{ ExecutableDotNet . BinPath } ") ;
593
+ }
594
+
595
+ [ Fact ]
596
+ public void GlobalJson_ErrorMessage ( )
597
+ {
598
+ GlobalJson . Sdk sdk = new ( ) { ErrorMessage = "Custom SDK resolution error" } ;
599
+ GlobalJson . Write ( SharedState . CurrentWorkingDir , sdk ) ;
600
+
601
+ RunTest ( )
602
+ . Should ( ) . Fail ( )
603
+ . And . HaveStdErrContaining ( sdk . ErrorMessage ) ;
604
+ }
605
+
440
606
public static IEnumerable < object [ ] > InvalidGlobalJsonData
441
607
{
442
608
get
@@ -472,7 +638,7 @@ public static IEnumerable<object[]> InvalidGlobalJsonData
472
638
473
639
// Use an invalid version value
474
640
yield return new object [ ] {
475
- GlobalJson . FormatVersionSettings ( version : "invalid" ) ,
641
+ GlobalJson . FormatSettings ( new GlobalJson . Sdk ( ) { Version = "invalid" } ) ,
476
642
new [ ] {
477
643
"Version 'invalid' is not valid for the 'sdk/version' value" ,
478
644
IgnoringSDKSettings
@@ -490,7 +656,7 @@ public static IEnumerable<object[]> InvalidGlobalJsonData
490
656
491
657
// Use a policy but no version
492
658
yield return new object [ ] {
493
- GlobalJson . FormatVersionSettings ( policy : "latestPatch" ) ,
659
+ GlobalJson . FormatSettings ( new GlobalJson . Sdk ( ) { RollForward = "latestPatch" } ) ,
494
660
new [ ] {
495
661
"The roll-forward policy 'latestPatch' requires a 'sdk/version' value" ,
496
662
IgnoringSDKSettings
@@ -499,7 +665,7 @@ public static IEnumerable<object[]> InvalidGlobalJsonData
499
665
500
666
// Use an invalid policy value
501
667
yield return new object [ ] {
502
- GlobalJson . FormatVersionSettings ( policy : "invalid" ) ,
668
+ GlobalJson . FormatSettings ( new GlobalJson . Sdk ( ) { RollForward = "invalid" } ) ,
503
669
new [ ] {
504
670
"The roll-forward policy 'invalid' is not supported for the 'sdk/rollForward' value" ,
505
671
IgnoringSDKSettings
@@ -517,7 +683,7 @@ public static IEnumerable<object[]> InvalidGlobalJsonData
517
683
518
684
// Use a prerelease version and allowPrerelease = false
519
685
yield return new object [ ] {
520
- GlobalJson . FormatVersionSettings ( version : "9999.1.402-preview1" , allowPrerelease : false ) ,
686
+ GlobalJson . FormatSettings ( new GlobalJson . Sdk ( ) { Version = "9999.1.402-preview1" , AllowPrerelease = false } ) ,
521
687
new [ ] { "Ignoring the 'sdk/allowPrerelease' value" }
522
688
} ;
523
689
}
@@ -992,6 +1158,15 @@ public static IEnumerable<object[]> SdkRollForwardData
992
1158
}
993
1159
}
994
1160
1161
+ private static void AddSdkToCustomPath ( string sdkRoot , string version )
1162
+ {
1163
+ DotNetBuilder . AddMockSDK ( sdkRoot , version , version ) ;
1164
+
1165
+ // Add a mock framework matching the runtime version for the mock SDK
1166
+ // This allows the host to successfully resolve frameworks for the SDK at the custom location
1167
+ DotNetBuilder . AddMicrosoftNETCoreAppFrameworkMockHostPolicy ( sdkRoot , version ) ;
1168
+ }
1169
+
995
1170
// This method adds a list of new sdk version folders in the specified directory.
996
1171
// The actual contents are 'fake' and the minimum required for SDK discovery.
997
1172
// The dotnet.runtimeconfig.json created uses a dummy framework version (9999.0.0)
@@ -1003,8 +1178,8 @@ private void AddAvailableSdkVersions(params string[] availableVersions)
1003
1178
}
1004
1179
}
1005
1180
1006
- private string ExpectedResolvedSdkOutput ( string expectedVersion )
1007
- => Path . Combine ( "Using .NET SDK dll=[" , ExecutableDotNet . BinPath , "sdk" , expectedVersion , "dotnet.dll]" ) ;
1181
+ private string ExpectedResolvedSdkOutput ( string expectedVersion , string rootPath = null )
1182
+ => $ "Using .NET SDK dll=[{ Path . Combine ( rootPath == null ? ExecutableDotNet . BinPath : rootPath , "sdk" , expectedVersion , "dotnet.dll" ) } ]" ;
1008
1183
1009
1184
private CommandResult RunTest ( ) => RunTest ( "help" ) ;
1010
1185
@@ -1021,6 +1196,7 @@ public sealed class SharedTestState : IDisposable
1021
1196
{
1022
1197
public TestArtifact BaseArtifact { get ; }
1023
1198
1199
+ public TestArtifact CurrentWorkingDirArtifact { get ; }
1024
1200
public string CurrentWorkingDir { get ; }
1025
1201
1026
1202
public SharedTestState ( )
@@ -1035,10 +1211,12 @@ public SharedTestState()
1035
1211
. AddMockSDK ( "10000.0.0" , "9999.0.0" )
1036
1212
. Build ( ) ;
1037
1213
CurrentWorkingDir = currentWorkingSdk . BinPath ;
1214
+ CurrentWorkingDirArtifact = new TestArtifact ( CurrentWorkingDir ) ;
1038
1215
}
1039
1216
1040
1217
public void Dispose ( )
1041
1218
{
1219
+ CurrentWorkingDirArtifact . Dispose ( ) ;
1042
1220
BaseArtifact . Dispose ( ) ;
1043
1221
}
1044
1222
}
0 commit comments