Files
runner-images-sangeeth/helpers/software-report-base/SoftwareReport.DifferenceCalculator.psm1
Maxim Lobanov 4aeccc7b5b Implement tests for software-report-module (#6815)
* Minor improvements

* fix typos

* fix brew rendering

* add temp test

* Implement tests

* Add arguments validation

* ToMarkdown()

* Use before-All and helpers

* Get rid of arrays

* Add validation, no new nodes after header

* Fix naming

* add workflow

* Revisit comments + tiny improvements

* Fix tables

* Fix html table indent

* remove comment

* attemp to break test - testing CI

* revert breaking test

* fix nitpicks
2022-12-21 10:58:27 +01:00

136 lines
8.1 KiB
PowerShell

using module ./SoftwareReport.psm1
using module ./SoftwareReport.BaseNodes.psm1
using module ./SoftwareReport.Nodes.psm1
using module ./SoftwareReport.DifferenceRender.psm1
class SoftwareReportDifferenceCalculator {
[ValidateNotNullOrEmpty()]
hidden [SoftwareReport] $PreviousReport
[ValidateNotNullOrEmpty()]
hidden [SoftwareReport] $CurrentReport
hidden [Collections.Generic.List[ReportDifferenceItem]] $AddedItems
hidden [Collections.Generic.List[ReportDifferenceItem]] $ChangedItems
hidden [Collections.Generic.List[ReportDifferenceItem]] $DeletedItems
SoftwareReportDifferenceCalculator([SoftwareReport] $PreviousReport, [SoftwareReport] $CurrentReport) {
$this.PreviousReport = $PreviousReport
$this.CurrentReport = $CurrentReport
}
[void] CompareReports() {
$this.AddedItems = @()
$this.ChangedItems = @()
$this.DeletedItems = @()
$this.CompareInternal($this.PreviousReport.Root, $this.CurrentReport.Root, @())
}
[String] GetMarkdownReport() {
$reporter = [SoftwareReportDifferenceRender]::new()
$report = $reporter.GenerateMarkdownReport($this.CurrentReport, $this.PreviousReport, $this.AddedItems, $this.ChangedItems, $this.DeletedItems)
return $report
}
hidden [void] CompareInternal([HeaderNode] $previousReportPointer, [HeaderNode] $currentReportPointer, [String[]] $Headers) {
$currentReportPointer.Children ?? @() | Where-Object { $_.ShouldBeIncludedToDiff() -and $this.FilterExcludedNodes($_) } | ForEach-Object {
$currentReportNode = $_
$sameNodeInPreviousReport = $previousReportPointer ? $previousReportPointer.FindSimilarChildNode($currentReportNode) : $null
if ($currentReportNode -is [HeaderNode]) {
# Compare HeaderNode recursively
$this.CompareInternal($sameNodeInPreviousReport, $currentReportNode, $Headers + $currentReportNode.Title)
} else {
if ($sameNodeInPreviousReport -and ($currentReportNode.IsIdenticalTo($sameNodeInPreviousReport))) {
# Nodes are identical, nothing changed, just ignore it
} elseif ($sameNodeInPreviousReport) {
# Nodes are equal but not identical, something was changed
if ($currentReportNode -is [TableNode]) {
$this.CompareSimilarTableNodes($sameNodeInPreviousReport, $currentReportNode, $Headers)
} elseif ($currentReportNode -is [ToolVersionsListNode]) {
$this.CompareSimilarToolVersionsListNodes($sameNodeInPreviousReport, $currentReportNode, $Headers)
} else {
$this.ChangedItems.Add([ReportDifferenceItem]::new($sameNodeInPreviousReport, $currentReportNode, $Headers))
}
} else {
# Node was not found in previous report, new node was added
$this.AddedItems.Add([ReportDifferenceItem]::new($null, $currentReportNode, $Headers))
}
}
}
# Detecting nodes that were removed
$previousReportPointer.Children ?? @() | Where-Object { $_.ShouldBeIncludedToDiff() -and $this.FilterExcludedNodes($_) } | ForEach-Object {
$previousReportNode = $_
$sameNodeInCurrentReport = $currentReportPointer ? $currentReportPointer.FindSimilarChildNode($previousReportNode) : $null
if (-not $sameNodeInCurrentReport) {
if ($previousReportNode -is [HeaderNode]) {
# Compare removed HeaderNode recursively
$this.CompareInternal($previousReportNode, $null, $Headers + $previousReportNode.Title)
} else {
# Node was not found in current report, node was removed
$this.DeletedItems.Add([ReportDifferenceItem]::new($previousReportNode, $null, $Headers))
}
}
}
}
hidden [void] CompareSimilarTableNodes([TableNode] $PreviousReportNode, [TableNode] $CurrentReportNode, [String[]] $Headers) {
$addedRows = $CurrentReportNode.Rows | Where-Object { $_ -notin $PreviousReportNode.Rows }
$deletedRows = $PreviousReportNode.Rows | Where-Object { $_ -notin $CurrentReportNode.Rows }
if (($addedRows.Count -eq 0) -and ($deletedRows.Count -eq 0)) {
# Unexpected state: TableNodes are identical
return
}
if ($PreviousReportNode.Headers -ne $CurrentReportNode.Headers) {
# If headers are changed and rows are changed at the same time, we should track it as removing table and adding new one
$this.DeletedItems.Add([ReportDifferenceItem]::new($PreviousReportNode, $null, $Headers))
$this.AddedItems.Add([ReportDifferenceItem]::new($null, $CurrentReportNode, $Headers))
} elseif (($addedRows.Count -gt 0) -and ($deletedRows.Count -eq 0)) {
# If new rows were added and no rows were deleted, then it is AddedItem
$this.AddedItems.Add([ReportDifferenceItem]::new($PreviousReportNode, $CurrentReportNode, $Headers))
} elseif (($deletedRows.Count -gt 0) -and ($addedRows.Count -eq 0)) {
# If no rows were added and some rows were deleted, then it is DeletedItem
$this.DeletedItems.Add([ReportDifferenceItem]::new($PreviousReportNode, $CurrentReportNode, $Headers))
} else {
# If some rows were added and some rows were removed, then it is UpdatedItem
$this.ChangedItems.Add([ReportDifferenceItem]::new($PreviousReportNode, $CurrentReportNode, $Headers))
}
}
hidden [void] CompareSimilarToolVersionsListNodes([ToolVersionsListNode] $PreviousReportNode, [ToolVersionsListNode] $CurrentReportNode, [String[]] $Headers) {
$previousReportMajorVersions = $PreviousReportNode.Versions | ForEach-Object { $PreviousReportNode.ExtractMajorVersion($_) }
$currentReportMajorVersion = $CurrentReportNode.Versions | ForEach-Object { $CurrentReportNode.ExtractMajorVersion($_) }
$addedVersions = $CurrentReportNode.Versions | Where-Object { $CurrentReportNode.ExtractMajorVersion($_) -notin $previousReportMajorVersions }
$deletedVersions = $PreviousReportNode.Versions | Where-Object { $PreviousReportNode.ExtractMajorVersion($_) -notin $currentReportMajorVersion }
$changedPreviousVersions = $PreviousReportNode.Versions | Where-Object { ($PreviousReportNode.ExtractMajorVersion($_) -in $currentReportMajorVersion) -and ($_ -notin $CurrentReportNode.Versions) }
$changedCurrentVersions = $CurrentReportNode.Versions | Where-Object { ($CurrentReportNode.ExtractMajorVersion($_) -in $previousReportMajorVersions) -and ($_ -notin $PreviousReportNode.Versions) }
if ($addedVersions.Count -gt 0) {
$this.AddedItems.Add([ReportDifferenceItem]::new($null, [ToolVersionsListNode]::new($CurrentReportNode.ToolName, $addedVersions, $CurrentReportNode.MajorVersionRegex, "List"), $Headers))
}
if ($deletedVersions.Count -gt 0) {
$this.DeletedItems.Add([ReportDifferenceItem]::new([ToolVersionsListNode]::new($PreviousReportNode.ToolName, $deletedVersions, $PreviousReportNode.MajorVersionRegex, "List"), $null, $Headers))
}
$previousChangedNode = ($changedPreviousVersions.Count -gt 0) ? [ToolVersionsListNode]::new($PreviousReportNode.ToolName, $changedPreviousVersions, $PreviousReportNode.MajorVersionRegex, "List") : $null
$currentChangedNode = ($changedCurrentVersions.Count -gt 0) ? [ToolVersionsListNode]::new($CurrentReportNode.ToolName, $changedCurrentVersions, $CurrentReportNode.MajorVersionRegex, "List") : $null
if ($previousChangedNode -and $currentChangedNode) {
$this.ChangedItems.Add([ReportDifferenceItem]::new($previousChangedNode, $currentChangedNode, $Headers))
}
}
hidden [Boolean] FilterExcludedNodes([BaseNode] $Node) {
# We shouldn't show "Image Version" diff because it is already shown in report header
if (($Node -is [ToolVersionNode]) -and ($Node.ToolName -eq "Image Version:")) {
return $false
}
return $true
}
}