@@ -362,36 +362,81 @@ function VerifyAssemblyVersionsAndSymbols() {
362362 }
363363}
364364
365- function TestUsingMSBuild ([string ] $testProject , [string ] $targetFramework , [string ]$testadapterpath , [boolean ] $asBackgroundJob = $false ) {
365+ function TestUsingMSBuild ([string ] $testProject , [string ] $targetFramework , [string ]$testadapterpath , [string ] $backgroundJob = " " , [string ] $settings = " " ) {
366+ $jobId = if ($backgroundJob ) { " _$backgroundJob " } else {" " }
366367 $dotnetPath = InitializeDotNetCli
367368 $dotnetExe = Join-Path $dotnetPath " dotnet.exe"
368369 $projectName = [System.IO.Path ]::GetFileNameWithoutExtension($testProject )
369- $testLogPath = " $ArtifactsDir \TestResults\$configuration \${projectName} _$targetFramework .xml"
370- $testBinLogPath = " $LogDir \${projectName} _$targetFramework .binlog"
371- $args = " test $testProject -c $configuration -f $targetFramework -v n --test-adapter-path $testadapterpath --logger "" xunit;LogFilePath=$testLogPath "" /bl:$testBinLogPath "
372- $args += " --blame --results-directory $ArtifactsDir \TestResults\$configuration -p:vstestusemsbuildoutput=false "
370+ $testLogPath = " $ArtifactsDir \TestResults\$configuration \${projectName} _$targetFramework$jobId .xml"
371+ $testBinLogPath = " $LogDir \${projectName} _$targetFramework$jobId .binlog"
372+ $arguments = " test $testProject -c $configuration -f $targetFramework -v n --test-adapter-path $testadapterpath --logger "" xunit;LogFilePath=$testLogPath "" /bl:$testBinLogPath "
373+ $arguments += " --blame --blame-hang-timeout 5minutes -- results-directory $ArtifactsDir \TestResults\$configuration -p:vstestusemsbuildoutput=true "
373374
374375 if (-not $noVisualStudio -or $norestore ) {
375- $args += " --no-restore"
376+ $arguments += " --no-restore"
376377 }
377378
378379 if (-not $noVisualStudio ) {
379- $args += " --no-build"
380+ $arguments += " --no-build"
380381 }
381382
382- if ($asBackgroundJob ) {
383- Write-Host (" Starting on the background: $args " )
383+ $arguments += " $settings "
384+
385+ if ($backgroundJob ) {
386+ Write-Host
387+ Write-Host (" Starting on the background: $arguments " )
384388 Write-Host (" ------------------------------------" )
385- $bgJob = Start-Job - ScriptBlock {
386- & $using :dotnetExe test $using :testProject - c $using :configuration -f $using :targetFramework - v n -- test-adapter - path $using :testadapterpath -- logger " xunit;LogFilePath=$using :testLogPath " / bl:$using :testBinLogPath -- blame -- results- directory $using :ArtifactsDir \TestResults\$using :configuration
389+ Start-Job - ScriptBlock {
390+ $argArray = $using :arguments -Split " "
391+ & $using :dotnetExe $argArray
387392 if ($LASTEXITCODE -ne 0 ) {
388393 throw " Command failed to execute with exit code $ ( $LASTEXITCODE ) : $using :dotnetExe $using :args "
389394 }
390395 }
391- return $bgJob
392- } else {
393- Write-Host (" $args " )
394- Exec- Console $dotnetExe $args
396+ } else {
397+ Write-Host (" $arguments " )
398+ Exec- Console $dotnetExe $arguments
399+ }
400+ }
401+
402+ function TestSolutionUsingMSBuild ([string ] $testSolution , [string ] $targetFramework , [string ] $testadapterpath , [string ] $backgroundJob = " " , [string ] $settings = " " ) {
403+ $jobId = if ($backgroundJob ) { " _$backgroundJob " } else {" " }
404+ $dotnetPath = InitializeDotNetCli
405+ $dotnetExe = Join-Path $dotnetPath " dotnet.exe"
406+ $solutionName = [System.IO.Path ]::GetFileNameWithoutExtension($testSolution )
407+ $testLogPath = " $ArtifactsDir \TestResults\$configuration \{assembly}.{framework}$jobId .xml"
408+ $testBinLogPath = " $LogDir \${solutionName} _$targetFramework$jobId .binlog"
409+
410+ $arguments = " test"
411+
412+ $arguments += " $testSolution -c $configuration -f $targetFramework --test-adapter-path $testadapterpath -v n --logger "" xunit;LogFilePath=$testLogPath "" /bl:$testBinLogPath "
413+ $arguments += " --blame-hang-timeout 5minutes --results-directory $ArtifactsDir \TestResults\$configuration /p:VsTestUseMSBuildOutput=true"
414+
415+ if (-not $noVisualStudio -or $norestore ) {
416+ $arguments += " --no-restore"
417+ }
418+
419+ if (-not $noVisualStudio ) {
420+ $arguments += " --no-build"
421+ }
422+
423+ $arguments += " $settings "
424+
425+ if ($backgroundJob ) {
426+ Write-Host
427+ Write-Host (" Starting on the background: $arguments " )
428+ Write-Host (" ------------------------------------" )
429+ Start-Job - ScriptBlock {
430+ $argArray = $using :arguments -Split " "
431+ $argArray += " --no-build"
432+ & $using :dotnetExe $argArray
433+ if ($LASTEXITCODE -ne 0 ) {
434+ throw " Command failed to execute with exit code $ ( $LASTEXITCODE ) : $using :dotnetExe $using :args "
435+ }
436+ }
437+ } else {
438+ Write-Host (" $arguments " )
439+ Exec- Console $dotnetExe $arguments
395440 }
396441}
397442
@@ -588,32 +633,48 @@ try {
588633 $script :BuildCategory = " Test"
589634 $script :BuildMessage = " Failure running tests"
590635
636+ function Receive ($job ) {
637+ while ($job.HasMoreData ) {
638+ Receive-Job $job | Write-Host
639+ Start-Sleep - Seconds 1
640+ }
641+ Receive-Job $job - Wait - ErrorAction Stop
642+ }
643+
591644 if ($testCoreClr ) {
592- $bgJob = TestUsingMSBuild - testProject " $RepoRoot \tests\fsharp\FSharpSuite.Tests.fsproj" - targetFramework $script :coreclrTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharpSuite.Tests\" - asBackgroundJob $true
645+ $cpuLimit = if ($ci ) { " -m:2 -- xUnit.MaxParallelThreads=0.25x" } else { " " }
646+ TestSolutionUsingMSBuild - testSolution " $RepoRoot \FSharp.sln" - targetFramework $script :coreclrTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.ComponentTests\" - settings $cpuLimit
647+ }
593648
594- TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.ComponentTests\FSharp.Compiler.ComponentTests.fsproj" - targetFramework $script :coreclrTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.ComponentTests\"
595- TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.Service.Tests\FSharp.Compiler.Service.Tests.fsproj" - targetFramework $script :coreclrTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.Service.Tests\"
596- TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj" - targetFramework $script :coreclrTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.Private.Scripting.UnitTests\"
597- TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" - targetFramework $script :coreclrTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Build.UnitTests\"
598- TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" - targetFramework $script :coreclrTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Core.UnitTests\"
649+ if ($testDesktop -and -not $ci ) {
650+
651+ # Split ComponentTests into processes using filter, because it is slow and underutilizes CPU locally.
652+ $bgJob1 = TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.ComponentTests\FSharp.Compiler.ComponentTests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.ComponentTests\" - backgroundJob 1 - settings " --filter ExecutionNode=1"
653+ $bgJob2 = TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.ComponentTests\FSharp.Compiler.ComponentTests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.ComponentTests\" - backgroundJob 2 - settings " --filter ExecutionNode=2"
654+ $bgJob3 = TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.ComponentTests\FSharp.Compiler.ComponentTests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.ComponentTests\" - backgroundJob 3 - settings " --filter ExecutionNode=3"
655+ $bgJob4 = TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.ComponentTests\FSharp.Compiler.ComponentTests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.ComponentTests\" - backgroundJob 4 - settings " --filter ExecutionNode=4"
656+
657+ TestSolutionUsingMSBuild - testSolution " $RepoRoot \FSharp.sln" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.ComponentTests\" - settings " --filter "" Project!=FSharpSuite.Tests&Project!=FSharp.Compiler.ComponentTests"" "
658+ # FSharpSuite does most of it's work in external processes, saturating the CPU. It makes sense to run it separately.
659+ TestUsingMSBuild - testProject " $RepoRoot \tests\fsharp\FSharpSuite.Tests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharpSuite.Tests\"
599660
600- # Collect output from background jobs
601- Wait-job $bgJob | out-null
602- Receive-Job $bgJob - ErrorAction Stop
661+ # Collect output from background jobs
662+ Receive - job $bgJob1
663+ Receive - job $bgJob2
664+ Receive - job $bgJob3
665+ Receive - job $bgJob4
603666 }
604667
605- if ($testDesktop ) {
606- $bgJob = TestUsingMSBuild - testProject " $RepoRoot \tests\fsharp\FSharpSuite.Tests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharpSuite.Tests\" - asBackgroundJob $true
668+ if ($testDesktop -and $ci ) {
669+ $bgJob = TestUsingMSBuild - testProject " $RepoRoot \tests\fsharp\FSharpSuite.Tests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharpSuite.Tests\" - backgroundJob 1
607670
608671 TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.ComponentTests\FSharp.Compiler.ComponentTests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.ComponentTests\"
609672 TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.Service.Tests\FSharp.Compiler.Service.Tests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.Service.Tests\"
610673 TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Compiler.Private.Scripting.UnitTests\"
611674 TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Build.UnitTests\"
612675 TestUsingMSBuild - testProject " $RepoRoot \tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" - targetFramework $script :desktopTargetFramework - testadapterpath " $ArtifactsDir \bin\FSharp.Core.UnitTests\"
613676
614- # Collect output from background jobs
615- Wait-job $bgJob | out-null
616- Receive-Job $bgJob - ErrorAction Stop
677+ Receive - job $bgJob
617678 }
618679
619680 if ($testFSharpQA ) {
0 commit comments