Skip to content

Commit

Permalink
simplify temp dirs in service (#18046)
Browse files Browse the repository at this point in the history
Co-authored-by: Kevin Ransom (msft) <[email protected]>
  • Loading branch information
majocha and KevinRansom authored Nov 25, 2024
1 parent 744aa02 commit 30d9ea7
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 119 deletions.
73 changes: 13 additions & 60 deletions tests/FSharp.Compiler.Service.Tests/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -473,63 +473,16 @@ let assertRange
Assert.Equal(Position.mkPos expectedStartLine expectedStartColumn, actualRange.Start)
Assert.Equal(Position.mkPos expectedEndLine expectedEndColumn, actualRange.End)

[<AutoOpen>]
module TempDirUtils =
let getTempPath dir =
Path.Combine(tempDirectoryOfThisTestRun.Value.FullName, dir)

/// Returns the file name part of a temp file name created with tryCreateTemporaryFileName ()
/// and an added process id and thread id to ensure uniqueness between threads.
let getTempFileName() =
let tempFileName = getTemporaryFileName ()
try
let tempFile, tempExt = Path.GetFileNameWithoutExtension tempFileName, Path.GetExtension tempFileName
let procId, threadId = Process.GetCurrentProcess().Id, Thread.CurrentThread.ManagedThreadId
String.concat "" [tempFile; "_"; string procId; "_"; string threadId; tempExt] // ext includes dot
finally
try
FileSystem.FileDeleteShim tempFileName
with _ -> ()

/// Given just a file name, returns it with changed extension located in %TEMP%\ExprTests
let getTempFilePathChangeExt dir tmp ext =
Path.Combine(getTempPath dir, Path.ChangeExtension(tmp, ext))

/// If it doesn't exists, create a folder 'ExprTests' in local user's %TEMP% folder
let createTempDir dirName =
let tempPath = getTempPath dirName
do
if Directory.Exists tempPath then ()
else Directory.CreateDirectory tempPath |> ignore

/// Clean up after a test is run. If you need to inspect the create *.fs files, change this function to do nothing, or just break here.
let cleanupTempFiles dirName files =
{ new IDisposable with
member _.Dispose() =
for fileName in files do
try
// cleanup: only the source file is written to the temp dir.
FileSystem.FileDeleteShim fileName
with _ -> ()

try
// remove the dir when empty
let tempPath = getTempPath dirName
if Directory.GetFiles tempPath |> Array.isEmpty then
Directory.Delete tempPath
with _ -> () }

let createProjectOptions dirName fileSources extraArgs =
let fileNames = fileSources |> List.map (fun _ -> getTempFileName())
let temp2 = getTempFileName()
let fileNames = fileNames |> List.map (fun temp1 -> getTempFilePathChangeExt dirName temp1 ".fs")
let dllName = getTempFilePathChangeExt dirName temp2 ".dll"
let projFileName = getTempFilePathChangeExt dirName temp2 ".fsproj"

createTempDir dirName
for fileSource: string, fileName in List.zip fileSources fileNames do
FileSystem.OpenFileForWriteShim(fileName).Write(fileSource)
let args = [| yield! extraArgs; yield! mkProjectCommandLineArgs (dllName, []) |]
let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames |> List.toArray }

cleanupTempFiles dirName (fileNames @ [dllName; projFileName]), options
let createProjectOptions fileSources extraArgs =
let tempDir = createTemporaryDirectory()
let temp2 = getTemporaryFileNameInDirectory tempDir
let dllName = changeExtension temp2 ".dll"
let projFileName = changeExtension temp2 ".fsproj"

let sourceFiles =
[| for fileSource: string in fileSources do
let fileName = changeExtension (getTemporaryFileNameInDirectory tempDir) ".fs"
FileSystem.OpenFileForWriteShim(fileName).Write(fileSource)
fileName |]
let args = [| yield! extraArgs; yield! mkProjectCommandLineArgs (dllName, []) |]
{ checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = sourceFiles }
59 changes: 24 additions & 35 deletions tests/FSharp.Compiler.Service.Tests/ExprTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ open FSharp.Compiler.Service.Tests.Common
open FSharp.Compiler.Symbols
open FSharp.Compiler.Symbols.FSharpExprPatterns

open TestFramework

type FSharpCore =
| FC45
| FC46
Expand Down Expand Up @@ -593,7 +595,7 @@ let testMutableVar = mutableVar 1
let testMutableConst = mutableConst ()
"""

let createOptionsWithArgs args = createProjectOptions dirName [ fileSource1; fileSource2 ] args
let createOptionsWithArgs args = createProjectOptions [ fileSource1; fileSource2 ] args

let createOptions() = createOptionsWithArgs []

Expand Down Expand Up @@ -659,8 +661,7 @@ let test{0}ToStringOperator (e1:{1}) = string e1
/// This test is run in unison with its optimized counterpart below
[<Fact>]
let ``Test Unoptimized Declarations Project1`` () =
let cleanup, options = Project1.createOptionsWithArgs [ "--langversion:preview" ]
use _holder = cleanup
let options = Project1.createOptionsWithArgs [ "--langversion:preview" ]
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -798,8 +799,7 @@ let ``Test Unoptimized Declarations Project1`` () =

[<Fact>]
let ``Test Optimized Declarations Project1`` () =
let cleanup, options = Project1.createOptionsWithArgs [ "--langversion:preview" ]
use _holder = cleanup
let options = Project1.createOptionsWithArgs [ "--langversion:preview" ]
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -938,15 +938,13 @@ let ``Test Optimized Declarations Project1`` () =

let testOperators dnName fsName excludedTests expectedUnoptimized expectedOptimized =

let tempFileName = getTempFileName()
let filePath = getTempFilePathChangeExt dirName tempFileName ".fs"
let dllPath =getTempFilePathChangeExt dirName tempFileName ".dll"
let projFilePath = getTempFilePathChangeExt dirName tempFileName ".fsproj"
let tempFileName = getTemporaryFileName()
let filePath = changeExtension tempFileName ".fs"
let dllPath =changeExtension tempFileName ".dll"
let projFilePath = changeExtension tempFileName ".fsproj"
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=true)

begin
use _cleanup = cleanupTempFiles dirName [filePath; dllPath; projFilePath]
createTempDir dirName
let source = String.Format(Project1.operatorTests, dnName, fsName)
let replace (s:string) r = s.Replace("let " + r, "// let " + r)
let fileSource = excludedTests |> List.fold replace source
Expand Down Expand Up @@ -3128,16 +3126,15 @@ let BigSequenceExpression(outFileOpt,docFileOpt,baseAddressOpt) =
"""


let createOptions() = createProjectOptions dirName [fileSource1] []
let createOptions() = createProjectOptions [fileSource1] []

#if !NETFRAMEWORK && DEBUG
[<Theory(Skip = "Test is known to fail in DEBUG when not using NetFramework. Use RELEASE configuration or NetFramework to run it.")>]
#else
[<Fact>]
#endif
let ``Test expressions of declarations stress big expressions`` () =
let cleanup, options = ProjectStressBigExpressions.createOptions()
use _holder = cleanup
let options = ProjectStressBigExpressions.createOptions()
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand All @@ -3155,8 +3152,7 @@ let ``Test expressions of declarations stress big expressions`` () =
[<Fact>]
#endif
let ``Test expressions of optimized declarations stress big expressions`` () =
let cleanup, options = ProjectStressBigExpressions.createOptions()
use _holder = cleanup
let options = ProjectStressBigExpressions.createOptions()
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -3211,12 +3207,11 @@ let f7() = callXY (C()) (D())
let f8() = callXY (D()) (C())
"""

let createOptions() = createProjectOptions dirName [fileSource1] ["--langversion:7.0"]
let createOptions() = createProjectOptions [fileSource1] ["--langversion:7.0"]

[<Fact>]
let ``Test ProjectForWitnesses1`` () =
let cleanup, options = ProjectForWitnesses1.createOptions()
use _holder = cleanup
let options = ProjectForWitnesses1.createOptions()
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -3259,8 +3254,7 @@ let ``Test ProjectForWitnesses1`` () =

[<Fact>]
let ``Test ProjectForWitnesses1 GetWitnessPassingInfo`` () =
let cleanup, options = ProjectForWitnesses1.createOptions()
use _holder = cleanup
let options = ProjectForWitnesses1.createOptions()
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -3335,12 +3329,11 @@ type MyNumberWrapper =
{ MyNumber: MyNumber }
"""

let createOptions() = createProjectOptions dirName [fileSource1] ["--langversion:7.0"]
let createOptions() = createProjectOptions [fileSource1] ["--langversion:7.0"]

[<Fact>]
let ``Test ProjectForWitnesses2`` () =
let cleanup, options = ProjectForWitnesses2.createOptions()
use _holder = cleanup
let options = ProjectForWitnesses2.createOptions()
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -3391,12 +3384,11 @@ let s2 = sign p1
"""

let createOptions() = createProjectOptions dirName [fileSource1] ["--langversion:7.0"]
let createOptions() = createProjectOptions [fileSource1] ["--langversion:7.0"]

[<Fact>]
let ``Test ProjectForWitnesses3`` () =
let cleanup, options = createProjectOptions dirName [ ProjectForWitnesses3.fileSource1 ] ["--langversion:7.0"]
use _holder = cleanup
let options = createProjectOptions [ ProjectForWitnesses3.fileSource1 ] ["--langversion:7.0"]
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -3426,8 +3418,7 @@ let ``Test ProjectForWitnesses3`` () =

[<Fact>]
let ``Test ProjectForWitnesses3 GetWitnessPassingInfo`` () =
let cleanup, options = ProjectForWitnesses3.createOptions()
use _holder = cleanup
let options = ProjectForWitnesses3.createOptions()
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -3485,12 +3476,11 @@ let isNullQuoted (ts : 't[]) =
"""

let createOptions() = createProjectOptions dirName [fileSource1] ["--langversion:7.0"]
let createOptions() = createProjectOptions [fileSource1] ["--langversion:7.0"]

[<Fact>]
let ``Test ProjectForWitnesses4 GetWitnessPassingInfo`` () =
let cleanup, options = ProjectForWitnesses4.createOptions()
use _holder = cleanup
let options = ProjectForWitnesses4.createOptions()
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -3523,12 +3513,11 @@ module N.M
let rec f = new System.EventHandler(fun _ _ -> f.Invoke(null,null))
"""

let createOptions() = createProjectOptions dirName [fileSource1] []
let createOptions() = createProjectOptions [fileSource1] []

[<Fact>]
let ``Test NoWarn HashDirective`` () =
let cleanup, options = ProjectForNoWarnHashDirective.createOptions()
use _holder = cleanup
let options = ProjectForNoWarnHashDirective.createOptions()
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down
12 changes: 3 additions & 9 deletions tests/FSharp.Compiler.Service.Tests/GeneratedCodeSymbolsTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ open FSharp.Compiler.CodeAnalysis
open FSharp.Compiler.Service.Tests.Common
open FSharp.Compiler.Symbols

[<Literal>]
let dirName = "GeneratedCodeSymbolsTests"

[<Fact>]
let ``IsUnionCaseTester for Is* member in a class`` () =
let source = """
Expand All @@ -16,8 +13,7 @@ module Lib
type T () =
member x.IsM = 1
"""
let cleanup, options = createProjectOptions dirName [ source ] [ "--langversion:preview" ]
use _holder = cleanup
let options = createProjectOptions [ source ] [ "--langversion:preview" ]
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=false)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -46,8 +42,7 @@ module Lib
type T = A | B
"""
let cleanup, options = createProjectOptions dirName [ source ] [ "--langversion:preview" ]
use _holder = cleanup
let options = createProjectOptions [ source ] [ "--langversion:preview" ]
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=false)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down Expand Up @@ -80,8 +75,7 @@ type T =
member x.IsC
with get () = false
"""
let cleanup, options = createProjectOptions dirName [ source ] [ "--langversion:preview" ]
use _holder = cleanup
let options = createProjectOptions [ source ] [ "--langversion:preview" ]
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=false)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate

Expand Down
6 changes: 3 additions & 3 deletions tests/FSharp.Compiler.Service.Tests/ScriptOptionsTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ let ``can generate options for different frameworks regardless of execution envi
[<InlineData("--targetprofile:netcore")>]
[<InlineData("--targetprofile:netstandard")>]
let ``can resolve nuget packages to right target framework for different frameworks regardless of execution environment``(flag) =
let path = DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)).FullName
let file = (getTemporaryFileNameInDirectory path) + ".fsx"
let scriptFullPath = Path.Combine(path, file)
let dir = DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location))
let file = (getTemporaryFileNameInDirectory dir) + ".fsx"
let scriptFullPath = Path.Combine(dir.FullName, file)
let scriptSource = """
#r "nuget: FSharp.Data, 3.3.3"
open System
Expand Down
17 changes: 7 additions & 10 deletions tests/FSharp.Test.Utilities/CompilerAssert.fs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ module CompilerAssertHelpers =
let name =
match nameOpt with
| Some name -> name
| _ -> getTemporaryFileNameInDirectory outputDirectory.FullName
| _ -> getTemporaryFileNameInDirectory outputDirectory

let outputFilePath = Path.ChangeExtension (Path.Combine(outputDirectory.FullName, name), if isExe then ".exe" else ".dll")
let sources =
Expand Down Expand Up @@ -508,7 +508,7 @@ module CompilerAssertHelpers =

let compile isExe options (source:SourceCodeFileKind) f =
let outputFilePath = Path.ChangeExtension (getTemporaryFileName (), if isExe then ".exe" else ".dll")
let tempDir = Path.GetDirectoryName outputFilePath
let tempDir = Directory.GetParent outputFilePath

let sourceFile =
match source.GetSourceText with
Expand All @@ -521,10 +521,7 @@ module CompilerAssertHelpers =
// On Disk file
source

try
f (rawCompile outputFilePath isExe options TargetFramework.Current [sourceFile])
finally
try Directory.Delete(tempDir, true) with | _ -> ()
f (rawCompile outputFilePath isExe options TargetFramework.Current [sourceFile])

let rec compileCompilationAux outputDirectory ignoreWarnings (cmpl: Compilation) : (FSharpDiagnostic[] * exn option * string) * string list =

Expand All @@ -548,21 +545,21 @@ module CompilerAssertHelpers =

res, (deps @ deps2)

and evaluateReferences (outputPath:DirectoryInfo) ignoreWarnings (cmpl: Compilation) : string[] * string list =
and evaluateReferences (outputDir:DirectoryInfo) ignoreWarnings (cmpl: Compilation) : string[] * string list =
match cmpl with
| Compilation(_, _, _, _, cmpls, _, _) ->
let compiledRefs =
cmpls
|> List.map (fun cmpl ->
match cmpl with
| CompilationReference (cmpl, staticLink) ->
compileCompilationAux outputPath ignoreWarnings cmpl, staticLink
compileCompilationAux outputDir ignoreWarnings cmpl, staticLink
| TestCompilationReference (cmpl) ->
let fileName =
match cmpl with
| TestCompilation.CSharp c when not (String.IsNullOrWhiteSpace c.AssemblyName) -> c.AssemblyName
| _ -> getTemporaryFileNameInDirectory outputPath.FullName
let tmp = Path.Combine(outputPath.FullName, Path.ChangeExtension(fileName, ".dll"))
| _ -> getTemporaryFileNameInDirectory outputDir
let tmp = Path.Combine(outputDir.FullName, Path.ChangeExtension(fileName, ".dll"))
cmpl.EmitAsFile tmp
(([||], None, tmp), []), false)

Expand Down
6 changes: 4 additions & 2 deletions tests/FSharp.Test.Utilities/TestFramework.fs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ let createTemporaryDirectory () =
let getTemporaryFileName () =
createTemporaryDirectory().FullName ++ getShortId()

let getTemporaryFileNameInDirectory (directory: string) =
directory ++ getShortId()
let changeExtension path extension = Path.ChangeExtension(path, extension)

let getTemporaryFileNameInDirectory (directory: DirectoryInfo) =
directory.FullName ++ getShortId()

// Well, this function is AI generated.
let rec copyDirectory (sourceDir: string) (destinationDir: string) (recursive: bool) =
Expand Down

0 comments on commit 30d9ea7

Please sign in to comment.