|
16 | 16 | 1. Finds this leg's test run for the build (matched by the unique |
17 | 17 | TestRunNamePrefix set in cdac-stress-helix.proj). |
18 | 18 | 2. Extracts the per-debuggee logs from the downloaded tarball. |
19 | | - 3. Attaches each log to the run's GCStress test result(s) via the Azure |
20 | | - DevOps Test Attachments REST API (falling back to a run-level attachment |
21 | | - if no matching result is found). |
| 19 | + 3. Attaches each log to its own per-debuggee test result. The legacy |
| 20 | + reporter models a [Theory] as one result with a sub-result per data row, |
| 21 | + so each debuggee's log is attached to its sub-result (via |
| 22 | + testSubResultId); single-row theories are attached to the result itself. |
| 23 | + Anything that can't be mapped is attached at the run level so no log is |
| 24 | + lost. |
22 | 25 |
|
23 | 26 | Failures here are non-fatal: the build artifact remains the source of truth, |
24 | 27 | so the script logs warnings and always exits 0. |
@@ -104,42 +107,89 @@ try { |
104 | 107 | return $name |
105 | 108 | } |
106 | 109 |
|
| 110 | + # Pull the debuggee name out of an xUnit display name like |
| 111 | + # '...GCStress_AllVerificationsPass(debuggeeName: "BasicAlloc")'. |
| 112 | + function Get-Debuggee([string]$name) { |
| 113 | + if ([string]::IsNullOrEmpty($name)) { return $null } |
| 114 | + $m = [regex]::Match($name, 'debuggeeName:\s*\\?"(?<d>[^"\\]+)') |
| 115 | + if ($m.Success) { return $m.Groups['d'].Value } |
| 116 | + return $null |
| 117 | + } |
| 118 | + |
| 119 | + # Map each downloaded log to its debuggee (case-insensitive) so we can attach |
| 120 | + # it to the matching per-debuggee test result / sub-result. |
| 121 | + $logByDebuggee = @{} |
| 122 | + foreach ($log in $logFiles) { |
| 123 | + $m = [regex]::Match($log.Name, '^cdac-gcstress-(?<d>.+?)-[0-9a-fA-F]{32}\.txt$') |
| 124 | + if ($m.Success) { $logByDebuggee[$m.Groups['d'].Value.ToLowerInvariant()] = $log } |
| 125 | + } |
| 126 | + |
107 | 127 | foreach ($run in $matchingRuns) { |
108 | 128 | $runId = $run.id |
109 | 129 | $resultsUri = "$baseUrl/_apis/test/runs/$runId/results?api-version=7.1" |
110 | 130 | $results = Invoke-RestMethod -Headers $headers -Uri $resultsUri -Method Get |
111 | 131 | $gcStressResults = @($results.value | Where-Object { $_.automatedTestName -match 'GCStress' }) |
112 | 132 |
|
113 | 133 | $attached = 0 |
114 | | - if ($gcStressResults.Count -gt 0) { |
115 | | - # Attach every log to each GCStress result so they appear in the |
116 | | - # result's Attachments pane (the data-driven theory collapses to a |
117 | | - # single result, so over-attaching is both harmless and complete). |
118 | | - foreach ($res in $gcStressResults) { |
119 | | - $uri = "$baseUrl/_apis/test/Runs/$runId/Results/$($res.id)/attachments?api-version=$apiVer" |
120 | | - foreach ($log in $logFiles) { |
| 134 | + $usedDebuggees = New-Object 'System.Collections.Generic.HashSet[string]' |
| 135 | + |
| 136 | + # Attach each debuggee's log to its own test result. The legacy reporter |
| 137 | + # models a [Theory] as a single result with one sub-result per data row, |
| 138 | + # so the per-debuggee runs are sub-results (attach via testSubResultId). |
| 139 | + # A single-row theory (e.g. the Windows-only PInvoke case) stays as a |
| 140 | + # standalone result with the arg in its name (attach to the result). |
| 141 | + foreach ($res in $gcStressResults) { |
| 142 | + $detail = Invoke-RestMethod -Headers $headers -Uri "$baseUrl/_apis/test/runs/$runId/results/$($res.id)?detailsToInclude=SubResults&api-version=7.1" -Method Get |
| 143 | + $subs = @($detail.subResults) |
| 144 | + |
| 145 | + if ($subs.Count -gt 0) { |
| 146 | + foreach ($sub in $subs) { |
| 147 | + $d = Get-Debuggee $sub.displayName |
| 148 | + if ($d -and $logByDebuggee.ContainsKey($d.ToLowerInvariant())) { |
| 149 | + $log = $logByDebuggee[$d.ToLowerInvariant()] |
| 150 | + $uri = "$baseUrl/_apis/test/Runs/$runId/Results/$($res.id)/attachments?testSubResultId=$($sub.id)&api-version=$apiVer" |
| 151 | + try { |
| 152 | + Add-Attachment -uri $uri -fileName "$d.txt" -filePath $log.FullName |
| 153 | + $attached++; [void]$usedDebuggees.Add($d.ToLowerInvariant()) |
| 154 | + } catch { |
| 155 | + Write-Warn "Failed to attach '$($log.Name)' to run $runId result $($res.id) sub $($sub.id): $($_.Exception.Message)" |
| 156 | + } |
| 157 | + } else { |
| 158 | + Write-Warn "No log found for sub-result debuggee '$d' (result $($res.id))." |
| 159 | + } |
| 160 | + } |
| 161 | + } else { |
| 162 | + $d = Get-Debuggee $res.automatedTestName |
| 163 | + if ($d -and $logByDebuggee.ContainsKey($d.ToLowerInvariant())) { |
| 164 | + $log = $logByDebuggee[$d.ToLowerInvariant()] |
| 165 | + $uri = "$baseUrl/_apis/test/Runs/$runId/Results/$($res.id)/attachments?api-version=$apiVer" |
121 | 166 | try { |
122 | | - Add-Attachment -uri $uri -fileName (Get-CleanName $log.Name) -filePath $log.FullName |
123 | | - $attached++ |
| 167 | + Add-Attachment -uri $uri -fileName "$d.txt" -filePath $log.FullName |
| 168 | + $attached++; [void]$usedDebuggees.Add($d.ToLowerInvariant()) |
124 | 169 | } catch { |
125 | 170 | Write-Warn "Failed to attach '$($log.Name)' to run $runId result $($res.id): $($_.Exception.Message)" |
126 | 171 | } |
127 | 172 | } |
128 | 173 | } |
129 | | - Write-Info "Run $runId ('$($run.name)'): attached $attached log(s) across $($gcStressResults.Count) GCStress result(s)." |
130 | | - } else { |
131 | | - # Fallback: attach at the run level. |
132 | | - $uri = "$baseUrl/_apis/test/Runs/$runId/attachments?api-version=$apiVer" |
133 | | - foreach ($log in $logFiles) { |
| 174 | + } |
| 175 | + |
| 176 | + # Fallback: any log we couldn't map to a result/sub-result (e.g. a |
| 177 | + # debuggee that crashed before producing a result) is attached at the run |
| 178 | + # level so nothing is silently lost. |
| 179 | + foreach ($kv in $logByDebuggee.GetEnumerator()) { |
| 180 | + if (-not $usedDebuggees.Contains($kv.Key)) { |
| 181 | + $uri = "$baseUrl/_apis/test/Runs/$runId/attachments?api-version=$apiVer" |
134 | 182 | try { |
135 | | - Add-Attachment -uri $uri -fileName (Get-CleanName $log.Name) -filePath $log.FullName |
| 183 | + Add-Attachment -uri $uri -fileName (Get-CleanName $kv.Value.Name) -filePath $kv.Value.FullName |
136 | 184 | $attached++ |
| 185 | + Write-Warn "Debuggee '$($kv.Key)' had no matching test result; attached '$($kv.Value.Name)' at run level." |
137 | 186 | } catch { |
138 | | - Write-Warn "Failed to attach '$($log.Name)' to run ${runId}: $($_.Exception.Message)" |
| 187 | + Write-Warn "Failed to attach unmatched '$($kv.Value.Name)' to run ${runId}: $($_.Exception.Message)" |
139 | 188 | } |
140 | 189 | } |
141 | | - Write-Info "Run $runId ('$($run.name)'): no GCStress result found; attached $attached log(s) at run level." |
142 | 190 | } |
| 191 | + |
| 192 | + Write-Info "Run $runId ('$($run.name)'): attached $attached log(s) ($($usedDebuggees.Count) mapped to per-debuggee results)." |
143 | 193 | } |
144 | 194 | } |
145 | 195 | catch { |
|
0 commit comments