From 227631e6139037b408bd26dc8edf3b522fe67351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Sat, 3 Jun 2023 20:17:51 +0200 Subject: [PATCH 01/12] Adding start process and wait --- .../test-dotnet/Invoke-SolutionTests.ps1 | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index 12b53e06d..6837c9003 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -47,6 +47,73 @@ Set-GitHubOutput 'test-count' $tests.Length Write-Output "Starting to execute tests from $($tests.Length) projects." +function StartProcessAndWaitForExit($FileName, $Arguments, $TimeoutSec = 5) +{ + $process = [System.Diagnostics.Process]@{ + StartInfo = @{ + FileName = $FileName + Arguments = $Arguments + RedirectStandardOutput = $true + RedirectStandardError = $true + UseShellExecute = $false + WorkingDirectory = Get-Location + } + } + + $output = New-Object System.Text.StringBuilder + $eventArgs = @{ + Output = $output + Process = $process + } + + $stdoutEvent = Register-ObjectEvent $process -EventName OutputDataReceived -MessageData $eventArgs -Action { + $Event.MessageData.Output.AppendLine($Event.SourceEventArgs.Data) + Write-Host $Event.SourceEventArgs.Data + } + + $stderrEvent = Register-ObjectEvent $process -EventName ErrorDataReceived -MessageData $eventArgs -Action { + $Event.MessageData.Output.AppendLine($Event.SourceEventArgs.Data) + Write-Host $Event.SourceEventArgs.Data + } + + $process.Start() | Out-Null + $process.BeginOutputReadLine() + $process.BeginErrorReadLine() + Wait-Process -Id $process.Id -TimeoutSec $TimeoutSec + + if ($process.HasExited) + { + $exitCode = $process.ExitCode + } + else + { + Write-Output "The process $($process.Id) didn't exit in $TimeoutSec seconds." + + Write-Output "Collecting a dump of the process $($process.Id)." + dotnet-dump collect -p $process.Id --type Full -o "./dotnet-test-hang-dump-$($process.Id).dmp" + + Write-Output "Killing the process $($process.Id)." + Stop-Process -Force -Id $process.Id + if ($output.ToString() -Like '*Test Run Successful.*') + { + Write-Output "The process $($process.Id) was killed but the tests were successful." + $exitCode = 0 + } + else + { + $exitCode = -1 + } + } + + Unregister-Event $stdoutEvent.Id + Unregister-Event $stderrEvent.Id + + return @{ + Output = $output.ToString() + ExitCode = $exitCode + } +} + foreach ($test in $tests) { # This could benefit from grouping, above the level of the potential groups created by the tests (the Lombiq UI @@ -71,10 +138,9 @@ foreach ($test in $tests) Write-Output "Starting testing with ``dotnet test $($dotnetTestSwitches -join ' ')``." - dotnet test @dotnetTestSwitches 2>&1 | - Where-Object { $PSItem -notlike '*Connection refused [[]::ffff:127.0.0.1[]]*' -and $PSItem -notlike '*ChromeDriver was started successfully*' } + $processResult = StartProcessAndWaitForExit 'dotnet' "test $($dotnetTestSwitches -join ' ')" 300 - if ($?) + if ($processResult.ExitCode -eq 0) { Write-Output "Test successful: $test" continue From f2f98464a0cfffe7c43e4ed3641ea2fd251b701a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Sun, 4 Jun 2023 17:15:55 +0200 Subject: [PATCH 02/12] Getting back test output --- .github/actions/test-dotnet/Invoke-SolutionTests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index 6837c9003..feffaceac 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -51,8 +51,8 @@ function StartProcessAndWaitForExit($FileName, $Arguments, $TimeoutSec = 5) { $process = [System.Diagnostics.Process]@{ StartInfo = @{ - FileName = $FileName - Arguments = $Arguments + FileName = 'pwsh' + Arguments = "-c `"$FileName $Arguments 2>&1`"" RedirectStandardOutput = $true RedirectStandardError = $true UseShellExecute = $false From e2dd0f259c76d5e96f15e9bc4977be42eedc2854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Mon, 5 Jun 2023 10:32:41 +0200 Subject: [PATCH 03/12] Making dotnet test timeout configurable --- .github/actions/test-dotnet/Invoke-SolutionTests.ps1 | 11 +++++------ .github/actions/test-dotnet/action.yml | 12 ++++++++++++ .github/workflows/build-and-test-dotnet.yml | 6 ++++++ .github/workflows/build-and-test-orchard-core.yml | 8 +++++++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index feffaceac..15f82fbc1 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -1,4 +1,4 @@ -param ($Solution, $Verbosity, $Filter, $Configuration, $BlameHangTimeout) +param ($Solution, $Verbosity, $Filter, $Configuration, $BlameHangTimeout, $TestProcessTimeout) # Note that this script will only find tests if they were previously build in Release mode. @@ -47,7 +47,7 @@ Set-GitHubOutput 'test-count' $tests.Length Write-Output "Starting to execute tests from $($tests.Length) projects." -function StartProcessAndWaitForExit($FileName, $Arguments, $TimeoutSec = 5) +function StartProcessAndWaitForExit($FileName, $Arguments, $Timeout = -1) { $process = [System.Diagnostics.Process]@{ StartInfo = @{ @@ -79,15 +79,15 @@ function StartProcessAndWaitForExit($FileName, $Arguments, $TimeoutSec = 5) $process.Start() | Out-Null $process.BeginOutputReadLine() $process.BeginErrorReadLine() - Wait-Process -Id $process.Id -TimeoutSec $TimeoutSec + $process.WaitForExit($Timeout) if ($process.HasExited) { $exitCode = $process.ExitCode } else { - Write-Output "The process $($process.Id) didn't exit in $TimeoutSec seconds." + Write-Output "The process $($process.Id) didn't exit in $Timeout seconds." Write-Output "Collecting a dump of the process $($process.Id)." dotnet-dump collect -p $process.Id --type Full -o "./dotnet-test-hang-dump-$($process.Id).dmp" @@ -138,8 +138,7 @@ foreach ($test in $tests) Write-Output "Starting testing with ``dotnet test $($dotnetTestSwitches -join ' ')``." - $processResult = StartProcessAndWaitForExit 'dotnet' "test $($dotnetTestSwitches -join ' ')" 300 - + $processResult = StartProcessAndWaitForExit 'dotnet' "test $($dotnetTestSwitches -join ' ')" $TestProcessTimeout if ($processResult.ExitCode -eq 0) { Write-Output "Test successful: $test" diff --git a/.github/actions/test-dotnet/action.yml b/.github/actions/test-dotnet/action.yml index 48d108ee1..303b2345c 100644 --- a/.github/actions/test-dotnet/action.yml +++ b/.github/actions/test-dotnet/action.yml @@ -15,6 +15,11 @@ inputs: required: false default: . description: Path to the directory where a solution file can be found and thus the .NET build has run. + dotnet-test-process-timeout: + required: false + type: number + default: -1 + description: Run the dotnet test process with the given timeout in milliseconds. solution-path: required: false default: "*.sln" @@ -80,6 +85,12 @@ runs: "Lombiq_Tests_UI__OrchardCoreUITestExecutorConfiguration__MaxParallelTests=${{ inputs.ui-test-parallelism }}" >> $Env:GITHUB_ENV + - name: Install dotnet-dump + uses: Lombiq/GitHub-Actions/.github/actions/install-dotnet-tool@dev + with: + name: dotnet-dump + version: 7.0.421201 + - name: Run Tests id: run-tests shell: pwsh @@ -91,6 +102,7 @@ runs: Filter = "${{ inputs.test-filter }}" Configuration = "${{ inputs.test-configuration }}" BlameHangTimeout = "${{ inputs.blame-hang-timeout }}" + TestProcessTimeout = ${{ inputs.dotnet-test-process-timeout }} } Invoke-SolutionTests @switches diff --git a/.github/workflows/build-and-test-dotnet.yml b/.github/workflows/build-and-test-dotnet.yml index a0e00b7e6..8e91c2b73 100644 --- a/.github/workflows/build-and-test-dotnet.yml +++ b/.github/workflows/build-and-test-dotnet.yml @@ -100,6 +100,11 @@ on: description: > Duration in days after which the artifact of the build's binary log (if any) will expire. See https://github.com/actions/upload-artifact#retention-period for more details. + dotnet-test-process-timeout: + required: false + type: number + default: -1 + description: Run the dotnet test process with the given timeout in milliseconds. test-disable: required: false type: string @@ -189,6 +194,7 @@ jobs: with: blame-hang-timeout: ${{ inputs.blame-hang-timeout }} build-directory: ${{ inputs.build-directory }} + dotnet-test-process-timeout: ${{ inputs.dotnet-test-process-timeout }} solution-path: ${{ inputs.build-solution-path }} test-verbosity: ${{ inputs.build-verbosity }} test-filter: ${{ inputs.test-filter }} diff --git a/.github/workflows/build-and-test-orchard-core.yml b/.github/workflows/build-and-test-orchard-core.yml index 4183b33b6..93db48202 100644 --- a/.github/workflows/build-and-test-orchard-core.yml +++ b/.github/workflows/build-and-test-orchard-core.yml @@ -101,6 +101,11 @@ on: description: > Duration in days after which the artifact of the build's binary log (if any) will expire. See https://github.com/actions/upload-artifact#retention-period for more details. + dotnet-test-process-timeout: + required: false + type: number + default: -1 + description: Run the dotnet test process with the given timeout in milliseconds. print-config-summary: required: false type: string @@ -233,10 +238,11 @@ jobs: - name: Tests if: inputs.test-disable == 'false' - uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@dev + uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@issue/OSOE-464-executing-dotnet-test-with-process-timeout with: blame-hang-timeout: ${{ inputs.blame-hang-timeout }} build-directory: ${{ inputs.build-directory }} + dotnet-test-process-timeout: ${{ inputs.dotnet-test-process-timeout }} solution-path: ${{ inputs.build-solution-path }} test-verbosity: ${{ inputs.build-verbosity }} test-filter: ${{ inputs.test-filter }} From 0a2b3221901ab0f518ad6a79092ef1b49b875818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Mon, 5 Jun 2023 11:14:50 +0200 Subject: [PATCH 04/12] Uploading hang dumps --- .../actions/test-dotnet/Invoke-SolutionTests.ps1 | 14 +++++++++----- .github/actions/test-dotnet/action.yml | 9 +++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index 15f82fbc1..fcb21e771 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -44,6 +44,7 @@ $tests = dotnet sln $Solution list | } Set-GitHubOutput 'test-count' $tests.Length +Set-GitHubOutput 'dotnet-test-hang-dump' 0 Write-Output "Starting to execute tests from $($tests.Length) projects." @@ -87,16 +88,19 @@ function StartProcessAndWaitForExit($FileName, $Arguments, $Timeout = -1) } else { - Write-Output "The process $($process.Id) didn't exit in $Timeout seconds." + Write-Output "::warning::The process $($process.Id) didn't exit in $Timeout seconds." - Write-Output "Collecting a dump of the process $($process.Id)." - dotnet-dump collect -p $process.Id --type Full -o "./dotnet-test-hang-dump-$($process.Id).dmp" + Write-Output "::warning::Collecting a dump of the process $($process.Id)." + $dumpRootPath = './DotnetTestHangDumps' + New-Item -ItemType "directory" -Path $dumpRootPath -Force | Out-Null + dotnet-dump collect -p $process.Id --type Full -o "$dumpRootPath/dotnet-test-hang-dump-$($process.Id).dmp" + Set-GitHubOutput 'dotnet-test-hang-dump' 1 - Write-Output "Killing the process $($process.Id)." + Write-Output "::warning::Killing the process $($process.Id)." Stop-Process -Force -Id $process.Id if ($output.ToString() -Like '*Test Run Successful.*') { - Write-Output "The process $($process.Id) was killed but the tests were successful." + Write-Output "::warning::The process $($process.Id) was killed but the tests were successful." $exitCode = 0 } else diff --git a/.github/actions/test-dotnet/action.yml b/.github/actions/test-dotnet/action.yml index 303b2345c..9fd00d032 100644 --- a/.github/actions/test-dotnet/action.yml +++ b/.github/actions/test-dotnet/action.yml @@ -143,6 +143,15 @@ runs: if-no-files-found: ignore retention-days: ${{ inputs.ui-test-artifact-retention-days }} + - name: Upload DotnetTestHangDumps + uses: actions/upload-artifact@v3.1.1 + if: (success() || failure()) && steps.run-tests.outputs.test-count != 0 && steps.run-tests.outputs.dotnet-test-hang-dump != 0 + with: + name: dotnet-test-hang-dump-${{ steps.setup.outputs.artifact-name-suffix }} + path: ${{ inputs.build-directory }}/DotnetTestHangDumps/ + if-no-files-found: ignore + retention-days: ${{ inputs.ui-test-artifact-retention-days }} + - name: Test Report # v10 uses: phoenix-actions/test-reporting@93ce19fa5882ebe3969ebdb9ee1024b3d29e776f From fc0759007f9b5eeaea711f033292b3263b09b112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Mon, 5 Jun 2023 11:45:27 +0200 Subject: [PATCH 05/12] Addressing analizer violations --- .github/actions/test-dotnet/Invoke-SolutionTests.ps1 | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index fcb21e771..794aa47ad 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -62,18 +62,20 @@ function StartProcessAndWaitForExit($FileName, $Arguments, $Timeout = -1) } $output = New-Object System.Text.StringBuilder - $eventArgs = @{ + $eventHandlerArgs = @{ Output = $output Process = $process } - $stdoutEvent = Register-ObjectEvent $process -EventName OutputDataReceived -MessageData $eventArgs -Action { + $stdoutEvent = Register-ObjectEvent $process -EventName OutputDataReceived -MessageData $eventHandlerArgs -Action { $Event.MessageData.Output.AppendLine($Event.SourceEventArgs.Data) + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification='Only Write-Host is available here.')] Write-Host $Event.SourceEventArgs.Data } - $stderrEvent = Register-ObjectEvent $process -EventName ErrorDataReceived -MessageData $eventArgs -Action { + $stderrEvent = Register-ObjectEvent $process -EventName ErrorDataReceived -MessageData $eventHandlerArgs -Action { $Event.MessageData.Output.AppendLine($Event.SourceEventArgs.Data) + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification='Only Write-Host is available here.')] Write-Host $Event.SourceEventArgs.Data } @@ -92,7 +94,7 @@ function StartProcessAndWaitForExit($FileName, $Arguments, $Timeout = -1) Write-Output "::warning::Collecting a dump of the process $($process.Id)." $dumpRootPath = './DotnetTestHangDumps' - New-Item -ItemType "directory" -Path $dumpRootPath -Force | Out-Null + New-Item -ItemType 'directory' -Path $dumpRootPath -Force | Out-Null dotnet-dump collect -p $process.Id --type Full -o "$dumpRootPath/dotnet-test-hang-dump-$($process.Id).dmp" Set-GitHubOutput 'dotnet-test-hang-dump' 1 @@ -142,7 +144,7 @@ foreach ($test in $tests) Write-Output "Starting testing with ``dotnet test $($dotnetTestSwitches -join ' ')``." - $processResult = StartProcessAndWaitForExit 'dotnet' "test $($dotnetTestSwitches -join ' ')" $TestProcessTimeout + $processResult = StartProcessAndWaitForExit -FileName 'dotnet' -Arguments "test $($dotnetTestSwitches -join ' ')" -Timeout $TestProcessTimeout if ($processResult.ExitCode -eq 0) { Write-Output "Test successful: $test" From 888f9efea93a202034e295cf670c28630ae6c8ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Sun, 7 Jan 2024 20:19:21 +0100 Subject: [PATCH 06/12] Better dump and kill of test process tree --- .../test-dotnet/Invoke-SolutionTests.ps1 | 101 ++++++++++++------ 1 file changed, 71 insertions(+), 30 deletions(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index 26cbde246..13b14a5dd 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -10,22 +10,25 @@ param ($Solution, $Verbosity, $Filter, $Configuration, $BlameHangTimeout, $TestP # the Actions web UI. Note that we use bash to output the log using bash to avoid pwsh wrapping the output to the # default buffer width. -$connectionStringSuffix = @( - ';MultipleActiveResultSets=True;Connection Timeout=60;ConnectRetryCount=15;ConnectRetryInterval=5;Encrypt=false;' - 'TrustServerCertificate=true' -) -join '' if ($Env:RUNNER_OS -eq 'Windows') { - $connectionStringStem = 'Server=.;Database=LombiqUITestingToolbox_{{id}};Integrated Security=True' + $connectionSecurity = 'Integrated Security=True' } else { - $connectionStringStem = 'Server=.;Database=LombiqUITestingToolbox_{{id}};User Id=sa;Password=Password1!' + $connectionSecurity = 'User Id=sa;Password=Password1!' $Env:Lombiq_Tests_UI__DockerConfiguration__ContainerName = 'uitt-sqlserver' } -$Env:Lombiq_Tests_UI__SqlServerDatabaseConfiguration__ConnectionStringTemplate = $connectionStringStem + $connectionStringSuffix +$connectionString = @( + 'Server=.;Database=LombiqUITestingToolbox_{{id}};Integrated Security=True' + $connectionSecurity + 'MultipleActiveResultSets=True;Connection Timeout=60;ConnectRetryCount=15;ConnectRetryInterval=5;Encrypt=false' + 'TrustServerCertificate=true' +) -join ';' + +$Env:Lombiq_Tests_UI__SqlServerDatabaseConfiguration__ConnectionStringTemplate = $connectionString $Env:Lombiq_Tests_UI__BrowserConfiguration__Headless = 'true' $solutionName = [System.IO.Path]::GetFileNameWithoutExtension($Solution) @@ -67,6 +70,45 @@ Set-GitHubOutput 'dotnet-test-hang-dump' 0 Write-Output "Starting to execute tests from $($tests.Length) project(s)." +function GetChildProcesses($Id) +{ + return Get-Process | Where-Object { $_.Parent.Id -eq $Id } +} + +function DumpProcess($Output, $RootProcess, $DumpRootPath, $Process) +{ + if ($Process -eq $null) + { + return + } + + $output.AppendLine("::warning::Collecting a dump of the process $($Process.Id).") + + dotnet-dump collect -p $Process.Id --type Full -o "$DumpRootPath/dotnet-test-hang-dump-$($RootProcess.Id)-$($Process.Name)_$($Process.Id).dmp" +} + +function DumpProcessTree($Output, $RootProcess, $DumpRootPath, $CurrentProcess) +{ + foreach ($child in GetChildProcesses -Id $CurrentProcess.Id) + { + DumpProcessTree -Output $Output -RootProcess $RootProcess -DumpRootPath $DumpRootPath -CurrentProcess $child + } + + DumpProcess -Output $Output -RootProcess $RootProcess -DumpRootPath $DumpRootPath -Process $CurrentProcess +} + +function KillProcessTree($Output, $Process) +{ + $Output.AppendLine("::warning::Killing the process $($Process.Name)($($Process.Id)).") + + foreach ($child in GetChildProcesses -Id $Process.Id) + { + KillProcessTree -Output $Output -Process $child + } + + Stop-Process -Force -InputObject $Process +} + function StartProcessAndWaitForExit($FileName, $Arguments, $Timeout = -1) { $process = [System.Diagnostics.Process]@{ @@ -88,14 +130,10 @@ function StartProcessAndWaitForExit($FileName, $Arguments, $Timeout = -1) $stdoutEvent = Register-ObjectEvent $process -EventName OutputDataReceived -MessageData $eventHandlerArgs -Action { $Event.MessageData.Output.AppendLine($Event.SourceEventArgs.Data) - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification='Only Write-Host is available here.')] - Write-Host $Event.SourceEventArgs.Data } $stderrEvent = Register-ObjectEvent $process -EventName ErrorDataReceived -MessageData $eventHandlerArgs -Action { $Event.MessageData.Output.AppendLine($Event.SourceEventArgs.Data) - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification='Only Write-Host is available here.')] - Write-Host $Event.SourceEventArgs.Data } $process.Start() | Out-Null @@ -103,31 +141,25 @@ function StartProcessAndWaitForExit($FileName, $Arguments, $Timeout = -1) $process.BeginErrorReadLine() $process.WaitForExit($Timeout) - if ($process.HasExited) + $hasExited = $process.HasExited + if ($hasExited) { $exitCode = $process.ExitCode } else { - Write-Output "::warning::The process $($process.Id) didn't exit in $Timeout seconds." + $output.AppendLine("::warning::The process $($process.Id) didn't exit in $Timeout seconds.") - Write-Output "::warning::Collecting a dump of the process $($process.Id)." + $output.AppendLine("::warning::Collecting a dump of the process $($process.Id) tree.") $dumpRootPath = './DotnetTestHangDumps' New-Item -ItemType 'directory' -Path $dumpRootPath -Force | Out-Null - dotnet-dump collect -p $process.Id --type Full -o "$dumpRootPath/dotnet-test-hang-dump-$($process.Id).dmp" + + $rootProcess = Get-Process -Id $process.Id + DumpProcessTree -RootProcess $rootProcess -DumpRootPath $dumpRootPath -CurrentProcess $rootProcess + Set-GitHubOutput 'dotnet-test-hang-dump' 1 - Write-Output "::warning::Killing the process $($process.Id)." - Stop-Process -Force -Id $process.Id - if ($output.ToString() -Like '*Test Run Successful.*') - { - Write-Output "::warning::The process $($process.Id) was killed but the tests were successful." - $exitCode = 0 - } - else - { - $exitCode = -1 - } + KillProcessTree -Output $output -Process $rootProcess } Unregister-Event $stdoutEvent.Id @@ -136,6 +168,7 @@ function StartProcessAndWaitForExit($FileName, $Arguments, $Timeout = -1) return @{ Output = $output.ToString() ExitCode = $exitCode + HasExited = $hasExited } } @@ -151,9 +184,9 @@ foreach ($test in $tests) $dotnetTestSwitches = @( '--configuration', $Configuration '--nologo', - '--logger', 'trx;LogFileName=test-results.trx' + '--logger', '''trx;LogFileName=test-results.trx''' # This is for xUnit ITestOutputHelper, see https://xunit.net/docs/capturing-output. - '--logger', 'console;verbosity=detailed' + '--logger', '''console;verbosity=detailed''' '--verbosity', $Verbosity $BlameHangTimeout ? ('--blame-hang-timeout', $BlameHangTimeout, '--blame-hang-dump-type', 'full') : '' $Filter ? '--filter', $Filter : '' @@ -162,11 +195,19 @@ foreach ($test in $tests) Write-Output "Starting testing with ``dotnet test $($dotnetTestSwitches -join ' ')``." - $processResult = StartProcessAndWaitForExit -FileName 'dotnet' -Arguments "test $($dotnetTestSwitches -join ' ')" -Timeout $TestProcessTimeout - if ($processResult.ExitCode -eq 0) + + Write-Output $processResult.Output + + if ($processResult.ExitCode -eq 0 || (!$processResult.HasExited && $processResult.Output -Like '*Test Run Successful.*')) { + if (!$processResult.HasExited) + { + Write-Output "::warning::The process $($process.Id) was killed but the tests were successful." + } + Write-Output "Test successful: $test" + continue } From 0d6418cb81ab57a31d6498533c75ba535526de94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Sun, 7 Jan 2024 20:44:40 +0100 Subject: [PATCH 07/12] Fixing branch references --- .github/workflows/build-and-test-dotnet.yml | 2 +- .github/workflows/msbuild-and-test.yml | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test-dotnet.yml b/.github/workflows/build-and-test-dotnet.yml index 0df08ecd7..7890092be 100644 --- a/.github/workflows/build-and-test-dotnet.yml +++ b/.github/workflows/build-and-test-dotnet.yml @@ -210,7 +210,7 @@ jobs: - name: Tests if: inputs.test-disable == 'false' - uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@dev + uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@issue/OSOE-464-executing-dotnet-test-with-process-timeout with: blame-hang-timeout: ${{ inputs.blame-hang-timeout }} build-directory: ${{ inputs.build-directory }} diff --git a/.github/workflows/msbuild-and-test.yml b/.github/workflows/msbuild-and-test.yml index 762b5c188..33d392281 100644 --- a/.github/workflows/msbuild-and-test.yml +++ b/.github/workflows/msbuild-and-test.yml @@ -77,6 +77,11 @@ on: type: string default: 'true' description: Indicates whether to enable static code analysis during msbuild. + dotnet-test-process-timeout: + required: false + type: number + default: -1 + description: Run the dotnet test process with the given timeout in milliseconds. test-disable: type: string default: 'false' @@ -120,9 +125,10 @@ jobs: - name: Tests if: inputs.test-disable == 'false' - uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@dev + uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@issue/OSOE-464-executing-dotnet-test-with-process-timeout with: build-directory: ${{ inputs.build-directory }} + dotnet-test-process-timeout: ${{ inputs.dotnet-test-process-timeout }} test-verbosity: ${{ inputs.build-verbosity }} test-filter: ${{ inputs.test-filter }} test-configuration: 'Release' From cd076646a822c50e07d326106ee77a35f51c1199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Sun, 7 Jan 2024 21:16:48 +0100 Subject: [PATCH 08/12] Fixing PS analyzer violations --- .github/actions/test-dotnet/Invoke-SolutionTests.ps1 | 4 ++-- .github/actions/test-dotnet/action.yml | 2 +- .github/workflows/build-and-test-dotnet.yml | 2 +- .github/workflows/build-and-test-orchard-core.yml | 2 +- .github/workflows/msbuild-and-test.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index 13b14a5dd..c20dd54f2 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -72,12 +72,12 @@ Write-Output "Starting to execute tests from $($tests.Length) project(s)." function GetChildProcesses($Id) { - return Get-Process | Where-Object { $_.Parent.Id -eq $Id } + return Get-Process | Where-Object { $PSItem.Parent.Id -eq $Id } } function DumpProcess($Output, $RootProcess, $DumpRootPath, $Process) { - if ($Process -eq $null) + if (!$Process) { return } diff --git a/.github/actions/test-dotnet/action.yml b/.github/actions/test-dotnet/action.yml index 9fd00d032..f99e58311 100644 --- a/.github/actions/test-dotnet/action.yml +++ b/.github/actions/test-dotnet/action.yml @@ -19,7 +19,7 @@ inputs: required: false type: number default: -1 - description: Run the dotnet test process with the given timeout in milliseconds. + description: Run the dotnet test process with the given timeout in milliseconds. -1 means no timeout. solution-path: required: false default: "*.sln" diff --git a/.github/workflows/build-and-test-dotnet.yml b/.github/workflows/build-and-test-dotnet.yml index 7890092be..84630bdaf 100644 --- a/.github/workflows/build-and-test-dotnet.yml +++ b/.github/workflows/build-and-test-dotnet.yml @@ -105,7 +105,7 @@ on: required: false type: number default: -1 - description: Run the dotnet test process with the given timeout in milliseconds. + description: Run the dotnet test process with the given timeout in milliseconds. -1 means no timeout. test-disable: type: string default: 'false' diff --git a/.github/workflows/build-and-test-orchard-core.yml b/.github/workflows/build-and-test-orchard-core.yml index a6ee3685e..36cce8212 100644 --- a/.github/workflows/build-and-test-orchard-core.yml +++ b/.github/workflows/build-and-test-orchard-core.yml @@ -103,7 +103,7 @@ on: required: false type: number default: -1 - description: Run the dotnet test process with the given timeout in milliseconds. + description: Run the dotnet test process with the given timeout in milliseconds. -1 means no timeout. print-config-summary: type: string default: 'false' diff --git a/.github/workflows/msbuild-and-test.yml b/.github/workflows/msbuild-and-test.yml index 33d392281..92e9b2277 100644 --- a/.github/workflows/msbuild-and-test.yml +++ b/.github/workflows/msbuild-and-test.yml @@ -81,7 +81,7 @@ on: required: false type: number default: -1 - description: Run the dotnet test process with the given timeout in milliseconds. + description: Run the dotnet test process with the given timeout in milliseconds. -1 means no timeout. test-disable: type: string default: 'false' From ef6781d01381568096ff4563c40210f13b890070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Sun, 7 Jan 2024 21:31:48 +0100 Subject: [PATCH 09/12] Fixing Sql connection string --- .github/actions/test-dotnet/Invoke-SolutionTests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index c20dd54f2..f599c77fc 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -22,7 +22,7 @@ else } $connectionString = @( - 'Server=.;Database=LombiqUITestingToolbox_{{id}};Integrated Security=True' + 'Server=.;Database=LombiqUITestingToolbox_{{id}}' $connectionSecurity 'MultipleActiveResultSets=True;Connection Timeout=60;ConnectRetryCount=15;ConnectRetryInterval=5;Encrypt=false' 'TrustServerCertificate=true' From 8e9812b2598e0eea2395e56ce43cd0d746f6f766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Mon, 8 Jan 2024 19:14:31 +0100 Subject: [PATCH 10/12] Better filter condition --- .github/actions/test-dotnet/Invoke-SolutionTests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index f599c77fc..81a08a1bc 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -72,7 +72,7 @@ Write-Output "Starting to execute tests from $($tests.Length) project(s)." function GetChildProcesses($Id) { - return Get-Process | Where-Object { $PSItem.Parent.Id -eq $Id } + return Get-Process | Where-Object { $PSItem.Parent -and $PSItem.Parent.Id -eq $Id } } function DumpProcess($Output, $RootProcess, $DumpRootPath, $Process) From d1af38efab26d4e62f9da2bebc3acbf0636f7124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Horv=C3=A1th?= Date: Thu, 11 Jan 2024 19:24:27 +0100 Subject: [PATCH 11/12] Update .github/actions/test-dotnet/Invoke-SolutionTests.ps1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sára El-Saig --- .github/actions/test-dotnet/Invoke-SolutionTests.ps1 | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 index 81a08a1bc..74d02a19b 100644 --- a/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 +++ b/.github/actions/test-dotnet/Invoke-SolutionTests.ps1 @@ -22,9 +22,14 @@ else } $connectionString = @( - 'Server=.;Database=LombiqUITestingToolbox_{{id}}' + 'Server=.' + 'Database=LombiqUITestingToolbox_{{id}}' $connectionSecurity - 'MultipleActiveResultSets=True;Connection Timeout=60;ConnectRetryCount=15;ConnectRetryInterval=5;Encrypt=false' + 'MultipleActiveResultSets=True' + 'Connection Timeout=60' + 'ConnectRetryCount=15' + 'ConnectRetryInterval=5' + 'Encrypt=false' 'TrustServerCertificate=true' ) -join ';' From 31b8dd88a690a41919a095b175b06b3987bc5646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A1ra=20El-Saig?= Date: Sat, 13 Jan 2024 15:24:58 +0100 Subject: [PATCH 12/12] Revert branch version selectors. --- .github/workflows/build-and-test-dotnet.yml | 2 +- .github/workflows/build-and-test-orchard-core.yml | 2 +- .github/workflows/msbuild-and-test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-and-test-dotnet.yml b/.github/workflows/build-and-test-dotnet.yml index 84630bdaf..3ae2da584 100644 --- a/.github/workflows/build-and-test-dotnet.yml +++ b/.github/workflows/build-and-test-dotnet.yml @@ -210,7 +210,7 @@ jobs: - name: Tests if: inputs.test-disable == 'false' - uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@issue/OSOE-464-executing-dotnet-test-with-process-timeout + uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@dev with: blame-hang-timeout: ${{ inputs.blame-hang-timeout }} build-directory: ${{ inputs.build-directory }} diff --git a/.github/workflows/build-and-test-orchard-core.yml b/.github/workflows/build-and-test-orchard-core.yml index 36cce8212..27f1ab3ed 100644 --- a/.github/workflows/build-and-test-orchard-core.yml +++ b/.github/workflows/build-and-test-orchard-core.yml @@ -250,7 +250,7 @@ jobs: - name: Tests if: inputs.test-disable == 'false' - uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@issue/OSOE-464-executing-dotnet-test-with-process-timeout + uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@dev with: blame-hang-timeout: ${{ inputs.blame-hang-timeout }} build-directory: ${{ inputs.build-directory }} diff --git a/.github/workflows/msbuild-and-test.yml b/.github/workflows/msbuild-and-test.yml index 92e9b2277..02ee9116e 100644 --- a/.github/workflows/msbuild-and-test.yml +++ b/.github/workflows/msbuild-and-test.yml @@ -125,7 +125,7 @@ jobs: - name: Tests if: inputs.test-disable == 'false' - uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@issue/OSOE-464-executing-dotnet-test-with-process-timeout + uses: Lombiq/GitHub-Actions/.github/actions/test-dotnet@dev with: build-directory: ${{ inputs.build-directory }} dotnet-test-process-timeout: ${{ inputs.dotnet-test-process-timeout }}