Skip to content

Commit f7be8d0

Browse files
auduchinokclaude
andauthored
Unify baseline checking behind a single checkBaseline helper (#19888)
Introduce checkBaseline/checkBaselineWith in the Compiler test module and route the syntax-tree tests, surface-area verification, and the .err.bsl / .il.bsl / .vsbsl component-test baselines through it, replacing each site's own shouldUpdateBaselines check and ad-hoc file writes. The helper reads the baseline file, compares via a pluggable comparer (default exact equality; surface area and error baselines pass a set-based comparer, IL passes an ILChecker-based one), and on mismatch writes the produced content to an output file or updates the baseline when TEST_UPDATE_BSL is set. The output file extension is replaced for .bsl (foo.bsl -> foo.out) and appended otherwise (neg78.vsbsl -> neg78.vsbsl.out) so the .bsl/.vsbsl baselines a single test can have no longer collide. Removes the now-redundant updateBaseLineIfEnvironmentSaysSo, createBaselineErrors, convenienceBaselineInstructions, and assertBaseline, and drops the unused BaselineFile.FilePath field. This also fixes the IL baseline update path, which previously copied the previous run's IL to the baseline because the copy ran before the fresh actual was written. The SyntaxTree-local .gitignore (*.actual) is removed since those tests now write .out, covered by the global *.out rule. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 9bb6b56 commit f7be8d0

6 files changed

Lines changed: 64 additions & 122 deletions

File tree

tests/FSharp.Compiler.Service.Tests/SurfaceArea.fs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,4 @@ type SurfaceAreaTest() =
2828
Assembly.LoadFrom path
2929

3030
let baseline = Path.Combine(__SOURCE_DIRECTORY__, $"FSharp.Compiler.Service.SurfaceArea.{platform}.bsl")
31-
let outFileName = Path.Combine(__SOURCE_DIRECTORY__, $"FSharp.Compiler.Service.SurfaceArea.{platform}.out")
32-
FSharp.Test.SurfaceArea.verify assembly baseline outFileName
31+
FSharp.Test.SurfaceArea.verify assembly baseline

tests/FSharp.Compiler.Service.Tests/SyntaxTreeTests.fs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -178,25 +178,7 @@ let ParseFile fileName =
178178
|> normalize
179179
|> sprintf "%s\n"
180180

181-
let bslPath = $"{fullPath}.bsl"
182-
let actualPath = $"{fullPath}.actual"
183-
184-
let expected =
185-
if File.Exists bslPath then
186-
File.ReadAllText bslPath |> normalize
187-
else
188-
"No baseline was found"
189-
190-
if expected = actual then
191-
File.Delete(actualPath)
192-
else
193-
if shouldUpdateBaselines then
194-
File.Delete(actualPath)
195-
File.WriteAllText(bslPath, actual)
196-
else
197-
File.WriteAllText(actualPath, actual)
198-
199-
Assert.Equal(expected, actual)
181+
checkBaseline actual $"{fullPath}.bsl"
200182

201183
// Run type checker to assert that it doesn't fail with the tree produced by the parser
202184
CompilerAssert.ParseAndTypeCheck([|"--langversion:preview"|], fileName, contents) |> ignore

tests/FSharp.Core.UnitTests/SurfaceArea.fs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,4 @@ type SurfaceAreaTest() =
3838
#endif
3939
let assembly = typeof<int list>.Assembly
4040
let baseline = Path.Combine(__SOURCE_DIRECTORY__, $"FSharp.Core.SurfaceArea.{platform}.{flavor}.bsl")
41-
let outFileName = Path.Combine(Path.GetDirectoryName(assembly.Location), $"FSharp.Core.SurfaceArea.{platform}.{flavor}.out")
42-
SurfaceArea.verify assembly baseline outFileName
41+
SurfaceArea.verify assembly baseline

tests/FSharp.Test.Utilities/Compiler.fs

Lines changed: 50 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,54 @@ module rec Compiler =
3030
let shouldUpdateBaselines =
3131
Environment.GetEnvironmentVariable("TEST_UPDATE_BSL") <> null
3232

33+
let private baselineFailureMessage (expectedFile: string) (outFile: string) (diff: string) =
34+
$"""Baseline mismatch for {expectedFile}
35+
to update the baseline:
36+
$ cp {outFile} {expectedFile}
37+
to compare:
38+
$ code --diff {outFile} {expectedFile}
39+
(or set TEST_UPDATE_BSL=1 and re-run to update the baseline automatically)
40+
{diff}"""
41+
42+
let private baselineOutputFile (expectedFile: string) =
43+
if Path.GetExtension(expectedFile) = ".bsl" then
44+
Path.ChangeExtension(expectedFile, ".out")
45+
else
46+
expectedFile + ".out"
47+
48+
let checkBaselineWith (compare: string -> string -> string option) (expected: string) (expectedFile: string) =
49+
let outFile = baselineOutputFile expectedFile
50+
let baselineContent =
51+
if FileSystem.FileExistsShim expectedFile then File.ReadAllText expectedFile else ""
52+
let diff = compare baselineContent expected
53+
54+
match diff with
55+
| None ->
56+
if FileSystem.FileExistsShim outFile then
57+
FileSystem.FileDeleteShim outFile
58+
| Some diff ->
59+
if shouldUpdateBaselines then
60+
if FileSystem.FileExistsShim outFile then
61+
FileSystem.FileDeleteShim outFile
62+
File.WriteAllText(expectedFile, expected)
63+
else
64+
File.WriteAllText(outFile, expected)
65+
66+
Assert.True(false, baselineFailureMessage expectedFile outFile diff)
67+
68+
let checkBaseline (expected: string) (expectedFile: string) =
69+
let compare fileContent produced =
70+
let e = normalizeNewlines fileContent
71+
let a = normalizeNewlines produced
72+
if e = a then None else Some $"Expected:\n{e}\nActual:\n{a}"
73+
checkBaselineWith compare expected expectedFile
74+
3375
[<AutoOpen>]
3476
type SourceUtilities () =
3577
static member getCurrentMethodName([<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string) = memberName
3678

3779
type BaselineFile =
3880
{
39-
FilePath: string
4081
BslSource: string
4182
Content: string option
4283
}
@@ -251,8 +292,6 @@ module rec Compiler =
251292
| Some s -> s
252293
| None -> sourceFilePath + sourceBaselineSuffix + ".il.bsl"
253294

254-
let fsOutFilePath = normalizePathSeparator (Path.ChangeExtension(outputDirectoryPath ++ filename, ".err"))
255-
let ilOutFilePath = normalizePathSeparator (Path.ChangeExtension(outputDirectoryPath ++ filename, ".il"))
256295
let fsBslSource = readFileOrDefault fsBslFilePath
257296
let ilBslSource = readFileOrDefault ilBslFilePath
258297

@@ -262,8 +301,8 @@ module rec Compiler =
262301
Some
263302
{
264303
SourceFilename = Some sourceFilePath
265-
FSBaseline = { FilePath = fsOutFilePath; BslSource = fsBslFilePath; Content = fsBslSource }
266-
ILBaseline = { FilePath = ilOutFilePath; BslSource = ilBslFilePath; Content = ilBslSource }
304+
FSBaseline = { BslSource = fsBslFilePath; Content = fsBslSource }
305+
ILBaseline = { BslSource = ilBslFilePath; Content = ilBslSource }
267306
}
268307
Options = Compiler.defaultOptions
269308
OutputType = Library
@@ -1220,36 +1259,6 @@ module rec Compiler =
12201259
| _ -> failwith "FSI running only supports F#."
12211260

12221261

1223-
let convenienceBaselineInstructions baseline expected actual =
1224-
$"""to update baseline:
1225-
$ cp {baseline.FilePath} {baseline.BslSource}
1226-
to compare baseline:
1227-
$ code --diff {baseline.FilePath} {baseline.BslSource}
1228-
Expected:
1229-
{expected}
1230-
Actual:
1231-
{actual}"""
1232-
let updateBaseLineIfEnvironmentSaysSo baseline =
1233-
if shouldUpdateBaselines then
1234-
if FileSystem.FileExistsShim baseline.FilePath then
1235-
FileSystem.CopyShim(baseline.FilePath, baseline.BslSource, true)
1236-
1237-
let assertBaseline expected actual baseline fOnFail =
1238-
if expected <> actual then
1239-
fOnFail()
1240-
updateBaseLineIfEnvironmentSaysSo baseline
1241-
createBaselineErrors baseline actual
1242-
Assert.True((expected = actual), convenienceBaselineInstructions baseline expected actual)
1243-
elif FileSystem.FileExistsShim baseline.FilePath then
1244-
FileSystem.FileDeleteShim baseline.FilePath
1245-
1246-
1247-
let private createBaselineErrors (baselineFile: BaselineFile) (actualErrors: string) : unit =
1248-
printfn $"creating baseline error file for convenience: {baselineFile.FilePath}, expected: {baselineFile.BslSource}"
1249-
let file = FileSystem.OpenFileForWriteShim(baselineFile.FilePath)
1250-
file.SetLength(0)
1251-
file.WriteAllText(actualErrors)
1252-
12531262
/// Turn our ErrorInfo back into a genuine FSharpDiagnostic
12541263
let private toFSharpDiagnostic (ei: ErrorInfo) : FSharpDiagnostic =
12551264

@@ -1309,19 +1318,8 @@ Actual:
13091318
match o.Compilation with
13101319
| FS fs -> fs
13111320
| _ -> failwith "verifyBaseline only supports F#"
1312-
let expected =
1313-
fsSource.Baseline.Value.FSBaseline.Content
1314-
|> Option.defaultValue ""
1315-
|> normalizeNewlines
1316-
13171321
// 4) Compare or update
1318-
if expected <> formattedActual then
1319-
// same update mechanism you already have:
1320-
fsSource.CreateOutputDirectory()
1321-
createBaselineErrors fsSource.Baseline.Value.FSBaseline formattedActual
1322-
updateBaseLineIfEnvironmentSaysSo fsSource.Baseline.Value.FSBaseline
1323-
let msg = convenienceBaselineInstructions fsSource.Baseline.Value.FSBaseline expected formattedActual
1324-
Assert.True(false, msg)
1322+
checkBaseline formattedActual fsSource.Baseline.Value.FSBaseline.BslSource
13251323

13261324
// 5) Return the original result for fluent chaining
13271325
cResult
@@ -1387,14 +1385,8 @@ Actual:
13871385
| None -> String.Empty
13881386
let success, errorMsg, actualIL = ILChecker.verifyILAndReturnActual [] p [expectedIL]
13891387

1390-
if not success then
1391-
// Failed try update baselines if required
1392-
// If we are here then the il file has been produced we can write it back to the baseline location
1393-
// if the environment variable TEST_UPDATE_BSL has been set
1394-
updateBaseLineIfEnvironmentSaysSo baseline.ILBaseline
1395-
createBaselineErrors baseline.ILBaseline actualIL
1396-
let errorMsg = (convenienceBaselineInstructions baseline.ILBaseline expectedIL actualIL) + errorMsg
1397-
Assert.Fail(errorMsg)
1388+
let compare _ _ = if success then None else Some errorMsg
1389+
checkBaselineWith compare actualIL baseline.ILBaseline.BslSource
13981390

13991391
let verifyILBaseline (compilationResult: CompilationResult) : CompilationResult =
14001392
match compilationResult with
@@ -2011,22 +2003,9 @@ Actual:
20112003
|> String.Concat
20122004

20132005
let withResultsMatchingFile (path:string) (result:CompilationResult) =
2014-
let expectedContent = File.ReadAllText(path) |> normalizeNewLines
2015-
let actualErrors = renderToString result
2016-
2017-
match Assert.shouldBeSameMultilineStringSets expectedContent actualErrors with
2018-
| None -> ()
2019-
| Some diff ->
2020-
if shouldUpdateBaselines then
2021-
File.WriteAllText(path, actualErrors)
2022-
2023-
printfn $"{Path.GetFullPath path} \n {diff}"
2024-
printfn "==========================EXPECTED==========================="
2025-
printfn "%s" expectedContent
2026-
printfn "===========================ACTUAL============================"
2027-
printfn "%s" actualErrors
2028-
Assert.True(String.IsNullOrEmpty(diff), path)
2029-
2006+
let compare fileContent produced =
2007+
Assert.shouldBeSameMultilineStringSets (normalizeNewLines fileContent) produced
2008+
checkBaselineWith compare (renderToString result) path
20302009
result
20312010

20322011
let checkCodes (expected: int list) (selector: CompilationOutput -> ErrorInfo list) (result: CompilationResult) : CompilationResult =

tests/FSharp.Test.Utilities/SurfaceArea.fs

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,42 +42,26 @@ module FSharp.Test.SurfaceArea
4242
|]
4343
assembly, actual
4444

45-
let private appendNewLine str = str + System.Environment.NewLine
46-
4745
// verify public surface area matches expected, handles baseline update when TEST_UPDATE_BSL is set
48-
let verify assembly baselinePath outFilePath : unit =
49-
let expected =
50-
File.ReadAllLines(baselinePath)
51-
|> String.concat System.Environment.NewLine
52-
|> appendNewLine
53-
46+
let verify assembly baselinePath : unit =
5447
let normalize (s:string) = Regex.Replace(s, "(\\r\\n|\\n|\\r)+", Environment.NewLine).Trim()
5548
let asm, actualNotNormalized = getSurfaceAreaForAssembly (assembly)
56-
let actual =
57-
actualNotNormalized
58-
|> Seq.map normalize
49+
let actual =
50+
actualNotNormalized
51+
|> Seq.map normalize
5952
|> Seq.filter (String.IsNullOrWhiteSpace >> not)
6053
|> Seq.sort
6154
|> String.concat Environment.NewLine
6255

63-
let expected = normalize expected
64-
65-
match Assert.shouldBeSameMultilineStringSets expected actual with
66-
| None ->
67-
File.Delete(outFilePath)
68-
69-
| Some diff ->
70-
if shouldUpdateBaselines then
71-
File.Delete(outFilePath)
72-
File.WriteAllText(baselinePath, actual)
73-
else
74-
File.WriteAllText(outFilePath, actual)
75-
76-
let msg = $"""Assembly: %A{asm}
56+
let compare fileContent produced =
57+
match Assert.shouldBeSameMultilineStringSets (normalize fileContent) produced with
58+
| None -> None
59+
| Some diff ->
60+
Some $"""Assembly: %A{asm}
7761
7862
Expected and actual surface area don't match. To see the delta, run:
79-
windiff {baselinePath} {outFilePath}
63+
windiff {baselinePath} {Path.ChangeExtension(baselinePath, ".out")}
8064
8165
{diff}"""
8266

83-
failwith msg
67+
checkBaselineWith compare actual baselinePath

tests/service/data/SyntaxTree/.gitignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)