# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

# Runs Publish Test Results task for a specific framework

parameters:
  testProjectName: '' # The name of the test project
  framework: '' # The target framework for display purposes.
  vsTestPlatform: 'x64' # Target platform architecture used for test execution. Valid values are x86, x64, and ARM.
  osName: '' # The name of the operating system for display purposes.
  testResultsFormat: VSTest # Specify the format of the results files you want to publish. The following formats are supported: JUnit, NUnit, VSTest, XUnit, CTest
  testResultsArtifactName: 'testresults' # The name of the Azure DevOps build artifact where the test results will be published. Default 'testresults'.
  testResultsFileName: 'TestResults.trx' # The name of the file (not path) of the test results. Default 'TestResults.trx'.

steps:
#- pwsh: |
#    function EnsureNotNullOrEmpty([string]$param, [string]$nameOfParam) {
#        if ([string]::IsNullOrEmpty($param)) {
#            Write-Host "##vso[task.logissue type=error;]Missing template parameter \"$nameOfParam\""
#            Write-Host "##vso[task.complete result=Failed;]"
#        }
#    }
#    EnsureNotNullOrEmpty('${{ parameters.testProjectName }}', 'testProjectName')
#    EnsureNotNullOrEmpty('${{ parameters.framework }}', 'framework')
#    EnsureNotNullOrEmpty('${{ parameters.vsTestPlatform }}', 'vsTestPlatform')
#    EnsureNotNullOrEmpty('${{ parameters.osName }}', 'osName')
#    EnsureNotNullOrEmpty('${{ parameters.testResultsFormat }}', 'testResultsFormat')
#    EnsureNotNullOrEmpty('${{ parameters.testResultsArtifactName }}', 'testResultsArtifactName')
#    EnsureNotNullOrEmpty('${{ parameters.testResultsFileName }}', 'testResultsFileName')
#  displayName: 'Validate Template Parameters'

#- template: 'show-all-files.yml' # Uncomment for debugging

- pwsh: |
    $testProjectName = "${{ parameters.testProjectName }}"
    $testResultsFileName = "$(Build.ArtifactStagingDirectory)/${{ parameters.testResultsArtifactName }}/${{ parameters.osName }}/${{ parameters.framework }}/${{ parameters.vsTestPlatform }}/$testProjectName/${{ parameters.testResultsFileName }}"
    $testResultsFileExists = Test-Path $testResultsFileName
    if ($testResultsFileExists) {
    
        $reader = [System.Xml.XmlReader]::Create($testResultsFileName)
        try {
            $countersFound = $false
            $crashed = $false
            $inRunInfos = $false
            while ($reader.Read()) {
                if ($reader.NodeType -eq [System.Xml.XmlNodeType]::Element) {
                    if (!$countersFound -and $reader.Name -eq 'Counters') {
                        $failed = $reader.GetAttribute('failed')
                        $passed = $reader.GetAttribute('passed')
                        $ignored = (([int]$reader.GetAttribute('total')) - ([int]$reader.GetAttribute('executed'))).ToString()
                        $testResults = "Tests failed: $failed, passed: $passed, ignored: $ignored"
                        Write-Host "##vso[task.setvariable variable=TestResults;]$testResults"
                        # Report a running total of failures
                        $totalFailures = ([int]$env:TOTALFAILURES + [int]$failed).ToString()
                        Write-Host "##vso[task.setvariable variable=TotalFailures;]$totalFailures"
                        $countersFound = $true
                    }
                    # Report a crash of the test runner
                    if ($reader.Name -eq 'RunInfos') {
                        $inRunInfos = $true
                    }
                    if ($inRunInfos -and !$crashed -and $reader.Name -eq 'Text' -and $reader.ReadInnerXml().Contains('Test host process crashed')) {
                        Write-Host "##vso[task.setvariable variable=HostCrashed;]true"
                        # Report all of the test projects that crashed
                        $crashedRuns = "$env:CRASHEDRUNS,$testProjectName".TrimStart(',')
                        Write-Host "##vso[task.setvariable variable=CrashedRuns;]$crashedRuns"
                        $crashed = $true
                    }
                }
                if ($reader.NodeType -eq [System.Xml.XmlNodeType]::EndElement -and $reader.Name -eq 'RunInfos') {
                    $inRunInfos = $false
                }
            }
        } finally {
            $reader.Dispose()
        }
    } else {
        Write-Host "WARNING: File not found: $testResultsFileName"
    }
    Write-Host "##vso[task.setvariable variable=TestResultsFileExists;]$testResultsFileExists"
  displayName: 'Parse Test Results File'

- task: PublishTestResults@2
  displayName: 'Publish Test Results ${{ parameters.testProjectName }},${{ parameters.framework }},${{ parameters.vsTestPlatform }}'
  inputs:
    testResultsFormat: ${{ parameters.testResultsFormat }}
    testResultsFiles: '$(Build.ArtifactStagingDirectory)/${{ parameters.testResultsArtifactName }}/${{ parameters.osName }}/${{ parameters.framework }}/${{ parameters.vsTestPlatform }}/${{ parameters.testProjectName }}/${{ parameters.testResultsFileName }}'
    testRunTitle: '${{ parameters.testProjectName }} - ${{ parameters.framework }} - ${{ parameters.vsTestPlatform }} - ${{ parameters.osName }} | $(TestResults)'
  condition: and(succeeded(), eq(variables['TestResultsFileExists'], 'true'))