1
+ param ([Parameter (Mandatory = $true )][string ] $pulseFilePath )
2
+
3
+ $ErrorActionPreference = ' Stop'
4
+ Set-PSDebug - Strict
5
+
6
+ Add-Type - AssemblyName System.IO.Compression.FileSystem
7
+
8
+ function Get-ArchiveTextEntries ([string ] $archivePath , [string []] $entryNames ) {
9
+ $entries = @ ()
10
+ $archive = [System.IO.Compression.ZipFile ]::Open($archivePath , 0 )
11
+ try {
12
+ $entryNames | % {
13
+ $entry = $archive.getentry ($_ )
14
+ if ($entry -eq $null ) { throw " Unable to find entry '$_ ' in $archivePath " }
15
+ $entryStream = new-object System.IO.StreamReader($entry.open ())
16
+ try {
17
+ $entries += $entryStream.readtoend ()
18
+ } finally {
19
+ $entryStream.close ()
20
+ }
21
+ }
22
+ } finally {
23
+ $archive.dispose ()
24
+ }
25
+ $entries
26
+ }
27
+
28
+ function Test-ExportFileVersion ([string ] $pulseFilePath , [string ] $version ) {
29
+ (Get-ArchiveTextEntries $pulseFilePath ' .manifest' | select-string " version=$version " ) -ne $null
30
+ }
31
+
32
+ function Write-CodeCoverage ($groupingNodes , $encounters ) {
33
+ $groupingNodes | sort-object - property ' label' | % {
34
+ Write-Host (" {0}{1} - {2} of {3} methods ({4})" -f `
35
+ (new-object string(" `t " , $_.level )),`
36
+ $_.label , `
37
+ $_.encounters ,`
38
+ $_.nodes ,`
39
+ $_.coverage.tostring (' P' ))
40
+
41
+ if ($encounters -ne $null ) {
42
+ $groupingNode = $_
43
+ $groupingNode.methods.keys | ? { $encounters.ContainsKey ($_ ) } | sort-object ' label' | % {
44
+ Write-Host (" {0}-> [{2}] {1}" -f `
45
+ (new-object string(" `t " , ($groupingNode.level + 1 ))),`
46
+ $groupingNode.methods [$_ ].label,`
47
+ $groupingNode.methods [$_ ].parent.label)
48
+ }
49
+ }
50
+ Write-CodeCoverage ($_.packages.keys | % { $nodes [$_ ] }) $encounters
51
+ }
52
+ }
53
+
54
+ Write-Verbose ' Checking export file version compatibility with this script...'
55
+ $supportedVersions = ' 2' , ' 2.1'
56
+ if (-not (($supportedVersions | % { Test-ExportFileVersion $pulseFilePath $_ }) -contains $true )) {
57
+ throw " Unable to continue after finding unsupported manifest file version in $pulseFilePath (supported versions: $ ( [string ]::Join(' ,' , $supportedVersions )) )."
58
+ }
59
+
60
+ Write-Verbose ' Reading export file data...'
61
+ $coverageData = Get-ArchiveTextEntries $pulseFilePath ' nodes.json' , ' encounters.json'
62
+
63
+ Write-Verbose ' Indexing nodes...'
64
+ $nodes = @ {}
65
+ (ConvertFrom-Json $coverageData [0 ]) | % { $nodes [$_.id ] = $_ }
66
+
67
+ Write-Verbose ' Indexing encounters...'
68
+ $encounters = @ {}
69
+ (ConvertFrom-Json $coverageData [1 ]).all | % { $encounters [$_.nodeid ] = $_ }
70
+
71
+ Write-Verbose ' Processing packages/groups...'
72
+ $groupingNodes = $nodes.keys | ? { $nodes [$_ ].kind -eq ' package' -or $nodes [$_ ].kind -eq ' group' } | % { $node = $nodes [$_ ]
73
+
74
+ $groupNode = $node
75
+ $groupNodes = @ ($groupNode )
76
+
77
+ while ($groupNode.parentId -ne $null ) {
78
+ $parentNode = $nodes [$groupNode.parentId ]
79
+
80
+ Add-Member -in $parentNode ' packages' @ {} - erroract SilentlyContinue
81
+
82
+ $parentNode.packages [$groupNode.id ] = $groupNode
83
+ $groupNode = $parentNode
84
+ $groupNodes += $groupNode
85
+ }
86
+
87
+ $level = 0 ; [array ]::reverse($groupNodes )
88
+ $groupNodes | % {
89
+ if ((Get-Member -in $_ ' level' ) -eq $null ) { Add-Member -in $_ ' level' 0 }
90
+ $_.level = $level ++
91
+ }
92
+
93
+ $parentNode = $null
94
+ if ($node.parentId -ne $null ) {
95
+ $parentNode = $nodes [$node.parentId ]
96
+ }
97
+
98
+ Add-Member -in $node ' nodes' 0
99
+ Add-Member -in $node ' encounters' 0
100
+ Add-Member -in $node ' coverage' 0
101
+ Add-Member -in $node ' parent' $parentNode
102
+ Add-Member -in $node ' packages' @ {} - erroract SilentlyContinue
103
+ Add-Member -in $node ' methods' @ {} - pass
104
+ }
105
+
106
+ Write-Verbose ' Processing method ancestors...'
107
+ $methodNodes = $nodes.keys | ? { $nodes [$_ ].kind -eq ' method' } | % { $methodNode = $nodes [$_ ]
108
+ $parent = $nodes [$methodNode.parentId ]
109
+ while ($parent.kind -ne ' package' -and $parent.kind -ne ' group' ) {
110
+ $parent = $nodes [$parent.parentId ]
111
+ }
112
+ $parent.methods [$methodNode.id ] = $methodNode
113
+
114
+ Add-Member -in $methodNode ' parent' $nodes [$methodNode.parentId ]
115
+ $methodNode
116
+ }
117
+
118
+ Write-Verbose ' Processing leaf group nodes...'
119
+ $leafGroupingNodes = $groupingNodes | ? { $_.methods.Count -gt 0 }
120
+ $leafGroupingNodes | % {
121
+ $_.encounters = ($_.methods.keys | ? { $encounters.ContainsKey ($_ ) }).length
122
+ $_.nodes = $_.methods.Count
123
+ }
124
+
125
+ Write-Verbose ' Counting nodes and encounters across packages...'
126
+ $maxLevel = ($groupingNodes | % { $_.level } | measure - max).Maximum
127
+ $maxLevel .. 0 | % {
128
+ $level = $_
129
+ $groupingNodes | ? { $_.level -eq $level } | % {
130
+ $groupingNode = $_
131
+ $groupingNode.packages.keys | % {
132
+ $groupingNode.encounters += $nodes [$_ ].encounters
133
+ $groupingNode.nodes += $nodes [$_ ].nodes
134
+ }
135
+ $groupingNode.coverage = 0
136
+ if ($groupingNode.nodes -gt 0 ) {
137
+ $groupingNode.coverage = $groupingNode.encounters / $groupingNode.nodes
138
+ }
139
+ }
140
+ }
141
+
142
+ Write-Verbose ' Finding root package/group nodes...'
143
+ $topLevelGroupingNodes = $groupingNodes | ? { $_.level -eq 0 }
144
+
145
+ Write-Verbose ' Determining total method code coverage...'
146
+ $encountersCount = 0 ; $nodesCount = 0 ; $codeCoverage = 0
147
+ $topLevelGroupingNodes | % { $encountersCount = $_.encounters ; $nodesCount = $_.nodes }
148
+ $codeCoverage = $ (if ($nodesCount -eq 0 ) { 0 } else { $encountersCount / $nodesCount })
149
+
150
+ Write-Verbose ' Writing total method code coverage by package...'
151
+ Write-Host " `n Total Method Code Coverage: " $codeCoverage.ToString (' P' )
152
+
153
+ Write-Verbose ' Writing method code coverage by package...'
154
+ Write-Host " `n`n Method Code Coverage by Package:`n "
155
+ Write-CodeCoverage $topLevelGroupingNodes
156
+
157
+ Write-Verbose ' Writing method code coverage by package and method...'
158
+ Write-Host " `n`n Method Code Coverage by Package and Method:`n "
159
+ Write-CodeCoverage $topLevelGroupingNodes $encounters
0 commit comments