@@ -2957,6 +2957,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
29572957 [ "NoOpDuration" ] = value => value . Should ( ) . NotBeNull ( ) ,
29582958 [ "TotalUniquePackagesCount" ] = value => value . Should ( ) . Be ( 1 ) ,
29592959 [ "NewPackagesInstalledCount" ] = value => value . Should ( ) . Be ( 1 ) ,
2960+ [ "AnyPackageIdContainsNonASCIICharacters" ] = value => value . Should ( ) . Be ( false ) ,
29602961 [ "EvaluateLockFileDuration" ] = value => value . Should ( ) . NotBeNull ( ) ,
29612962 [ "CreateRestoreTargetGraphDuration" ] = value => value . Should ( ) . NotBeNull ( ) ,
29622963 [ "GenerateRestoreGraphDuration" ] = value => value . Should ( ) . NotBeNull ( ) ,
@@ -3235,7 +3236,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
32353236
32363237 var projectInformationEvent = telemetryEvents . Single ( e => e . Name . Equals ( "ProjectRestoreInformation" ) ) ;
32373238
3238- projectInformationEvent . Count . Should ( ) . Be ( 49 ) ;
3239+ projectInformationEvent . Count . Should ( ) . Be ( 50 ) ;
32393240 projectInformationEvent [ "RestoreSuccess" ] . Should ( ) . Be ( true ) ;
32403241 projectInformationEvent [ "NoOpResult" ] . Should ( ) . Be ( false ) ;
32413242 projectInformationEvent [ "TotalUniquePackagesCount" ] . Should ( ) . Be ( 2 ) ;
@@ -3644,6 +3645,139 @@ private static PackageSpec CreatePackageSpec(List<TargetFrameworkInformation> tf
36443645 return packageSpec ;
36453646 }
36463647
3648+ [ Fact ]
3649+ public async Task ExecuteAsync_WithASCIIPackageId_AnyPackageIdContainsNonASCIICharactersIsFalse ( )
3650+ {
3651+ // Arrange
3652+ using var pathContext = new SimpleTestPathContext ( ) ;
3653+ var projectName = "TestProject" ;
3654+ var projectPath = Path . Combine ( pathContext . SolutionRoot , projectName ) ;
3655+ PackageSpec packageSpec = ProjectTestHelpers . GetPackageSpec ( projectName , pathContext . SolutionRoot , "net472" , "My.Package1" ) ;
3656+
3657+ await SimpleTestPackageUtility . CreateFolderFeedV3Async (
3658+ pathContext . PackageSource ,
3659+ PackageSaveMode . Defaultv3 ,
3660+ new SimpleTestPackageContext ( "My.Package1" , "1.0.0" ) ) ;
3661+ var logger = new TestLogger ( ) ;
3662+
3663+ var request = new TestRestoreRequest ( packageSpec , new PackageSource [ ] { new PackageSource ( pathContext . PackageSource ) } , pathContext . UserPackagesFolder , logger )
3664+ {
3665+ LockFilePath = Path . Combine ( projectPath , "project.assets.json" ) ,
3666+ ProjectStyle = ProjectStyle . PackageReference ,
3667+ } ;
3668+
3669+ // Set-up telemetry service - Important to set-up the service *after* the package source creation call as that emits telemetry!
3670+ var telemetryEvents = new ConcurrentQueue < TelemetryEvent > ( ) ;
3671+ var _telemetryService = new Mock < INuGetTelemetryService > ( MockBehavior . Loose ) ;
3672+ _telemetryService
3673+ . Setup ( x => x . EmitTelemetryEvent ( It . IsAny < TelemetryEvent > ( ) ) )
3674+ . Callback < TelemetryEvent > ( x => telemetryEvents . Enqueue ( x ) ) ;
3675+
3676+ TelemetryActivity . NuGetTelemetryService = _telemetryService . Object ;
3677+
3678+ // Act
3679+ var restoreCommand = new RestoreCommand ( request ) ;
3680+ RestoreResult result = await restoreCommand . ExecuteAsync ( ) ;
3681+
3682+ // Assert
3683+ result . Success . Should ( ) . BeTrue ( because : logger . ShowMessages ( ) ) ;
3684+ var projectInformationEvent = telemetryEvents . Single ( e => e . Name . Equals ( "ProjectRestoreInformation" ) ) ;
3685+ projectInformationEvent [ "AnyPackageIdContainsNonASCIICharacters" ] . Should ( ) . Be ( false ) ;
3686+ }
3687+
3688+ [ Theory ]
3689+ [ InlineData ( "My_Package" ) ] // underscore
3690+ [ InlineData ( "Pac\u212B age" ) ] // Kelvin sign K (U+212A)
3691+ [ InlineData ( "Package\u03B1 " ) ] // Greek lowercase alpha (U+03B1)
3692+ [ InlineData ( "Package\u00E9 " ) ] // Latin small letter e with acute (U+00E9)
3693+ [ InlineData ( "\u0410 .Package" ) ] // Cyrillic capital A (U+0410)
3694+ public async Task ExecuteAsync_WithNonASCIIPackageId_AnyPackageIdContainsNonASCIICharactersIsTrue ( string packageId )
3695+ {
3696+ // Arrange
3697+ using var pathContext = new SimpleTestPathContext ( ) ;
3698+ var projectName = "TestProject" ;
3699+ var projectPath = Path . Combine ( pathContext . SolutionRoot , projectName ) ;
3700+ PackageSpec packageSpec = ProjectTestHelpers . GetPackageSpec ( projectName , pathContext . SolutionRoot , "net472" , packageId ) ;
3701+
3702+ await SimpleTestPackageUtility . CreateFolderFeedV3Async (
3703+ pathContext . PackageSource ,
3704+ PackageSaveMode . Defaultv3 ,
3705+ new SimpleTestPackageContext ( packageId , "1.0.0" ) ) ;
3706+ var logger = new TestLogger ( ) ;
3707+
3708+ var request = new TestRestoreRequest ( packageSpec , new PackageSource [ ] { new PackageSource ( pathContext . PackageSource ) } , pathContext . UserPackagesFolder , logger )
3709+ {
3710+ LockFilePath = Path . Combine ( projectPath , "project.assets.json" ) ,
3711+ ProjectStyle = ProjectStyle . PackageReference ,
3712+ } ;
3713+
3714+ // Set-up telemetry service - Important to set-up the service *after* the package source creation call as that emits telemetry!
3715+ var telemetryEvents = new ConcurrentQueue < TelemetryEvent > ( ) ;
3716+ var _telemetryService = new Mock < INuGetTelemetryService > ( MockBehavior . Loose ) ;
3717+ _telemetryService
3718+ . Setup ( x => x . EmitTelemetryEvent ( It . IsAny < TelemetryEvent > ( ) ) )
3719+ . Callback < TelemetryEvent > ( x => telemetryEvents . Enqueue ( x ) ) ;
3720+
3721+ TelemetryActivity . NuGetTelemetryService = _telemetryService . Object ;
3722+
3723+ // Act
3724+ var restoreCommand = new RestoreCommand ( request ) ;
3725+ RestoreResult result = await restoreCommand . ExecuteAsync ( ) ;
3726+
3727+ // Assert
3728+ result . Success . Should ( ) . BeTrue ( because : logger . ShowMessages ( ) ) ;
3729+ var projectInformationEvent = telemetryEvents . Single ( e => e . Name . Equals ( "ProjectRestoreInformation" ) ) ;
3730+ projectInformationEvent [ "AnyPackageIdContainsNonASCIICharacters" ] . Should ( ) . Be ( true ) ;
3731+ }
3732+
3733+ [ Theory ]
3734+ [ InlineData ( "My_Package" ) ] // underscore
3735+ [ InlineData ( "Pac\u212B age" ) ] // Kelvin sign K (U+212A)
3736+ [ InlineData ( "Package\u03B1 " ) ] // Greek lowercase alpha (U+03B1)
3737+ public async Task ExecuteAsync_WithMixedPackageIds_AnyPackageIdContainsNonASCIICharactersIsTrue ( string packageId )
3738+ {
3739+ // Arrange
3740+ using var pathContext = new SimpleTestPathContext ( ) ;
3741+ var projectName = "TestProject" ;
3742+ var projectPath = Path . Combine ( pathContext . SolutionRoot , projectName ) ;
3743+ var asciiOnlyPkg = new SimpleTestPackageContext ( "Some.Package" , "1.0.0" ) ;
3744+ var nonASCIIPkg = new SimpleTestPackageContext ( packageId , "1.0.0" ) ;
3745+ asciiOnlyPkg . Dependencies . Add ( nonASCIIPkg ) ;
3746+
3747+ await SimpleTestPackageUtility . CreateFolderFeedV3Async (
3748+ pathContext . PackageSource ,
3749+ PackageSaveMode . Defaultv3 ,
3750+ asciiOnlyPkg ,
3751+ nonASCIIPkg ) ;
3752+
3753+ PackageSpec packageSpec = ProjectTestHelpers . GetPackageSpec ( projectName , pathContext . SolutionRoot , "net472" , "Some.Package" ) ;
3754+ var logger = new TestLogger ( ) ;
3755+
3756+ var request = new TestRestoreRequest ( packageSpec , new PackageSource [ ] { new PackageSource ( pathContext . PackageSource ) } , pathContext . UserPackagesFolder , logger )
3757+ {
3758+ LockFilePath = Path . Combine ( projectPath , "project.assets.json" ) ,
3759+ ProjectStyle = ProjectStyle . PackageReference ,
3760+ } ;
3761+
3762+ // Set-up telemetry service - Important to set-up the service *after* the package source creation call as that emits telemetry!
3763+ var telemetryEvents = new ConcurrentQueue < TelemetryEvent > ( ) ;
3764+ var _telemetryService = new Mock < INuGetTelemetryService > ( MockBehavior . Loose ) ;
3765+ _telemetryService
3766+ . Setup ( x => x . EmitTelemetryEvent ( It . IsAny < TelemetryEvent > ( ) ) )
3767+ . Callback < TelemetryEvent > ( x => telemetryEvents . Enqueue ( x ) ) ;
3768+
3769+ TelemetryActivity . NuGetTelemetryService = _telemetryService . Object ;
3770+
3771+ // Act
3772+ var restoreCommand = new RestoreCommand ( request ) ;
3773+ RestoreResult result = await restoreCommand . ExecuteAsync ( ) ;
3774+
3775+ // Assert
3776+ result . Success . Should ( ) . BeTrue ( because : logger . ShowMessages ( ) ) ;
3777+ var projectInformationEvent = telemetryEvents . Single ( e => e . Name . Equals ( "ProjectRestoreInformation" ) ) ;
3778+ projectInformationEvent [ "AnyPackageIdContainsNonASCIICharacters" ] . Should ( ) . Be ( true ) ;
3779+ }
3780+
36473781 private Task < GraphNode < RemoteResolveResult > > DoWalkAsync ( RemoteDependencyWalker walker , string name , NuGetFramework framework )
36483782 {
36493783 var range = new LibraryRange
0 commit comments