Skip to content

Commit 7580b31

Browse files
authored
Tests: prevent in-proc fsi from killing test host with "exit" (#19407)
* wip * fix test * use FSharpScript everywhere, remove ScriptingShims.fsx * cleanup - this can run in parallel * cleanup * fix
1 parent 9b016f5 commit 7580b31

10 files changed

Lines changed: 38 additions & 48 deletions

File tree

tests/FSharp.Compiler.ComponentTests/InteractiveSession/Misc.fs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,9 +1997,13 @@ if toEnd <> [| 3; 4; 5 |] then exit 1
19971997
let name = "World"
19981998
let count = 42
19991999
let greeting = $"Hello, {name}! Count: {count}"
2000+
printfn "%s" greeting
20002001
if greeting <> "Hello, World! Count: 42" then exit 1
20012002
2003+
System.Globalization.CultureInfo.CurrentCulture <- System.Globalization.CultureInfo.InvariantCulture
2004+
20022005
let formatted = $"Pi is approximately {System.Math.PI:F2}"
2006+
printfn "%s" formatted
20032007
if not (formatted.Contains("3.14")) then exit 1
20042008
()
20052009
"""

tests/FSharp.Compiler.ComponentTests/Miscellaneous/FsharpSuiteMigrated.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module ScriptRunner =
2323
let private getOrCreateEngine(args,version) sessionIsolation =
2424
match sessionIsolation with
2525
| ScriptSessionIsolation.Isolated ->
26-
new FSharpScript(args, true, version)
26+
getIsolatedSessionForEval args version
2727
| ScriptSessionIsolation.Shared ->
2828
getSessionForEval args version
2929

tests/FSharp.Test.Utilities/Compiler.fs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,13 +1133,11 @@ module rec Compiler =
11331133
let outputWritten, errorsWritten = capture.OutText, capture.ErrorText
11341134
processScriptResults fs result outputWritten errorsWritten
11351135

1136-
let scriptingShim = Path.Combine(__SOURCE_DIRECTORY__,"ScriptingShims.fsx")
11371136
let private evalScriptFromDisk (fs: FSharpCompilationSource) (script:FSharpScript) : CompilationResult =
11381137

11391138
let fileNames =
11401139
(fs.Source :: fs.AdditionalSources)
11411140
|> List.map (fun x -> x.GetSourceFileName)
1142-
|> List.insertAt 0 scriptingShim
11431141
|> List.map (sprintf " @\"%s\"")
11441142
|> String.Concat
11451143

@@ -1158,13 +1156,21 @@ module rec Compiler =
11581156

11591157
let internal sessionCache =
11601158
Collections.Concurrent.ConcurrentDictionary<Set<string> * LangVersion, FSharpScript>()
1159+
1160+
let internal createSessionWithShadowedExit args version =
1161+
let script = new FSharpScript(additionalArgs=args,quiet=true,langVersion=version)
1162+
script.ApplyExitShadowing()
1163+
script
1164+
1165+
let getIsolatedSessionForEval args version =
1166+
createSessionWithShadowedExit args version
11611167

11621168
let getSessionForEval args version =
11631169
let key = Set args, version
11641170
match sessionCache.TryGetValue(key) with
11651171
| true, script -> script
11661172
| _ ->
1167-
let script = new FSharpScript(additionalArgs=args,quiet=true,langVersion=version)
1173+
let script = createSessionWithShadowedExit args version
11681174
sessionCache.TryAdd(key, script) |> ignore
11691175
script
11701176

tests/FSharp.Test.Utilities/CompilerAssert.fs

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ open FSharp.Compiler.BuildGraph
2222
open System.Runtime.Loader
2323
#endif
2424
open FSharp.Test.Utilities
25+
open FSharp.Test.ScriptHelpers
2526
open Microsoft.CodeAnalysis
2627
open Microsoft.CodeAnalysis.CSharp
2728
open Xunit
@@ -1006,41 +1007,25 @@ Updated automatically, please check diffs in your pull request, changes must be
10061007
// Save CurrentUICulture and GraphNode.culture to restore after FSI session
10071008
// FSI may change these via --preferreduilang option, and the change persists
10081009
// in the static GraphNode.culture which affects async computations in other tests
1009-
let originalUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture
1010-
let originalGraphNodeCulture = GraphNode.culture
1011-
1010+
let originalUICulture = CultureInfo.CurrentUICulture
1011+
let originalGraphNodeCulture = GraphNode.culture
10121012
try
1013-
// Initialize output and input streams
1014-
use inStream = new StringReader("")
10151013
use outStream = new StringWriter()
10161014
use errStream = new StringWriter()
1015+
use script = new FSharpScript(additionalArgs = Array.append [| "--noninteractive" |] options, quiet = false, outWriter = outStream, errWriter = errStream)
1016+
script.ApplyExitShadowing()
1017+
let result, errors = script.Eval(source)
10171018

1018-
// Build command line arguments & start FSI session
1019-
let argv = [| "C:\\fsi.exe" |]
1020-
#if NETCOREAPP
1021-
let args = Array.append argv [|"--noninteractive"; "--targetprofile:netcore"|]
1022-
#else
1023-
let args = Array.append argv [|"--noninteractive"; "--targetprofile:mscorlib"|]
1024-
#endif
1025-
let allArgs = Array.append args options
1026-
1027-
let fsiConfig = FsiEvaluationSession.GetDefaultConfiguration()
1028-
use fsiSession = FsiEvaluationSession.Create(fsiConfig, allArgs, inStream, outStream, errStream, collectible = true)
1029-
1030-
let ch, errors = fsiSession.EvalInteractionNonThrowing source
1031-
1032-
let errorMessages = ResizeArray()
1033-
errors
1034-
|> Seq.iter (fun error -> errorMessages.Add(error.Message))
1019+
let errorMessages = ResizeArray(errors |> Seq.map _.Message)
10351020

1036-
match ch with
1037-
| Choice2Of2 ex -> errorMessages.Add(ex.Message)
1021+
match result with
1022+
| Result.Error ex -> errorMessages.Add(ex.Message)
10381023
| _ -> ()
10391024

10401025
errorMessages, string outStream, string errStream
10411026
finally
10421027
// Restore CurrentUICulture and GraphNode.culture to prevent culture leaking between tests
1043-
System.Threading.Thread.CurrentThread.CurrentUICulture <- originalUICulture
1028+
CultureInfo.CurrentUICulture <- originalUICulture
10441029
GraphNode.culture <- originalGraphNodeCulture
10451030

10461031
static member RunScriptWithOptions options (source: string) (expectedErrorMessages: string list) =

tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,15 @@
2525
<Compile Include="..\scripts\scriptlib.fsx">
2626
<Link>scriptlib.fsx</Link>
2727
</Compile>
28-
<None Include="ScriptingShims.fsx" />
2928
<Compile Include="TestConsole.fs" />
3029
<Compile Include="TestFramework.fs" />
3130
<Compile Include="ILChecker.fs" />
3231
<Compile Include="Utilities.fs" />
3332
<Compile Include="VSInstallDiscovery.fs" />
33+
<Compile Include="ScriptHelpers.fs" />
3434
<Compile Include="CompilerAssert.fs" />
3535
<Compile Include="ProjectGeneration.fs" />
3636
<Compile Include="Assert.fs" />
37-
<Compile Include="ScriptHelpers.fs" />
3837
<Compile Include="Compiler.fs" />
3938
<Compile Include="ILVerifierModule.fs" />
4039
<Compile Include="DataAttributeBase.fs" />

tests/FSharp.Test.Utilities/ScriptHelpers.fs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type LangVersion =
1919
| Preview
2020
| Latest
2121

22-
type FSharpScript(?additionalArgs: string[], ?quiet: bool, ?langVersion: LangVersion) =
22+
type FSharpScript(?additionalArgs: string[], ?quiet: bool, ?langVersion: LangVersion, ?outWriter: IO.TextWriter, ?errWriter: IO.TextWriter) =
2323

2424
let additionalArgs = defaultArg additionalArgs [||]
2525
let quiet = defaultArg quiet true
@@ -44,13 +44,23 @@ type FSharpScript(?additionalArgs: string[], ?quiet: bool, ?langVersion: LangVer
4444

4545
let argv = Array.append baseArgs additionalArgs
4646

47-
let fsi = FsiEvaluationSession.Create (config, argv, TextReader.Null, stdout, stderr)
47+
let outWriter = defaultArg outWriter stdout
48+
let errWriter = defaultArg errWriter stderr
49+
let fsi = FsiEvaluationSession.Create (config, argv, TextReader.Null, outWriter, errWriter)
4850

4951
member _.ValueBound = fsi.ValueBound
5052

5153
member _.Fsi = fsi
5254

53-
member this.Eval(code: string, ?cancellationToken: CancellationToken, ?desiredCulture: Globalization.CultureInfo) =
55+
member _.ApplyExitShadowing() =
56+
fsi.EvalInteraction """
57+
let exit (code:int) =
58+
if code = 0 then
59+
()
60+
else failwith $"Script called function 'exit' with code={code}."
61+
"""
62+
63+
member _.Eval(code: string, ?cancellationToken: CancellationToken, ?desiredCulture: Globalization.CultureInfo) =
5464
let originalCulture = Thread.CurrentThread.CurrentCulture
5565
let originalUICulture = Thread.CurrentThread.CurrentUICulture
5666
Thread.CurrentThread.CurrentCulture <- Option.defaultValue Globalization.CultureInfo.InvariantCulture desiredCulture

tests/FSharp.Test.Utilities/ScriptingShims.fsx

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/FSharp.Test.Utilities/TestFramework.fs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ let rec copyDirectory (sourceDir: string) (destinationDir: string) (recursive: b
6060
[<RequireQualifiedAccess>]
6161
module Commands =
6262

63-
let gate = obj()
64-
6563
// Execute the process pathToExe passing the arguments: arguments with the working directory: workingDir timeout after timeout milliseconds -1 = wait forever
6664
// returns exit code, stdio and stderr as string arrays
6765
let executeProcess pathToExe arguments workingDir =

tests/fsharp/single-test.fs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ open FSharp.Compiler.IO
99

1010
let testConfig = testConfig __SOURCE_DIRECTORY__
1111

12-
let log = printfn
13-
1412
type Permutation =
1513
#if NETCOREAPP
1614
| FSC_NETCORE of optimized: bool * buildOnly: bool

tests/fsharp/tests.fs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ let FSI = FSI_NETFX
2727
#endif
2828
// ^^^^^^^^^^^^ To run these tests in F# Interactive , 'build net40', then send this chunk, then evaluate body of a test ^^^^^^^^^^^^
2929

30-
let log = printfn
31-
3230
module CoreTests =
3331

3432

0 commit comments

Comments
 (0)