Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify and reuse code around temp dirs in FSharp.Compiler.Service.Tests #18046

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading