Skip to content
Draft
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
30 changes: 7 additions & 23 deletions tests/FSharp.Test.Utilities/TestFramework.fs
Original file line number Diff line number Diff line change
Expand Up @@ -515,33 +515,19 @@ module Command =

let exec dir envVars (redirect:RedirectInfo) path args =

#if !NETCOREAPP
let ensureConsole () =
// Set UTF-8 encoding for console input/output to ensure FSI receives UTF-8 data.
// This is needed because on net472 ProcessStartInfo.StandardInputEncoding is unavailable,
// so the spawned process inherits the console's encoding settings.
Console.InputEncoding <- Text.UTF8Encoding(false)
Console.OutputEncoding <- Text.UTF8Encoding(false)
#else
let ensureConsole () = ()
#endif

let inputWriter sources (writer: StreamWriter) =
let pipeFile name = async {
let path = Commands.getfullpath dir name

// Read file content as text using UTF-8 (the standard encoding for F# source files)
let! content = async {
use reader = new StreamReader(path, Text.Encoding.UTF8, detectEncodingFromByteOrderMarks = true)
return! reader.ReadToEndAsync() |> Async.AwaitTask
}

// Write using the StreamWriter which now uses UTF-8 encoding (set in ensureConsole).
use reader = File.OpenRead (path)
use ms = new MemoryStream()
do! reader.CopyToAsync (ms) |> (Async.AwaitIAsyncResult >> Async.Ignore)
ms.Position <- 0L
try
do! writer.WriteAsync(content) |> Async.AwaitTask
do! ms.CopyToAsync(writer.BaseStream) |> (Async.AwaitIAsyncResult >> Async.Ignore)
do! writer.FlushAsync() |> (Async.AwaitIAsyncResult >> Async.Ignore)
with
| :? System.IO.IOException -> ()
| :? System.IO.IOException -> //input closed is ok if process is closed
()
}
sources |> pipeFile |> Async.RunSynchronously

Expand Down Expand Up @@ -585,8 +571,6 @@ module Command =

let exec cmdArgs =
printfn "%s" (logExec dir path args redirect)
if cmdArgs.RedirectInput.IsSome then
ensureConsole()
Process.exec cmdArgs dir envVars path args

{ RedirectOutput = None; RedirectError = None; RedirectInput = None }
Expand Down
24 changes: 9 additions & 15 deletions tests/FSharp.Test.Utilities/XunitHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -189,35 +189,29 @@ module OneTimeSetup =
// Ensure that the initialization is done only once per test run.
init.Force()

/// `XunitTestFramework` providing parallel console support and conditionally enabling optional xUnit customizations.
/// NOTE: Temporarily disabled due to xUnit3 API incompatibilities
/// TODO: Reimplement for xUnit3 if OneTimeSetup, OpenTelemetry, or cleanup functionality is needed
(*
type FSharpXunitFramework(sink: IMessageSink) =
inherit XunitTestFramework(sink)
type FSharpXunitFramework() =
inherit XunitTestFramework()

do OneTimeSetup.EnsureInitialized()

override this.CreateExecutor (assemblyName) =
{ new XunitTestFrameworkExecutor(assemblyName, this.SourceInformationProvider, this.DiagnosticMessageSink) with
override this.CreateExecutor (assembly) =
{ new XunitTestFrameworkExecutor(new XunitTestAssembly(assembly)) with

// Because xUnit v2 lacks assembly fixture, this is a good place to ensure things get called right at the start of the test run.
override x.RunTestCases(testCases, executionMessageSink, executionOptions) =
// Because xUnit v3 lacks assembly fixture, this is a good place to ensure things get called right at the start of the test run.
override x.RunTestCases(testCases, executionMessageSink, executionOptions, cancellationToken) =

let testRunName = $"RunTests_{assemblyName.Name} {Runtime.InteropServices.RuntimeInformation.FrameworkDescription}"
let testRunName = $"RunTests_{assembly.GetName().Name} {Runtime.InteropServices.RuntimeInformation.FrameworkDescription}"

use _ = new OpenTelemetryExport(testRunName, Environment.GetEnvironmentVariable("FSHARP_OTEL_EXPORT") <> null)

begin
use _ = Activity.startNoTags testRunName
// We can't just call base.RunTestCases here, because it's implementation is async void.
use runner = new XunitTestAssemblyRunner (x.TestAssembly, testCases, x.DiagnosticMessageSink, executionMessageSink, executionOptions)
runner.RunAsync().Wait()
base.RunTestCases(testCases, executionMessageSink, executionOptions, cancellationToken).AsTask().Wait()
end

cleanUpTemporaryDirectoryOfThisTestRun ()
new ValueTask()
}
*)

#if XUNIT_EXTRAS
// Rewrites discovered test cases to support extra parallelization and batch trait injection.
Expand Down
17 changes: 3 additions & 14 deletions tests/FSharp.Test.Utilities/XunitSetup.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,6 @@ type NotThreadSafeResourceCollection() = class end

module XUnitSetup =

// NOTE: Custom TestFramework temporarily disabled due to xUnit3 API incompatibilities
// TODO: Reimplement FSharpXunitFramework for xUnit3 if needed
// [<assembly: TestFramework("FSharp.Test.FSharpXunitFramework", "FSharp.Test.Utilities")>]

// NOTE: CaptureTrace is disabled because it conflicts with TestConsole.ExecutionCapture
// which is used by FSI tests to capture console output. xUnit3's trace capture intercepts
// console output before it can reach TestConsole's redirectors.
// [<assembly: CaptureTrace>]

/// Call this to ensure TestConsole is installed. Safe to call multiple times.
let initialize() = XUnitInit.initialize()

// Force initialization when module is loaded
do initialize()
[<assembly: TestFramework(typeof<FSharpXunitFramework>)>]
do ()

Loading