@@ -880,6 +880,124 @@ public void EmptyFile()
880880 . And . HaveStdOutContaining ( "error CS5001:" ) ; // Program does not contain a static 'Main' method suitable for an entry point
881881 }
882882
883+ /// <summary>
884+ /// See <see href="https://github.com/dotnet/sdk/issues/51778"/>.
885+ /// </summary>
886+ [ Theory , CombinatorialData ]
887+ public void WorkingDirectory ( bool cscOnly )
888+ {
889+ var testInstance = _testAssetsManager . CreateTestDirectory ( baseDirectory : cscOnly ? OutOfTreeBaseDirectory : null ) ;
890+ var programPath = Path . Join ( testInstance . Path , "Program.cs" ) ;
891+
892+ var code = """
893+ Console.WriteLine("v1");
894+ Console.WriteLine(Environment.CurrentDirectory);
895+ Console.WriteLine(Directory.GetCurrentDirectory());
896+ Console.WriteLine(new DirectoryInfo(".").FullName);
897+ Console.WriteLine(AppContext.GetData("EntryPointFileDirectoryPath"));
898+ """ ;
899+
900+ File . WriteAllText ( programPath , code ) ;
901+
902+ var workDir = TestPathUtility . ResolveTempPrefixLink ( Path . GetTempPath ( ) ) . TrimEnd ( Path . DirectorySeparatorChar ) ;
903+
904+ var artifactsDir = VirtualProjectBuildingCommand . GetArtifactsPath ( programPath ) ;
905+ if ( Directory . Exists ( artifactsDir ) ) Directory . Delete ( artifactsDir , recursive : true ) ;
906+
907+ Build ( testInstance ,
908+ expectedLevel : cscOnly ? BuildLevel . Csc : BuildLevel . All ,
909+ programFileName : programPath ,
910+ workDir : workDir ,
911+ expectedOutput : GetExpectedOutput ( "v1" , workDir ) ) ;
912+
913+ code = code . Replace ( "v1" , "v2" ) ;
914+ File . WriteAllText ( programPath , code ) ;
915+
916+ Build ( testInstance ,
917+ expectedLevel : BuildLevel . Csc ,
918+ programFileName : programPath ,
919+ workDir : workDir ,
920+ expectedOutput : GetExpectedOutput ( "v2" , workDir ) ) ;
921+
922+ string GetExpectedOutput ( string version , string workDir ) => $ """
923+ { version }
924+ { workDir }
925+ { workDir }
926+ { workDir }
927+ { Path . GetDirectoryName ( programPath ) }
928+ """ ;
929+ }
930+
931+ /// <summary>
932+ /// Combination of <see cref="WorkingDirectory"/> and <see cref="CscOnly_AfterMSBuild"/>.
933+ /// </summary>
934+ [ Fact ]
935+ public void WorkingDirectory_CscOnly_AfterMSBuild ( )
936+ {
937+ var testInstance = _testAssetsManager . CreateTestDirectory ( baseDirectory : OutOfTreeBaseDirectory ) ;
938+ var programPath = Path . Join ( testInstance . Path , "Program.cs" ) ;
939+
940+ var code = """
941+ #:property Configuration=Release
942+ Console.WriteLine("v1");
943+ Console.WriteLine(Environment.CurrentDirectory);
944+ Console.WriteLine(Directory.GetCurrentDirectory());
945+ Console.WriteLine(new DirectoryInfo(".").FullName);
946+ Console.WriteLine(AppContext.GetData("EntryPointFileDirectoryPath"));
947+ """ ;
948+
949+ File . WriteAllText ( programPath , code ) ;
950+
951+ var workDir = TestPathUtility . ResolveTempPrefixLink ( Path . GetTempPath ( ) ) . TrimEnd ( Path . DirectorySeparatorChar ) ;
952+
953+ var artifactsDir = VirtualProjectBuildingCommand . GetArtifactsPath ( programPath ) ;
954+ if ( Directory . Exists ( artifactsDir ) ) Directory . Delete ( artifactsDir , recursive : true ) ;
955+
956+ Build ( testInstance ,
957+ expectedLevel : BuildLevel . All ,
958+ programFileName : programPath ,
959+ workDir : workDir ,
960+ expectedOutput : GetExpectedOutput ( "v1" , workDir ) ) ;
961+
962+ Build ( testInstance ,
963+ expectedLevel : BuildLevel . None ,
964+ programFileName : programPath ,
965+ workDir : workDir ,
966+ expectedOutput : GetExpectedOutput ( "v1" , workDir ) ) ;
967+
968+ code = code . Replace ( "v1" , "v2" ) ;
969+ File . WriteAllText ( programPath , code ) ;
970+
971+ Build ( testInstance ,
972+ expectedLevel : BuildLevel . Csc ,
973+ programFileName : programPath ,
974+ workDir : workDir ,
975+ expectedOutput : GetExpectedOutput ( "v2" , workDir ) ) ;
976+
977+ // Can be overridden with a #:property.
978+ var workDir2 = Path . Join ( testInstance . Path , "dir2" ) ;
979+ Directory . CreateDirectory ( workDir2 ) ;
980+ code = $ """
981+ #:property RunWorkingDirectory={ workDir2 }
982+ { code }
983+ """ ;
984+ File . WriteAllText ( programPath , code ) ;
985+
986+ Build ( testInstance ,
987+ expectedLevel : BuildLevel . All ,
988+ programFileName : programPath ,
989+ workDir : workDir ,
990+ expectedOutput : GetExpectedOutput ( "v2" , workDir2 ) ) ;
991+
992+ string GetExpectedOutput ( string version , string workDir ) => $ """
993+ { version }
994+ { workDir }
995+ { workDir }
996+ { workDir }
997+ { Path . GetDirectoryName ( programPath ) }
998+ """ ;
999+ }
1000+
8831001 /// <summary>
8841002 /// Implicit build files have an effect.
8851003 /// </summary>
@@ -3238,7 +3356,7 @@ Release config
32383356 Build ( testInstance , BuildLevel . Csc ) ;
32393357 }
32403358
3241- private void Build ( TestDirectory testInstance , BuildLevel expectedLevel , ReadOnlySpan < string > args = default , string expectedOutput = "Hello from Program" , string programFileName = "Program.cs" )
3359+ private void Build ( TestDirectory testInstance , BuildLevel expectedLevel , ReadOnlySpan < string > args = default , string expectedOutput = "Hello from Program" , string programFileName = "Program.cs" , string ? workDir = null )
32423360 {
32433361 string prefix = expectedLevel switch
32443362 {
@@ -3249,12 +3367,12 @@ private void Build(TestDirectory testInstance, BuildLevel expectedLevel, ReadOnl
32493367 } ;
32503368
32513369 new DotnetCommand ( Log , [ "run" , programFileName , "-bl" , .. args ] )
3252- . WithWorkingDirectory ( testInstance . Path )
3370+ . WithWorkingDirectory ( workDir ?? testInstance . Path )
32533371 . Execute ( )
32543372 . Should ( ) . Pass ( )
32553373 . And . HaveStdOut ( prefix + expectedOutput ) ;
32563374
3257- var binlogs = new DirectoryInfo ( testInstance . Path )
3375+ var binlogs = new DirectoryInfo ( workDir ?? testInstance . Path )
32583376 . EnumerateFiles ( "*.binlog" , SearchOption . TopDirectoryOnly ) ;
32593377
32603378 binlogs . Select ( f => f . Name )
0 commit comments