tests-upgrade/tests-emitter/EmitterTest.ps1 (260 lines of code) (raw):

param( [Parameter(Mandatory, ParameterSetName = "SingleTestCase", HelpMessage = "Specify single test case to run")] [string] $TestName, [Parameter(Mandatory, ParameterSetName = "WhiteTestCase", HelpMessage = "Load white test case list from configuration to run")] [switch]$AllowList, [Parameter(Mandatory, ParameterSetName = "BlackTestCase", HelpMessage = "Load all test cases in the current folder and remove test cases that exist in the blacklist")] [switch]$BlackList, [string] $PowerShellEmitter, [switch] $SaveResult ) enum GeneratedStatus { Failed Success Skipped } enum ComparedStatus { Equal NotEqual } class TestEmitterModel { [string]$TestName [GeneratedStatus]$EmitterGeneratedStatus [ComparedStatus]$CodeComparedStatus [string]$GeneratedCodeFolder [string]$TargetCodeFolder [string[]]$Result [string]$Comment } function GenerateModuleWithEmitter { param ( [TestEmitterModel] $TestEmitter ) $result = (tsp compile ./ --emit $script:PowerShellEmitter) | Out-String Write-Debug "$($TestEmitter.TestName) generated powershell debug information" Write-Debug $result if ($LASTEXITCODE -ne 0) { return $false } elseif (!(Test-Path -Path $TestEmitter.TargetCodeFolder)) { return $false } else { return $true } } function GenerateCodeWithEmitter { param ( [TestEmitterModel] $TestEmitter ) Set-Location (Join-Path $TestEmitter.GeneratedCodeFolder '..') if ((GenerateModuleWithEmitter -TestEmitter $TestEmitter)) { $TestEmitter.EmitterGeneratedStatus = [GeneratedStatus]::Success } else { $TestEmitter.EmitterGeneratedStatus = [GeneratedStatus]::Failed $TestEmitter.Result += $TestEmitter.EmitterGeneratedStatus ? $null : "PowerShell module failed to generate" } Set-Location $PSScriptRoot } function CompareGenerateFileCount { param ( [string[]] $GeneratedFileNames, [string[]] $TargetFileNames ) $result = @{"result" = $null; "files" = @() } $ignoreFiles = @(".gitignore") foreach ($GeneratedFileName in $GeneratedFileNames) { if ($ignoreFiles -contains $GeneratedFileName) { #skip ignored files continue } if ($TargetFileNames -notcontains $GeneratedFileName) { $result["result"] += "$GeneratedFileName not extis in target folder. " } else { $result["files"] += $GeneratedFileName } } foreach ($TargetFileName in $TargetFileNames) { if ($ignoreFiles -contains $TargetFileName) { #skip ignored files continue } if ($GeneratedFileNames -notcontains $TargetFileName) { $result["result"] += "$TargetFileName not extis in generated folder. " } } return $result } function CompareSingleGeneratedFile { param ( [string] $GeneratedFilePath, [string] $TargetFilePath ) $fileName = Split-Path -Path $GeneratedFilePath -Leaf $validGeneratedContent = ((Get-Content -Path $GeneratedFilePath) | ForEach-Object { ($_ -replace "\s+", "") } ` | Where-Object { (($_ -notlike "*//*") -and ($_ -ne "") -and ($_ -ne '{') -and ($_ -ne '}') -and ($_ -ne '};')) }) $validTargetContent = ((Get-Content -Path $TargetFilePath) | ForEach-Object { ($_ -replace "\s+", "") } ` | Where-Object { (($_ -notlike "*//*") -and ($_ -ne "") -and ($_ -ne '{') -and ($_ -ne '}') -and ($_ -ne '};')) }) if ($validGeneratedContent.Length -ne $validTargetContent.Length) { return @{"compared" = $false; "result" = "$fileName - content different" } } foreach ($generatedContent in $validGeneratedContent) { if ($validTargetContent -notcontains $generatedContent) { return @{"compared" = $false; "result" = "$fileName - content different" } } } return @{"compared" = $true; "result" = $null } } function CompareTestEmitterCode { param ( [TestEmitterModel] $TestEmitter, [string[]] $ignoreFiles ) if ($TestEmitter.EmitterGeneratedStatus -eq [GeneratedStatus]::Failed) { $TestEmitter.CodeComparedStatus = [ComparedStatus]::NotEqual return } else { $generatedFiles = Get-ChildItem -Path $TestEmitter.GeneratedCodeFolder -Recurse -File | Where-Object { $exclude = $false foreach ($excludePath in $ignoreFiles) { if ($_.FullName -like "*$excludePath*") { $exclude = $true break } } -not $exclude } $targetFiles = Get-ChildItem -Path $TestEmitter.TargetCodeFolder -Recurse -File | Where-Object { $exclude = $false foreach ($excludePath in $ignoreFiles) { if ($_.FullName -like "*$excludePath*") { $exclude = $true break } } -not $exclude } $compareResult = (CompareGenerateFileCount -GeneratedFileNames $generatedFiles.Name -TargetFileNames $targetFiles.Name) $isFileContentEqual = $true if ($null -ne $compareResult["result"]) { $TestEmitter.Result += $compareResult["result"] $isFileContentEqual = $false } # Get files that exist in generated and target folder $existGeneratedFiles = $generatedFiles | Where-Object { $compareResult["files"] -contains $_.Name } foreach ($existFile in $existGeneratedFiles) { $targetFile = $targetFiles | Where-Object { $_.FullName.Replace([System.IO.Path]::DirectorySeparatorChar + 'target', [System.IO.Path]::DirectorySeparatorChar + 'generated') -eq $existFile.FullName } $fileCompareResult = CompareSingleGeneratedFile -GeneratedFilePath $existFile.FullName -TargetFilePath $targetFile.FullName if (!$fileCompareResult["compared"]) { $TestEmitter.Result += $fileCompareResult["result"] $isFileContentEqual = $false } } if ($isFileContentEqual) { $TestEmitter.CodeComparedStatus = [ComparedStatus]::Equal } else { $TestEmitter.CodeComparedStatus = [ComparedStatus]::NotEqual } } } try { if ([System.String]::IsNullOrEmpty($PowerShellEmitter)) { $PowerShellEmitter = Join-Path $PSScriptRoot "..\..\packages\typespec-powershell" } $configuration = (Get-Content -Path (Join-Path $PSScriptRoot "configuration.json") | ConvertFrom-Json) # Some folders are not test folders. $ignoreFolder = $configuration.ignoreFolder # Skip no need compare file. $ignoreCompareFiles = $configuration.ignoreCompareFile $testEmitterSummary = @() $compareResultFolder = Join-Path $PSScriptRoot "CompareResult" if (!(Test-Path -Path $compareResultFolder)) { New-Item -Path $compareResultFolder -ItemType "directory" } if ($TestName) { $testFolder = Join-Path $PSScriptRoot $TestName if ((Test-Path -Path $testFolder)) { $tests += (Get-Item -Path $testFolder) } else { Throw "$TestName folder not exist." } } if ($BlackList) { $blackTestList = $configuration.blackTestList $tests = (Get-ChildItem -Path $PSScriptRoot -Directory -Exclude ($blackTestList + $ignoreFolder)) | Sort-Object { $_.Name } } if ($AllowList) { $whiteTestList = $configuration.whiteTestList $tests = @() foreach ($whiteTest in $whiteTestList) { $testFolder = Join-Path $PSScriptRoot $whiteTest if ((Test-Path -Path $testFolder)) { $tests += (Get-Item -Path $testFolder) } else { Throw "Test $whiteTest folder not exist." } } } foreach ($test in $tests) { $testEmitter = [TestEmitterModel]::new() $testEmitter.TestName = $test.Name $testEmitter.EmitterGeneratedStatus = [GeneratedStatus]::Failed $testEmitter.CodeComparedStatus = [ComparedStatus]::NotEqual $testEmitter.GeneratedCodeFolder = (Join-Path $test.FullName 'generated') $testEmitter.TargetCodeFolder = (Join-Path $test.FullName 'target') $testEmitterSummary += $testEmitter } foreach ($testEmitter in $testEmitterSummary) { Write-Host "test $($testEmitter.TestName) testing...." GenerateCodeWithEmitter -TestEmitter $testEmitter CompareTestEmitterCode -TestEmitter $testEmitter -ignoreFiles $ignoreCompareFiles $testEmitter.Comment = ($testEmitter.Result | Out-String) $testEmitter | Select-Object -Property TestName, EmitterGeneratedStatus, CodeComparedStatus, Comment | Format-Table } if ($PSCmdlet.ParameterSetName -ne 'SingleTestCase' ) { Write-Host "Summary results as following" # Show summary test result $testEmitterSummary | Select-Object -Property TestName, EmitterGeneratedStatus, CodeComparedStatus, Comment | Format-Table } if ($testEmitterSummary.CodeComparedStatus -contains [ComparedStatus]::NotEqual) { throw 'The code generated by the typespec-powershell emitter is different from the target code.' } else { Write-Host 'All generated codes are as expected.' } } catch { Write-Error "An error occurred" Write-Error ($_ | Out-String) } finally { # Save test result to csv file if ($SaveResult) { $resultFilePath = Join-Path $compareResultFolder "typespec-powershell-generated-code-compare-$((Get-Date).ToString('yyyyMMddHHmmss')).csv" Write-Host "The output result to the $resultFilePath" $testEmitterSummary | Select-Object -Property TestName, EmitterGeneratedStatus, CodeComparedStatus, Comment | Export-Csv -Path $resultFilePath -NoClobber } }