@@ -496,6 +496,7 @@ public async Task CreateWslInstance_RemovesStaleFileAtInstallPathBeforeInstallin
496496 public void WslInstallSupport_ParsesVersionAndVerboseDistroList ( )
497497 {
498498 Assert . True ( WslInstallSupport . TryParseWslVersion ( "WSL version: 2.7.3.0" , out var version ) ) ;
499+ Assert . Equal ( new Version ( 2 , 7 , 3 , 0 ) , version ) ;
499500 Assert . True ( WslInstallSupport . SupportsDirectNamedInstall ( version ) ) ;
500501
501502 Assert . True ( WslInstallSupport . TryGetDistroVersion (
@@ -505,6 +506,93 @@ public void WslInstallSupport_ParsesVersionAndVerboseDistroList()
505506 Assert . Equal ( 2 , distroVersion ) ;
506507 }
507508
509+ // Regression: wsl.exe emits UTF-16LE on some Windows builds, and localized
510+ // Windows changes the human-readable label around the stable WSL product token.
511+ [ Theory ]
512+ [ InlineData ( "WSL version: 2.7.3.0" , "2.7.3.0" ) ] // English
513+ [ InlineData ( "WSL-Version: 2.7.7.0" , "2.7.7.0" ) ] // German / NUL-stripped UTF-16
514+ [ InlineData ( "WSL-Version: 2.7.7.0\n Kernelversion: 6.18.26.1-1\n WSLg-Version: 1.0.73.2\n Windows-Version: 10.0.26300.8553" , "2.7.7.0" ) ]
515+ [ InlineData ( "Versión de WSL: 2.7.3.0" , "2.7.3.0" ) ] // Spanish
516+ [ InlineData ( "Versión de WSL: 2.7.3.0\n Kernel: 5.15.0.1" , "2.7.3.0" ) ] // Spanish with trailing lines
517+ [ InlineData ( "WSL バージョン: 2.7.8.0" , "2.7.8.0" ) ] // Japanese-style label
518+ [ InlineData ( "WSL版本: 2.7.9.0" , "2.7.9.0" ) ] // No separator after WSL
519+ public void WslInstallSupport_TryParseWslVersion_HandlesLocalizedAndHyphenatedLabels ( string output , string expectedVersion )
520+ {
521+ Assert . True ( WslInstallSupport . TryParseWslVersion ( output , out var version ) ,
522+ $ "Expected TryParseWslVersion to succeed for: { output } ") ;
523+ Assert . Equal ( Version . Parse ( expectedVersion ) , version ) ;
524+ Assert . True ( WslInstallSupport . SupportsDirectNamedInstall ( version ) ,
525+ $ "Expected parsed version { version } to satisfy minimum install requirement") ;
526+ }
527+
528+ // Mirrors microsoft/WSL localization/strings/*/Resources.resw MessagePackageVersions.
529+ [ Theory ]
530+ [ InlineData ( "cs-CZ" , "Verze WSL: 2.7.3.0" ) ]
531+ [ InlineData ( "da-DK" , "WSL-version: 2.7.3.0" ) ]
532+ [ InlineData ( "de-DE" , "WSL-Version: 2.7.3.0" ) ]
533+ [ InlineData ( "en-GB" , "WSL version: 2.7.3.0" ) ]
534+ [ InlineData ( "en-US" , "WSL version: 2.7.3.0" ) ]
535+ [ InlineData ( "es-ES" , "Versión de WSL: 2.7.3.0" ) ]
536+ [ InlineData ( "fi-FI" , "WSL-versio: 2.7.3.0" ) ]
537+ [ InlineData ( "fr-FR" , "Version WSL : 2.7.3.0" ) ]
538+ [ InlineData ( "hu-HU" , "WSL-verzió: 2.7.3.0" ) ]
539+ [ InlineData ( "it-IT" , "Versione WSL: 2.7.3.0" ) ]
540+ [ InlineData ( "ja-JP" , "WSL バージョン: 2.7.3.0" ) ]
541+ [ InlineData ( "ko-KR" , "WSL 버전: 2.7.3.0" ) ]
542+ [ InlineData ( "nb-NO" , "WSL-versjon: 2.7.3.0" ) ]
543+ [ InlineData ( "nl-NL" , "WSL-versie: 2.7.3.0" ) ]
544+ [ InlineData ( "pl-PL" , "Wersja podsystemu WSL: 2.7.3.0" ) ]
545+ [ InlineData ( "pt-BR" , "Versão do WSL: 2.7.3.0" ) ]
546+ [ InlineData ( "pt-PT" , "Versão WSL: 2.7.3.0" ) ]
547+ [ InlineData ( "ru-RU" , "Версия WSL: 2.7.3.0" ) ]
548+ [ InlineData ( "sv-SE" , "WSL-version: 2.7.3.0" ) ]
549+ [ InlineData ( "tr-TR" , "WSL sürümü: 2.7.3.0" ) ]
550+ [ InlineData ( "zh-CN" , "WSL 版本: 2.7.3.0" ) ]
551+ [ InlineData ( "zh-TW" , "WSL 版本: 2.7.3.0" ) ]
552+ public void WslInstallSupport_TryParseWslVersion_HandlesMicrosoftLocalizedPackageVersionLabels (
553+ string locale ,
554+ string output )
555+ {
556+ Assert . True ( WslInstallSupport . TryParseWslVersion ( output , out var version ) ,
557+ $ "Expected TryParseWslVersion to succeed for { locale } : { output } ") ;
558+ Assert . Equal ( new Version ( 2 , 7 , 3 , 0 ) , version ) ;
559+ }
560+
561+ [ Theory ]
562+ [ InlineData ( "WSL-Version: 2.7.7.0" , "2.7.7.0" ) ]
563+ [ InlineData ( "Versión de WSL: 2.7.3.0" , "2.7.3.0" ) ]
564+ public void WslInstallSupport_TryParseWslVersion_NulStrippedUtf16_ParsesCorrectVersion ( string raw , string expectedVersion )
565+ {
566+ // Simulate UTF-16LE NUL-byte injection then NUL-stripping.
567+ var utf16Encoded = string . Join ( "\0 " , raw . ToCharArray ( ) ) + "\0 " ;
568+ var stripped = utf16Encoded . Replace ( "\0 " , "" ) ;
569+ Assert . True ( WslInstallSupport . TryParseWslVersion ( stripped , out var version ) ,
570+ $ "Expected TryParseWslVersion to succeed for NUL-stripped: { raw } ") ;
571+ Assert . Equal ( Version . Parse ( expectedVersion ) , version ) ;
572+ }
573+
574+ [ Fact ]
575+ public void WslInstallSupport_TryParseWslVersion_IgnoresAdjacentWslAndWindowsVersionLines ( )
576+ {
577+ var output = "WSLg-Version: 1.0.73.2\n "
578+ + "Windows-Version: 10.0.26300.8553\n "
579+ + "Kernelversion: 6.18.26.1-1\n "
580+ + "WSL-Version: 2.7.7.0\n " ;
581+
582+ Assert . True ( WslInstallSupport . TryParseWslVersion ( output , out var version ) ) ;
583+ Assert . Equal ( new Version ( 2 , 7 , 7 , 0 ) , version ) ;
584+ }
585+
586+ [ Fact ]
587+ public void WslInstallSupport_TryParseWslVersion_FailsWhenOnlyAdjacentComponentVersionsArePresent ( )
588+ {
589+ var output = "WSLg-Version: 1.0.73.2\n "
590+ + "Windows-Version: 10.0.26300.8553\n "
591+ + "Kernelversion: 6.18.26.1-1\n " ;
592+
593+ Assert . False ( WslInstallSupport . TryParseWslVersion ( output , out _ ) ) ;
594+ }
595+
508596 [ Fact ]
509597 public void WslInstallSupport_TryGetEnvironmentIssue_DetectsFirmwareVirtualizationOff ( )
510598 {
0 commit comments