From c0160f525975f70a93d70bb7846e602c97947765 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 5 May 2021 13:18:46 -0700 Subject: [PATCH 01/41] Struct out PGO scripts and jobs borrowed from MUX --- .vscode/settings.json | 6 +- build/Helix/RunTestsInHelix.proj | 1 + build/Helix/runtests.cmd | 2 +- build/pipelines/pgo.yml | 27 ++++++ .../pipelines/templates/build-console-pgo.yml | 52 +++++++++++ .../templates/build-console-steps.yml | 91 +++++++------------ .../templates/helix-runtests-job.yml | 14 ++- .../pgo-build-and-publish-nuget-job.yml | 55 +++++++++++ .../pipelines/templates/pgo-merge-pgd-job.yml | 54 +++++++++++ .../WindowsTerminal/WindowsTerminal.vcxproj | 4 +- src/common.pgo.compile.props | 19 ++++ src/common.pgo.runtime.props | 28 ++++++ src/host/exe/Host.EXE.vcxproj | 3 + tools/NugetWrapper.cmd | 26 ++++++ tools/PGODatabase/NuSpecs/PGO.nuspec.template | 21 +++++ tools/PGODatabase/NuSpecs/build/PGO.targets | 15 +++ tools/PGODatabase/PGO.version.props.template | 8 ++ tools/PGODatabase/config.ps1 | 7 ++ tools/PGODatabase/generate-nuspec.ps1 | 11 +++ tools/PGODatabase/readme.md | 49 ++++++++++ tools/PGODatabase/restore-pgodb.ps1 | 47 ++++++++++ tools/PGODatabase/template.ps1 | 16 ++++ tools/PGODatabase/version.ps1 | 75 +++++++++++++++ 23 files changed, 569 insertions(+), 62 deletions(-) create mode 100644 build/pipelines/pgo.yml create mode 100644 build/pipelines/templates/build-console-pgo.yml create mode 100644 build/pipelines/templates/pgo-build-and-publish-nuget-job.yml create mode 100644 build/pipelines/templates/pgo-merge-pgd-job.yml create mode 100644 src/common.pgo.compile.props create mode 100644 src/common.pgo.runtime.props create mode 100644 tools/NugetWrapper.cmd create mode 100644 tools/PGODatabase/NuSpecs/PGO.nuspec.template create mode 100644 tools/PGODatabase/NuSpecs/build/PGO.targets create mode 100644 tools/PGODatabase/PGO.version.props.template create mode 100644 tools/PGODatabase/config.ps1 create mode 100644 tools/PGODatabase/generate-nuspec.ps1 create mode 100644 tools/PGODatabase/readme.md create mode 100644 tools/PGODatabase/restore-pgodb.ps1 create mode 100644 tools/PGODatabase/template.ps1 create mode 100644 tools/PGODatabase/version.ps1 diff --git a/.vscode/settings.json b/.vscode/settings.json index 1b6028e5aea..03fd8e97206 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,5 +41,9 @@ "**/obj/**": true, "**/packages/**": true, "**/generated files/**": true - } + }, + "vscode-nmake-tools.workspaceBuildDirectories": [ + "d:\\src\\terminal" + ], + "C_Cpp.default.configurationProvider": "microsoft.vscode-nmake-tools" } \ No newline at end of file diff --git a/build/Helix/RunTestsInHelix.proj b/build/Helix/RunTestsInHelix.proj index d5206693784..aaac4ab47ab 100644 --- a/build/Helix/RunTestsInHelix.proj +++ b/build/Helix/RunTestsInHelix.proj @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/build/Helix/runtests.cmd b/build/Helix/runtests.cmd index b55ee2cf3c8..77f6180e09a 100644 --- a/build/Helix/runtests.cmd +++ b/build/Helix/runtests.cmd @@ -46,7 +46,7 @@ move te.wtl te_original.wtl copy /y te_original.wtl %HELIX_WORKITEM_UPLOAD_ROOT% copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT% -for /f "tokens=* delims=" %%a in ('dir /b *.pgc') do ren "%%a" "%testnameprefix%.%%~na.pgc" +:: for /f "tokens=* delims=" %%a in ('dir /b *.pgc') do ren "%%a" "%testnameprefix%.%%~na.pgc" copy /y *.pgc %HELIX_WORKITEM_UPLOAD_ROOT% set FailedTestQuery= diff --git a/build/pipelines/pgo.yml b/build/pipelines/pgo.yml new file mode 100644 index 00000000000..f221f10387a --- /dev/null +++ b/build/pipelines/pgo.yml @@ -0,0 +1,27 @@ +trigger: none +pr: none + +variables: + - name: runCodesignValidationInjectionBG + value: false + +# 0.0.yyMM.dd## +# 0.0.1904.0900 +name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr) + +stages: + - stage: Build_x64 + displayName: Build x64 + dependsOn: [] + condition: succeeded() + jobs: + - template: ./templates/build-console-pgo.yml + parameters: + platform: x64 + - stage: Build_x86 + displayName: Build x86 + dependsOn: [] + jobs: + - template: ./templates/build-console-pgo.yml + parameters: + platform: x86 diff --git a/build/pipelines/templates/build-console-pgo.yml b/build/pipelines/templates/build-console-pgo.yml new file mode 100644 index 00000000000..9590dd955ba --- /dev/null +++ b/build/pipelines/templates/build-console-pgo.yml @@ -0,0 +1,52 @@ +parameters: + configuration: 'Release' + platform: '' + additionalBuildArguments: '' + minimumExpectedTestsExecutedCount: 10 # Sanity check for minimum expected tests to be reported + rerunPassesRequiredToAvoidFailure: 5 + +jobs: +- job: Build${{ parameters.platform }}${{ parameters.configuration }} + displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }} + variables: + BuildConfiguration: ${{ parameters.configuration }} + BuildPlatform: ${{ parameters.platform }} + PGOBuildMode: 'Instrument' + pool: "windevbuildagents" + # The public pool is also an option! + # pool: { vmImage: windows-2019 } + + steps: + - template: build-console-steps.yml + parameters: + additionalBuildArguments: ${{ parameters.additionalBuildArguments }} + +- template: helix-runtests-job.yml + parameters: + name: 'RunTestsInHelix' + dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }} + condition: succeeded() + testSuite: 'PgoInstrumentationSuite' + rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }} + +- template: helix-processtestresults-job.yml + parameters: + name: 'ProcessTestResults' + dependsOn: + - RunTestsInHelix + condition: succeededOrFailed() + rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }} + minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }} + +- template: pgo-merge-pgd-job.yml + parameters: + name: 'MergePGD' + dependsOn: + - ProcessTestResults + pgoArtifact: 'PGO' + +- template: pgo-build-and-publish-nuget-job.yml + parameters: + dependsOn: + - MergePGD + pgoArtifact: 'PGO' \ No newline at end of file diff --git a/build/pipelines/templates/build-console-steps.yml b/build/pipelines/templates/build-console-steps.yml index e5455dc8c4e..22bc6094c9a 100644 --- a/build/pipelines/templates/build-console-steps.yml +++ b/build/pipelines/templates/build-console-steps.yml @@ -32,6 +32,29 @@ steps: restoreSolution: build/packages.config restoreDirectory: '$(Build.SourcesDirectory)\packages' +# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves. +- script: | + "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt + set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt + del %TEMP%\vsinstalldir.txt + call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat" + echo VCToolsInstallDir = %VCToolsInstallDir% + echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir% + displayName: 'Retrieve VC tools directory' + +- task: CmdLine@1 + displayName: 'Display build machine environment variables' + inputs: + filename: 'set' + +- task: powershell@2 + displayName: 'Restore PGO database' + condition: eq(variables['PGOBuildMode'], 'Optimize') + inputs: + targetType: filePath + workingDirectory: $(Build.SourcesDirectory)\tools\PGODatabase + filePath: $(Build.SourcesDirectory)\tools\PGODatabase\restore-pgodb.ps1 + - task: VSBuild@1 displayName: 'Build solution **\OpenConsole.sln' inputs: @@ -51,60 +74,6 @@ steps: $Package = Get-ChildItem -Recurse -Filter "CascadiaPackage_*.msix" .\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path $Package.FullName -- task: powershell@2 - displayName: 'Source Index PDBs' - inputs: - targetType: filePath - filePath: build\scripts\Index-Pdbs.ps1 - arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion) - errorActionPreference: silentlyContinue - -- task: PowerShell@2 - displayName: 'Rationalize build platform' - inputs: - targetType: inline - script: | - $Arch = "$(BuildPlatform)" - If ($Arch -Eq "x86") { $Arch = "Win32" } - Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}" - -- task: PowerShell@2 - displayName: 'Run Unit Tests' - inputs: - targetType: filePath - filePath: build\scripts\Run-Tests.ps1 - arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' - condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86'))) - -- task: PowerShell@2 - displayName: 'Run Feature Tests (x64 only)' - inputs: - targetType: filePath - filePath: build\scripts\Run-Tests.ps1 - arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' - condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64')) - -- task: PowerShell@2 - displayName: 'Convert Test Logs from WTL to xUnit format' - inputs: - targetType: filePath - filePath: build\Helix\ConvertWttLogToXUnit.ps1 - arguments: -WttInputPath '${{ parameters.testLogPath }}' -WttSingleRerunInputPath 'unused.wtl' -WttMultipleRerunInputPath 'unused2.wtl' -XUnitOutputPath 'onBuildMachineResults.xml' -TestNamePrefix '$(BuildConfiguration).$(BuildPlatform)' - condition: or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')) - -- task: PublishTestResults@2 - displayName: 'Upload converted test logs' - inputs: - testResultsFormat: 'xUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest - testResultsFiles: '**/onBuildMachineResults.xml' - #searchFolder: '$(System.DefaultWorkingDirectory)' # Optional - #mergeTestResults: false # Optional - #failTaskOnFailedTests: false # Optional - testRunTitle: 'On Build Machine Tests' # Optional - buildPlatform: $(BuildPlatform) # Optional - buildConfiguration: $(BuildConfiguration) # Optional - #publishRunAttachments: true # Optional - - task: CopyFiles@2 displayName: 'Copy result logs to Artifacts' inputs: @@ -127,7 +96,7 @@ steps: TargetFolder: '$(Build.ArtifactStagingDirectory)/appx' OverWrite: true flattenFolders: true - condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) + condition: succeeded() - task: CopyFiles@2 displayName: 'Copy outputs needed for test runs to Artifacts' @@ -141,7 +110,17 @@ steps: TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test' OverWrite: true flattenFolders: true - condition: and(and(succeeded(), eq(variables['BuildPlatform'], 'x64')), ne(variables['Build.Reason'], 'PullRequest')) + condition: succeeded() + +- task: CopyFiles@2 + displayName: 'Copy PGO databases needed for PGO instrumentation run' + inputs: + Contents: | + $(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.pgd + TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/PGO' + OverWrite: true + flattenFolders: true + condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument')) - task: PublishBuildArtifacts@1 displayName: 'Publish All Build Artifacts' diff --git a/build/pipelines/templates/helix-runtests-job.yml b/build/pipelines/templates/helix-runtests-job.yml index 43854029191..39f3592f178 100644 --- a/build/pipelines/templates/helix-runtests-job.yml +++ b/build/pipelines/templates/helix-runtests-job.yml @@ -99,7 +99,7 @@ jobs: - template: helix-createprojfile-steps.yml parameters: - condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite')) + condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite')) testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\TerminalApp.LocalTests.dll' outputProjFileName: 'RunTestsInHelix-TerminalAppLocalTests.proj' testSuite: '${{ parameters.testSuite }}' @@ -107,7 +107,7 @@ jobs: - template: helix-createprojfile-steps.yml parameters: - condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite')) + condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite')) testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\SettingsModel.LocalTests.dll' outputProjFileName: 'RunTestsInHelix-SettingsModelLocalTests.proj' testSuite: '${{ parameters.testSuite }}' @@ -116,12 +116,20 @@ jobs: - template: helix-createprojfile-steps.yml parameters: - condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite')) + condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite')) testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\Conhost.UIA.Tests.dll' outputProjFileName: 'RunTestsInHelix-HostTestsUIA.proj' testSuite: '${{ parameters.testSuite }}' taefQuery: ${{ parameters.taefQuery }} + - template: helix-createprojfile-steps.yml + parameters: + condition: and(succeeded(),eq('${{ parameters.testSuite }}','PgoInstrumentationSuite')) + testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\TerminalApp.PGO.Tests.dll' + outputProjFileName: 'RunTestsInHelix-TerminalAppPGOTests.proj' + testSuite: '${{ parameters.testSuite }}' + taefQuery: ${{ parameters.taefQuery }} + - task: PublishBuildArtifacts@1 displayName: 'Publish generated .proj files' inputs: diff --git a/build/pipelines/templates/pgo-build-and-publish-nuget-job.yml b/build/pipelines/templates/pgo-build-and-publish-nuget-job.yml new file mode 100644 index 00000000000..d5d5a03e7c3 --- /dev/null +++ b/build/pipelines/templates/pgo-build-and-publish-nuget-job.yml @@ -0,0 +1,55 @@ +# From our friends at MUX: https://github.com/microsoft/microsoft-ui-xaml/blob/main/build/AzurePipelinesTemplates/MUX-BuildAndPublishPGONuGet-Job.yml + +parameters: + dependsOn: '' + pgoArtifact: PGO + +jobs: +- job: BuildAndPublishPGONuGet + dependsOn: ${{ parameters.dependsOn }} + pool: + vmImage: 'windows-2019' + variables: + artifactsPath: $(Build.SourcesDirectory)\Artifacts + pgoToolsPath: $(Build.SourcesDirectory)\tools\PGODatabase + nuspecPath: $(pgoToolsPath)\NuSpecs + nuspecFilename: PGO.nuspec + + steps: + - task: DownloadBuildArtifacts@0 + inputs: + artifactName: ${{ parameters.pgoArtifact }} + downloadPath: $(artifactsPath) + + - task: CopyFiles@2 + displayName: 'Copy pgd files to NuGet build directory' + inputs: + sourceFolder: $(artifactsPath)\${{ parameters.pgoArtifact }} + contents: '**\*.pgd' + targetFolder: $(nuspecPath)\tools + + - task: powershell@2 + displayName: 'Generate NuSpec file' + inputs: + targetType: filePath + filePath: $(pgoToolsPath)\generate-nuspec.ps1 + workingDirectory: $(pgoToolsPath) + arguments: $(nuspecPath)\$(nuspecFilename).template $(nuspecPath)\$(nuspecFilename) + + - task: CmdLine@1 + displayName: 'Build NuGet package' + inputs: + filename: '$(Build.SourcesDirectory)\tools\NugetWrapper.cmd' + arguments: pack "$(nuspecPath)\$(nuspecFilename)" -BasePath "$(nuspecPath)" -OutputDirectory "$(Build.ArtifactStagingDirectory)" -properties PROGRAMFILES="%ProgramFiles(x86)%" + + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: $(Build.ArtifactStagingDirectory) + artifactName: ${{ parameters.pgoArtifact }} + + - task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 + displayName: 'NuGet push' + inputs: + command: push + publishVstsFeed: Terminal/TerminalDependencies + packagesToPush: $(Build.ArtifactStagingDirectory)/*.nupkg \ No newline at end of file diff --git a/build/pipelines/templates/pgo-merge-pgd-job.yml b/build/pipelines/templates/pgo-merge-pgd-job.yml new file mode 100644 index 00000000000..74eb152ce44 --- /dev/null +++ b/build/pipelines/templates/pgo-merge-pgd-job.yml @@ -0,0 +1,54 @@ +parameters: + dependsOn: '' + pgoArtifact: PGO + +jobs: +- job: MergePGD + dependsOn: ${{ parameters.dependsOn }} + pool: + vmImage: 'windows-2019' + variables: + artifactsPath: $(Build.SourcesDirectory)\Artifacts + pgoArtifactsPath: $(artifactsPath)\${{ parameters.pgoArtifact }} + strategy: + matrix: ${{ parameters.matrix }} + + steps: + # The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves. + - script: | + "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt + set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt + del %TEMP%\vsinstalldir.txt + call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat" + echo VCToolsInstallDir = %VCToolsInstallDir% + echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir% + displayName: 'Retrieve VC tools directory' + + - task: DownloadBuildArtifacts@0 + inputs: + artifactName: ${{ parameters.pgoArtifact }} + downloadPath: $(artifactsPath) + + - script: | + cd $(buildPlatform) + "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge WindowsTerminal*.pgc WindowsTerminal.pgd + displayName: 'Merge Terminal pgc files into pgd' + workingDirectory: $(pgoArtifactsPath) + + - script: | + cd $(buildPlatform) + "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge OpenConsole*.pgc OpenConsole.pgd + displayName: 'Merge OpenConsole pgc files into pgd' + workingDirectory: $(pgoArtifactsPath) + + - task: CopyFiles@2 + displayName: 'Copy merged pgd to artifact staging' + inputs: + sourceFolder: $(pgoArtifactsPath) + contents: '**\$(buildPlatform)\*.pgd' + targetFolder: $(Build.ArtifactStagingDirectory) + + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: $(Build.ArtifactStagingDirectory) + artifactName: ${{ parameters.pgoArtifact }} \ No newline at end of file diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj index 806c83c0bf3..9c689cb1836 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj @@ -21,6 +21,8 @@ + + @@ -170,7 +172,7 @@ - + diff --git a/src/common.pgo.compile.props b/src/common.pgo.compile.props new file mode 100644 index 00000000000..4256c124dee --- /dev/null +++ b/src/common.pgo.compile.props @@ -0,0 +1,19 @@ + + + + + true + + + + + + /GENPROFILE %(AdditionalOptions) + UseLinkTimeCodeGeneration + $(VC_ReferencesPath_VC_ARM)\pgort.lib;%(AdditionalDependencies) + $(VC_ReferencesPath_VC_ARM64)\pgort.lib;%(AdditionalDependencies) + $(VC_ReferencesPath_VC_x86)\pgort.lib;%(AdditionalDependencies) + $(VC_ReferencesPath_VC_x64)\pgort.lib;%(AdditionalDependencies) + + + \ No newline at end of file diff --git a/src/common.pgo.runtime.props b/src/common.pgo.runtime.props new file mode 100644 index 00000000000..55c8091ed2a --- /dev/null +++ b/src/common.pgo.runtime.props @@ -0,0 +1,28 @@ + + + + + $(Platform) + x86 + x64 + x64 + x64 + $(VCToolsInstallDir)bin\Host$(PlatformShortName)\$(PlatformShortName) + $(VCToolsInstallDir)bin\$(PlatformShortName) + + + + + %(Filename)%(Extension) + PreserveNewest + + + %(Filename)%(Extension) + PreserveNewest + + + %(Filename)%(Extension) + PreserveNewest + + + \ No newline at end of file diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj index c43679ab67a..7c26324266e 100644 --- a/src/host/exe/Host.EXE.vcxproj +++ b/src/host/exe/Host.EXE.vcxproj @@ -9,6 +9,8 @@ Application + + @@ -89,6 +91,7 @@ WinMM.Lib;%(AdditionalDependencies) + \ No newline at end of file diff --git a/tools/NugetWrapper.cmd b/tools/NugetWrapper.cmd new file mode 100644 index 00000000000..da2868bf1a1 --- /dev/null +++ b/tools/NugetWrapper.cmd @@ -0,0 +1,26 @@ +@echo OFF +setlocal + +:: From our friends at Microsoft-UI-XAML +:: https://github.com/microsoft/microsoft-ui-xaml/blob/main/tools/NugetWrapper.cmd + +if "%VisualStudioVersion%" == "" set VisualStudioVersion=15.0 + +if defined NUGETEXETOOLPATH goto :AzurePipelines + +if not exist %TEMP%\nuget.5.2.0.exe ( + echo Nuget.exe not found in the temp dir, downloading. + powershell -Command "& { Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/v5.2.0/nuget.exe -outfile $env:TEMP\nuget.5.2.0.exe }" +) + +%TEMP%\nuget.5.2.0.exe %* + +exit /B %ERRORLEVEL% + + + +:AzurePipelines +echo NUGETEXETOOLPATH = %NUGETEXETOOLPATH% + +%NUGETEXETOOLPATH% %* +exit /B %ERRORLEVEL% \ No newline at end of file diff --git a/tools/PGODatabase/NuSpecs/PGO.nuspec.template b/tools/PGODatabase/NuSpecs/PGO.nuspec.template new file mode 100644 index 00000000000..32bf2daaa09 --- /dev/null +++ b/tools/PGODatabase/NuSpecs/PGO.nuspec.template @@ -0,0 +1,21 @@ + + + + $id + $version + PGO Database + Microsoft + Microsoft + false + PGO Database + Initial release + Copyright 2021 + + + + + + + + + \ No newline at end of file diff --git a/tools/PGODatabase/NuSpecs/build/PGO.targets b/tools/PGODatabase/NuSpecs/build/PGO.targets new file mode 100644 index 00000000000..10d996c2707 --- /dev/null +++ b/tools/PGODatabase/NuSpecs/build/PGO.targets @@ -0,0 +1,15 @@ + + + + + $(MSBuildThisFileDirectory)..\tools\$(PlatformShortName)\WindowsTerminal.pgd + + + + + PGUpdate + $(ProfileGuidedDatabaseFileName) + /force:pgorepro %(AdditionalOptions) + + + \ No newline at end of file diff --git a/tools/PGODatabase/PGO.version.props.template b/tools/PGODatabase/PGO.version.props.template new file mode 100644 index 00000000000..3af39b85c32 --- /dev/null +++ b/tools/PGODatabase/PGO.version.props.template @@ -0,0 +1,8 @@ + + + + + $id + $version + + \ No newline at end of file diff --git a/tools/PGODatabase/config.ps1 b/tools/PGODatabase/config.ps1 new file mode 100644 index 00000000000..a4974b39784 --- /dev/null +++ b/tools/PGODatabase/config.ps1 @@ -0,0 +1,7 @@ +$pgoBranch = "main" +$packageId = "Microsoft.Internal.Windows.Terminal.PGODatabase" + +# Get release version +[xml] $customProps = ( Get-Content "..\..\custom.props" ) +$releaseVersionMajor = ( [int]::Parse( $customProps.GetElementsByTagName("VersionMajor").'#text' ) ) +$releaseVersionMinor = ( [int]::Parse( $customProps.GetElementsByTagName("VersionMinor").'#text' ) ) \ No newline at end of file diff --git a/tools/PGODatabase/generate-nuspec.ps1 b/tools/PGODatabase/generate-nuspec.ps1 new file mode 100644 index 00000000000..d382e5c40a5 --- /dev/null +++ b/tools/PGODatabase/generate-nuspec.ps1 @@ -0,0 +1,11 @@ +Param( + [Parameter(Mandatory = $true, Position = 1)] [string] $templatePath, + [Parameter(Mandatory = $true, Position = 2)] [string] $outputPath) + +. .\version.ps1 +. .\template.ps1 +. .\config.ps1 + +$version = FormatVersion ( MakeVersion $releaseVersionMajor $releaseVersionMinor ( GetDatetimeStamp $pgoBranch ) ) +Write-Host ( "PGO INSTRUMENT: generating {0} version {1}" -f $packageId, $version ) +FillOut-Template $templatePath $outputPath @{ "version" = $version; "id" = $packageId } \ No newline at end of file diff --git a/tools/PGODatabase/readme.md b/tools/PGODatabase/readme.md new file mode 100644 index 00000000000..c06300f36fa --- /dev/null +++ b/tools/PGODatabase/readme.md @@ -0,0 +1,49 @@ +# Profile Guided Optimization + +**NOTE: All PGO work builds on work from Microsoft/Microsoft-UI-XAML** + +## Description + +We generate PGO database NuGet package which is versioned based on product release version and branch name/time stamp of the code that was used for instrumentation and training. In CI/release builds an initialization step enumerates all available versions, filters out those for other releases and branches. Given a list of applicable versions, it will find the one that is closest (BEFORE) the time-stamp of the last commit or a fork-point from instrumented branch. That package version will be installed and version references will be updated. The PGO branch is determined by variable $pgoBranch in tools/MUXPGODatabase/config.ps1. It will need to be updated if a forked branch should be PGO'd. + +## Scenarios + +For the purpose of illustration, let’s assume the following is a chronological list of check-ins to two branches (main and release/2.4). Some of them have had instrumentation/training run done on them and have generated PGO NuGets (version numbers in parentheses). To simplify, let’s assume that release major and minor versions are the same for all check-in as they merely act as filters for what versions are considered to be available. + + 1b27fd5f -- main -- + 7b303f74 -- main -- + 930ff585 -- main -- 2.4.2001312227-main + 63948a75 -- main -- + 0d379b51 -- main -- + f23f1fad -- main -- 2.4.2001312205-main + bcf9adaa -- main -- + 6ef44a23 -- main -- + 310bc133 -- release/2.4 -- + 80a4ab55 -- release/2.4 -- 2.4.2001312054-release_2_4 + 18b956f6 -- release/2.4 -- + 4abd4d54 -- main -- 2.4.2001312033-main + d150eae0 -- main -- 2.4.2001312028-main + +### Optimizing on PGO’d branch + +If we are building on main (which in this example is PGO’d), the version picked will be the one that has the same major and minor versions AND branch name and is the same or is right before the SHA being built. + +E.g. + + 1b27fd5f -- 2.4.2001312227-main + f23f1fad -- 2.4.2001312205-main + bcf9adaa -- 2.4.2001312033-main + +### Optimizing release branch + +A branch which will be PGO’d requires a slightly different handling. Let’s say release/2.4 forked from main on commit 4abd4d54. Initially, it will be configured to track main and 18b956f6 will be optimized with 2.4.2001312033-main. When the configuration is changed to start tracking release/2.4 (change branch name $pgoBranch in tools/MUXPGODatabase/config.ps1 script), it will start tracking its own branch. + +E.g. + + 18b956f6 -- if tracking main -> 2.4.2001312033-main, + if tracking release/2.4 -> ERROR (no database exists) + 310bc133 -- 2.4.2001312054-release_2_4 + +### Optimizing topic branch + +Assuming topic branch will not have a training run done, it can still use database from branch it was forked from. Let’s say we have a branch which was forked from main on 4abd4d54. If we don’t change which branch it’s tracking, it will keep using 2.4.2001312033-main. Merging main on f23f1fad into topic branch, will change used database to 2.4.2001312205-main. diff --git a/tools/PGODatabase/restore-pgodb.ps1 b/tools/PGODatabase/restore-pgodb.ps1 new file mode 100644 index 00000000000..46e5fb8cc4d --- /dev/null +++ b/tools/PGODatabase/restore-pgodb.ps1 @@ -0,0 +1,47 @@ +. .\version.ps1 +. .\template.ps1 +. .\config.ps1 + +$feedUri = "https://pkgs.dev.azure.com/ms/terminal/_packaging/TerminalDependencies/nuget/v2" + +$currentVersion = MakeVersion $releaseVersionMajor $releaseVersionMinor ( GetDatetimeStamp $pgoBranch ) + +Write-Host ( "PGO OPTIMIZE: requesting {0} version {1}" -f $packageId, ( FormatVersion $currentVersion ) ) + +$packageSource = Register-PackageSource -ForceBootstrap -Name MUX_Dependencies -Location $feedUri -ProviderName NuGet -Trusted +$packages = ( Find-Package $packageId -Source MUX_Dependencies -AllowPrereleaseVersions -AllVersions ) | Sort-Object -Property Version -Descending + +$best = $null + +foreach ( $existing in $packages ) +{ + $existingVersion = MakeVersionFromString $existing.Version + + if ( ( CompareBranches $existingVersion $currentVersion ) -eq $False -or + ( CompareReleases $existingVersion $currentVersion ) -ne 0 ) + { + # If this is different release or branch, then skip it. + continue + } + + if ( ( CompareRevisions $existingVersion $currentVersion ) -le 0 ) + { + # Version are sorted in descending order, the first one less than or equal to the current is the one we want. + # NOTE: at this point the only difference between versions will be revision (date-time stamp) + # which is formatted as a fixed-length string, so string comparison WILL sort it correctly. + $best = $existing + break + } +} + +if ( $best -eq $null ) +{ + throw "Appropriate database cannot be found" +} + +Write-Host ( "PGO OPTIMIZE: picked {0} version {1}" -f $packageId, $best.Version ) + +$best | Install-Package -Destination ..\..\packages -Force +$packageSource | Unregister-PackageSource + +FillOut-Template "PGO.version.props.template" "PGO.version.props" @{ "version" = $best.Version; "id" = $packageId } \ No newline at end of file diff --git a/tools/PGODatabase/template.ps1 b/tools/PGODatabase/template.ps1 new file mode 100644 index 00000000000..217f0037a3e --- /dev/null +++ b/tools/PGODatabase/template.ps1 @@ -0,0 +1,16 @@ +function Replace-Many ( $string, $dictionary ) +{ + foreach ( $key in $dictionary.Keys ) + { + $field = '$' + $key.ToString() + $string = $string.Replace( $field, $dictionary[$key].ToString() ) + } + + return $string +} + +function FillOut-Template ( $inputPath, $outputPath, $dictionary ) +{ + $replaced = Replace-Many ( Get-Content $inputPath ) $dictionary + Write-Output $replaced | Set-Content $outputPath -Force | Out-Null +} \ No newline at end of file diff --git a/tools/PGODatabase/version.ps1 b/tools/PGODatabase/version.ps1 new file mode 100644 index 00000000000..c6fb8f677af --- /dev/null +++ b/tools/PGODatabase/version.ps1 @@ -0,0 +1,75 @@ +function MakeVersion ( $major, $minor, $datetimeStamp ) +{ + $revision, $branch = $datetimeStamp.Split("-") + + if ( $branch -eq $null ) + { + $branch = "" + } + + return [PSCustomObject] @{ + Major = $major + Minor = $minor + Revision = $revision + Branch = $branch + } +} + +function MakeVersionFromString ( $str ) +{ + $parts = $str.Split(".") + return MakeVersion ( [int]::Parse($parts[0]) ) ( [int]::Parse($parts[1]) ) $parts[2] +} + +function FormatVersion ( $version ) +{ + $branch = "" + + if ( $version.Branch -ne "" ) + { + $branch = "-{0}" -f $version.Branch + } + + return "{0}.{1}.{2}{3}" -f $version.Major, $version.Minor, $version.Revision, $branch +} + +function CompareReleases ( $version1, $version2 ) +{ + $cmpMajor = [Math]::Sign($version1.Major - $version2.Major) + + if ( $cmpMajor -ne 0 ) + { + return $cmpMajor + } + + return [Math]::Sign($version1.Minor - $version2.Minor) +} + +function CompareRevisions ( $version1, $version2 ) +{ + return [Math]::Sign($version1.Revision - $version2.Revision) +} + +function CompareBranches ( $version1, $version2 ) +{ + return $version1.Branch -eq $version2.Branch +} + +function GetDatetimeStamp ( $pgoBranch ) +{ + $forkSHA = $( git merge-base origin/$pgoBranch HEAD ) + + if ( $LastExitCode -ne 0 ) + { + throw "FAILED: git merge-base" + } + + $forkDate = ( Get-Date -Date $( git log -1 $forkSHA --date=iso --pretty=format:"%ad" ) ).ToUniversalTime().ToString("yyMMddHHmm") + + if ( $LastExitCode -ne 0 ) + { + throw "FAILED: Get forkDate" + } + + return $forkDate + "-" + $pgoBranch.Replace("/", "_").Replace("-", "_").Replace(".", "_") +} \ No newline at end of file From ec6baa170d7fd713516b55c9e7599f85028f1793 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 5 May 2021 15:41:44 -0700 Subject: [PATCH 02/41] Update notices. Add WT UIA test project built from conhost test project. Add smoke test to project to just launch the app. --- NOTICE.md | 16 + OpenConsole.sln | 54 ++ .../templates/helix-runtests-job.yml | 4 +- .../Common/Globals.cs | 27 + .../Common/NativeMethods.cs | 861 ++++++++++++++++++ .../Elements/TerminalApp.cs | 158 ++++ src/cascadia/WindowsTerminal_UIATests/Init.cs | 46 + .../WindowsTerminal_UIATests/SmokeTests.cs | 32 + .../WindowsTerminal.UIA.Tests.csproj | 130 +++ .../WindowsTerminal_UIATests/app.config | 15 + .../WindowsTerminal_UIATests/packages.config | 9 + 11 files changed, 1350 insertions(+), 2 deletions(-) create mode 100644 src/cascadia/WindowsTerminal_UIATests/Common/Globals.cs create mode 100644 src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs create mode 100644 src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs create mode 100644 src/cascadia/WindowsTerminal_UIATests/Init.cs create mode 100644 src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs create mode 100644 src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj create mode 100644 src/cascadia/WindowsTerminal_UIATests/app.config create mode 100644 src/cascadia/WindowsTerminal_UIATests/packages.config diff --git a/NOTICE.md b/NOTICE.md index ccff11e177e..44e0f66629c 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -252,10 +252,26 @@ DEALINGS IN THE SOFTWARE. ``` +# Microsoft Open Source + +This product also incorporates source code from other Microsoft open source projects, all licensed under the MIT license. + +## `GSL` + +**Source**: [https://github.com/microsoft/GSL](https://github.com/microsoft/GSL) + +## `Microsoft-UI-XAML` + +**Source**: [https://github.com/microsoft/Microsoft-UI-XAML](https://github.com/microsoft/Microsoft-UI-XAML) + ## `VirtualDesktopUtils` **Source**: [https://github.com/microsoft/PowerToys](https://github.com/microsoft/PowerToys) +## `wil` + +**Source**: [https://github.com/microsoft/wil](https://github.com/microsoft/wil) + ### License ``` diff --git a/OpenConsole.sln b/OpenConsole.sln index 2b644ae98a8..3d2dde08d04 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -395,6 +395,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Control", "src\ca {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests", "src\cascadia\WindowsTerminal_UIATests\WindowsTerminal.UIA.Tests.csproj", "{F19DACD5-0C6E-40DC-B6E4-767A3200542C}" + ProjectSection(ProjectDependencies) = postProject + {CA5CAD1A-224A-4171-B13A-F16E576FDD12} = {CA5CAD1A-224A-4171-B13A-F16E576FDD12} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AuditMode|Any CPU = AuditMode|Any CPU @@ -3256,6 +3261,54 @@ Global {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x64.Build.0 = Release|x64 {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.ActiveCfg = Release|Win32 {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.Build.0 = Release|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|Any CPU.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|Any CPU.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM64.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM64.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x64Test.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x64Test.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x86Test.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x86Test.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x64.ActiveCfg = Debug|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x64.Build.0 = Debug|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x86.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x86.Build.0 = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM64.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x64.ActiveCfg = Debug|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x64.Build.0 = Debug|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x86.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x86.Build.0 = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|Any CPU.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|Any CPU.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM64.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x64Test.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x64Test.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x86Test.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x64.ActiveCfg = Debug|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x64.Build.0 = Debug|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x86.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x86.Build.0 = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|Any CPU.ActiveCfg = Release|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM.ActiveCfg = Release|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM64.ActiveCfg = Release|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM64.Build.0 = Release|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.ActiveCfg = Release|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.Build.0 = Release|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.ActiveCfg = Release|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3353,6 +3406,7 @@ Global {9921CA0A-320C-4460-8623-3A3196E7F4CB} = {59840756-302F-44DF-AA47-441A9D673202} {05D9052F-D78F-478F-968A-2DE38A6DB996} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB} {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} + {F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271} diff --git a/build/pipelines/templates/helix-runtests-job.yml b/build/pipelines/templates/helix-runtests-job.yml index 39f3592f178..5cd059da716 100644 --- a/build/pipelines/templates/helix-runtests-job.yml +++ b/build/pipelines/templates/helix-runtests-job.yml @@ -125,8 +125,8 @@ jobs: - template: helix-createprojfile-steps.yml parameters: condition: and(succeeded(),eq('${{ parameters.testSuite }}','PgoInstrumentationSuite')) - testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\TerminalApp.PGO.Tests.dll' - outputProjFileName: 'RunTestsInHelix-TerminalAppPGOTests.proj' + testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\WindowsTerminal.UIA.Tests.dll' + outputProjFileName: 'RunTestsInHelix-WindowsTerminalUIATests.proj' testSuite: '${{ parameters.testSuite }}' taefQuery: ${{ parameters.taefQuery }} diff --git a/src/cascadia/WindowsTerminal_UIATests/Common/Globals.cs b/src/cascadia/WindowsTerminal_UIATests/Common/Globals.cs new file mode 100644 index 00000000000..8a47ab90248 --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/Common/Globals.cs @@ -0,0 +1,27 @@ +//---------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Windows Terminal UI Automation global settings +//---------------------------------------------------------------------------------------------------------------------- +namespace WindowsTerminal.UIA.Tests.Common +{ + using System; + + public static class Globals + { + public const int Timeout = 50; // in milliseconds + public const int LongTimeout = 5000; // in milliseconds + public const int AppCreateTimeout = 3000; // in milliseconds + + public static void WaitForTimeout() + { + System.Threading.Thread.Sleep(Globals.Timeout); + } + + public static void WaitForLongTimeout() + { + System.Threading.Thread.Sleep(Globals.LongTimeout); + } + } +} diff --git a/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs b/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs new file mode 100644 index 00000000000..e465ae0b1e3 --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs @@ -0,0 +1,861 @@ +//---------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Wrapper class for storing P/Invoke and COM Interop definitions. +//---------------------------------------------------------------------------------------------------------------------- + +namespace WindowsTerminal.UIA.Tests.Common.NativeMethods +{ + using System; + using System.Drawing; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Text; + + using Microsoft.Win32; + using WEX.TestExecution; + using WEX.Logging.Interop; + + // Small extension method helpers to make C# feel closer to native. + public static class NativeExtensions + { + public static int LoWord(this int val) + { + return val & 0xffff; + } + + public static int HiWord(this int val) + { + return (val >> 16) & 0xffff; + } + } + + public static class NativeMethods + { + public static void Win32BoolHelper(bool result, string actionMessage) + { + if (!result) + { + string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error()); + Log.Comment(errorMsg); + } + + Verify.IsTrue(result, actionMessage); + } + + public static void Win32NullHelper(IntPtr result, string actionMessage) + { + if (result == IntPtr.Zero) + { + string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error()); + Log.Comment(errorMsg); + } + + Verify.IsNotNull(result, actionMessage); + } + } + + public static class WinCon + { + [Flags()] + public enum CONSOLE_SELECTION_INFO_FLAGS : uint + { + CONSOLE_NO_SELECTION = 0x0, + CONSOLE_SELECTION_IN_PROGRESS = 0x1, + CONSOLE_SELECTION_NOT_EMPTY = 0x2, + CONSOLE_MOUSE_SELECTION = 0x4, + CONSOLE_MOUSE_DOWN = 0x8 + } + + public enum CONSOLE_STD_HANDLE : int + { + STD_INPUT_HANDLE = -10, + STD_OUTPUT_HANDLE = -11, + STD_ERROR_HANDLE = -12 + } + + public enum CONSOLE_ATTRIBUTES : ushort + { + FOREGROUND_BLUE = 0x1, + FOREGROUND_GREEN = 0x2, + FOREGROUND_RED = 0x4, + FOREGROUND_INTENSITY = 0x8, + FOREGROUND_YELLOW = FOREGROUND_RED | FOREGROUND_GREEN, + FOREGROUND_CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE, + FOREGROUND_MAGENTA = FOREGROUND_RED | FOREGROUND_BLUE, + FOREGROUND_COLORS = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, + FOREGROUND_ALL = FOREGROUND_COLORS | FOREGROUND_INTENSITY, + BACKGROUND_BLUE = 0x10, + BACKGROUND_GREEN = 0x20, + BACKGROUND_RED = 0x40, + BACKGROUND_INTENSITY = 0x80, + BACKGROUND_YELLOW = BACKGROUND_RED | BACKGROUND_GREEN, + BACKGROUND_CYAN = BACKGROUND_GREEN | BACKGROUND_BLUE, + BACKGROUND_MAGENTA = BACKGROUND_RED | BACKGROUND_BLUE, + BACKGROUND_COLORS = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN, + BACKGROUND_ALL = BACKGROUND_COLORS | BACKGROUND_INTENSITY, + COMMON_LVB_LEADING_BYTE = 0x100, + COMMON_LVB_TRAILING_BYTE = 0x200, + COMMON_LVB_GRID_HORIZONTAL = 0x400, + COMMON_LVB_GRID_LVERTICAL = 0x800, + COMMON_LVB_GRID_RVERTICAL = 0x1000, + COMMON_LVB_REVERSE_VIDEO = 0x4000, + COMMON_LVB_UNDERSCORE = 0x8000 + } + + public enum CONSOLE_OUTPUT_MODES : uint + { + ENABLE_PROCESSED_OUTPUT = 0x1, + ENABLE_WRAP_AT_EOL_OUTPUT = 0x2, + ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4 + } + + //CHAR_INFO struct, which was a union in the old days + // so we want to use LayoutKind.Explicit to mimic it as closely + // as we can + [StructLayout(LayoutKind.Explicit)] + public struct CHAR_INFO + { + [FieldOffset(0)] + internal char UnicodeChar; + [FieldOffset(0)] + internal char AsciiChar; + [FieldOffset(2)] //2 bytes seems to work properly + internal CONSOLE_ATTRIBUTES Attributes; + } + + [StructLayout(LayoutKind.Sequential)] + public struct COORD + { + public short X; + public short Y; + + public override string ToString() + { + return string.Format("(X:{0} Y:{1})", X, Y); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct SMALL_RECT + { + public short Left; + public short Top; + public short Right; + public short Bottom; + + public short Width + { + get + { + // The API returns bottom/right as the inclusive lower-right + // corner, so we need +1 for the true width + return (short)(this.Right - this.Left + 1); + } + } + + public short Height + { + get + { + // The API returns bottom/right as the inclusive lower-right + // corner, so we need +1 for the true height + return (short)(this.Bottom - this.Top + 1); + } + } + + public override string ToString() + { + return string.Format("(L:{0} T:{1} R:{2} B:{3})", Left, Top, Right, Bottom); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_CURSOR_INFO + { + public uint dwSize; + public bool bVisible; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_FONT_INFO + { + public int nFont; + public COORD dwFontSize; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_SELECTION_INFO + { + public CONSOLE_SELECTION_INFO_FLAGS Flags; + public COORD SelectionAnchor; + public SMALL_RECT Selection; + + public override string ToString() + { + return string.Format("Flags:{0:X} Anchor:{1} Selection:{2}", Flags, SelectionAnchor, Selection); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_SCREEN_BUFFER_INFO + { + public COORD dwSize; + public COORD dwCursorPosition; + public CONSOLE_ATTRIBUTES wAttributes; + public SMALL_RECT srWindow; + public COORD dwMaximumWindowSize; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_SCREEN_BUFFER_INFO_EX + { + public uint cbSize; + public COORD dwSize; + public COORD dwCursorPosition; + public CONSOLE_ATTRIBUTES wAttributes; + public SMALL_RECT srWindow; + public COORD dwMaximumWindowSize; + + public CONSOLE_ATTRIBUTES wPopupAttributes; + public bool bFullscreenSupported; + + internal COLORREF black; + internal COLORREF darkBlue; + internal COLORREF darkGreen; + internal COLORREF darkCyan; + internal COLORREF darkRed; + internal COLORREF darkMagenta; + internal COLORREF darkYellow; + internal COLORREF gray; + internal COLORREF darkGray; + internal COLORREF blue; + internal COLORREF green; + internal COLORREF cyan; + internal COLORREF red; + internal COLORREF magenta; + internal COLORREF yellow; + internal COLORREF white; + } + + [StructLayout(LayoutKind.Sequential)] + public struct COLORREF + { + internal uint ColorDWORD; + + public COLORREF(Color color) + { + ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16); + } + + public COLORREF(uint r, uint g, uint b) + { + ColorDWORD = r + (g << 8) + (b << 16); + } + + public Color GetColor() + { + return Color.FromArgb((int)(0x000000FFU & ColorDWORD), + (int)(0x0000FF00U & ColorDWORD) >> 8, (int)(0x00FF0000U & ColorDWORD) >> 16); + } + + public void SetColor(Color color) + { + ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16); + } + } + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GetStdHandle(CONSOLE_STD_HANDLE nStdHandle); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool AttachConsole(UInt32 dwProcessId); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool FreeConsole(); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern bool SetConsoleTitle(string ConsoleTitle); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleMode(IntPtr hConsoleOutputHandle, out CONSOLE_OUTPUT_MODES lpMode); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern uint GetConsoleTitle(StringBuilder lpConsoleTitle, int nSize); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GetConsoleWindow(); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleSelectionInfo(out CONSOLE_SELECTION_INFO lpConsoleSelectionInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool bAbsolute, [In] ref SMALL_RECT lpConsoleWindow); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleCursorInfo(IntPtr hConsoleOutput, out CONSOLE_CURSOR_INFO lpConsoleCursorInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool SetConsoleScreenBufferInfoEx(IntPtr ConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfoEx); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetCurrentConsoleFont(IntPtr hConsoleOutput, bool bMaximumWindow, out CONSOLE_FONT_INFO lpConsoleCurrentFont); + + [DllImport("kernel32.dll", EntryPoint = "ReadConsoleOutputW", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool ReadConsoleOutput( + IntPtr hConsoleOutput, + /* This pointer is treated as the origin of a two-dimensional array of CHAR_INFO structures + whose size is specified by the dwBufferSize parameter.*/ + [MarshalAs(UnmanagedType.LPArray), Out] CHAR_INFO[,] lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + ref SMALL_RECT lpReadRegion); + + [DllImport("kernel32.dll", EntryPoint = "WriteConsoleOutputCharacterW", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool WriteConsoleOutputCharacter( + IntPtr hConsoleOutput, + string lpCharacter, + UInt32 nLength, + COORD dwWriteCoord, + ref UInt32 lpNumberOfCharsWritten); + + } + + /// + /// The definitions within this file match the winconp.h file that is generated from wincon.w + /// Please see /windows/published/main/wincon.w + /// + public static class WinConP + { + private static readonly Guid PKEY_Console_FormatId = new Guid(0x0C570607, 0x0396, 0x43DE, new byte[] { 0x9D, 0x61, 0xE3, 0x21, 0xD7, 0xDF, 0x50, 0x26 }); + + public static readonly Wtypes.PROPERTYKEY PKEY_Console_ForceV2 = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 1 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_WrapText = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 2 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_FilterOnPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 3 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_CtrlKeysDisabled = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 4 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_LineSelection = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 5 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_WindowTransparency = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 6 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_TrimZeros = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 7 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorType = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 8 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorColor = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 9 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_InterceptCopyPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 10 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultForeground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 11 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultBackground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 12 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_TerminalScrolling = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 13 }; + + public static readonly uint NT_CONSOLE_PROPS_SIG = 0xA0000002; + public static readonly uint NT_FE_CONSOLE_PROPS_SIG = 0xA0000004; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct NT_CONSOLE_PROPS + { + public Shell32.DATABLOCK_HEADER dbh; + public short wFillAttribute; + public short wPopupFillAttribute; + public WinCon.COORD dwScreenBufferSize; + public WinCon.COORD dwWindowSize; + public WinCon.COORD dwWindowOrigin; + public int nFont; + public int nInputBufferSize; + public WinCon.COORD dwFontSize; + public uint uFontFamily; + public uint uFontWeight; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string FaceName; + public uint uCursorSize; + public int bFullScreen; + public int bQuickEdit; + public int bInsertMode; + public int bAutoPosition; + public uint uHistoryBufferSize; + public uint uNumberOfHistoryBuffers; + public int bHistoryNoDup; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public int[] ColorTable; + public uint CursorType; + public WinCon.COLORREF CursorColor; + public bool InterceptCopyPaste; + public WinCon.COLORREF DefaultForeground; + public WinCon.COLORREF DefaultBackground; + public bool TerminalScrolling; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NT_FE_CONSOLE_PROPS + { + Shell32.DATABLOCK_HEADER dbh; + uint uCodePage; + } + } + + public static class User32 + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public Int32 left; + public Int32 top; + public Int32 right; + public Int32 bottom; + } + + [StructLayout(LayoutKind.Sequential)] + public struct POINT + { + public Int32 x; + public Int32 y; + } + + public const int WHEEL_DELTA = 120; + + [DllImport("user32.dll")] + public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); + + [DllImport("user32.dll")] + public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); + + public const int GWL_STYLE = (-16); + public const int GWL_EXSTYLE = (-20); + + [DllImport("user32.dll", SetLastError = true)] + public static extern int GetWindowLong(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll")] + public static extern bool AdjustWindowRectEx(ref RECT lpRect, int dwStyle, bool bMenu, int dwExStyle); + + [DllImport("user32.dll")] + public static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint); + + public enum WindowMessages : UInt32 + { + WM_KEYDOWN = 0x0100, + WM_KEYUP = 0x0101, + WM_CHAR = 0x0102, + WM_MOUSEWHEEL = 0x020A, + WM_MOUSEHWHEEL = 0x020E, + WM_USER = 0x0400, + CM_SET_KEY_STATE = WM_USER + 18 + } + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr SendMessage(IntPtr hWnd, WindowMessages Msg, Int32 wParam, IntPtr lParam); + + public enum SPI : uint + { + SPI_GETWHEELSCROLLLINES = 0x0068, + SPI_GETWHEELSCROLLCHARACTERS = 0x006C + } + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, ref uint pvParam, uint fWinIni); + + + public enum WinEventId : uint + { + EVENT_CONSOLE_CARET = 0x4001, + EVENT_CONSOLE_UPDATE_REGION = 0x4002, + EVENT_CONSOLE_UPDATE_SIMPLE = 0x4003, + EVENT_CONSOLE_UPDATE_SCROLL = 0x4004, + EVENT_CONSOLE_LAYOUT = 0x4005, + EVENT_CONSOLE_START_APPLICATION = 0x4006, + EVENT_CONSOLE_END_APPLICATION = 0x4007 + } + + [Flags] + public enum WinEventFlags : uint + { + WINEVENT_OUTOFCONTEXT = 0x0000, // Events are ASYNC + WINEVENT_SKIPOWNTHREAD = 0x0001, // Don't call back for events on installer's thread + WINEVENT_SKIPOWNPROCESS = 0x0002, // Don't call back for events on installer's process + WINEVENT_INCONTEXT = 0x0004, // Events are SYNC, this causes your dll to be injected into every process + } + + public delegate void WinEventDelegate(IntPtr hWinEventHook, WinEventId eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr SetWinEventHook(WinEventId eventMin, WinEventId eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, WinEventFlags dwFlags); + + [DllImport("user32.dll")] + public static extern bool UnhookWinEvent(IntPtr hWinEventHook); + + [DllImport("user32.dll", SetLastError = true)] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + + public struct MSG + { + public IntPtr hwnd; + public uint message; + public IntPtr wParam; + public IntPtr lParam; + public uint time; + public POINT pt; + } + + public enum PM : uint + { + PM_NOREMOVE = 0x0000, + PM_REMOVE = 0x0001, + PM_NOYIELD = 0x0002, + } + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PM wRemoveMsg); + + [DllImport("user32.dll", SetLastError = true)] + public static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr DispatchMessage(ref MSG lpmsg); + } + + public static class Shell32 + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773249(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + public struct DATABLOCK_HEADER + { + public int cbSize; + public int dwSignature; + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774944(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Enums/SLGP_FLAGS.html + /// IShellLink.GetPath fFlags: Flags that specify the type of path information to retrieve + [Flags()] + public enum SLGP_FLAGS + { + /// Retrieves the standard short (8.3 format) file name + SLGP_SHORTPATH = 0x1, + /// Retrieves the Universal Naming Convention (UNC) path name of the file + SLGP_UNCPRIORITY = 0x2, + /// Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded + SLGP_RAWPATH = 0x4 + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774952(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Enums/SLR_FLAGS.html + /// IShellLink.Resolve fFlags + [Flags()] + public enum SLR_FLAGS + { + /// + /// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set, + /// the high-order word of fFlags can be set to a time-out value that specifies the + /// maximum amount of time to be spent resolving the link. The function returns if the + /// link cannot be resolved within the time-out duration. If the high-order word is set + /// to zero, the time-out duration will be set to the default value of 3,000 milliseconds + /// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out + /// duration, in milliseconds. + /// + SLR_NO_UI = 0x1, + /// Obsolete and no longer used + SLR_ANY_MATCH = 0x2, + /// If the link object has changed, update its path and list of identifiers. + /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine + /// whether or not the link object has changed. + SLR_UPDATE = 0x4, + /// Do not update the link information + SLR_NOUPDATE = 0x8, + /// Do not execute the search heuristics + SLR_NOSEARCH = 0x10, + /// Do not use distributed link tracking + SLR_NOTRACK = 0x20, + /// Disable distributed link tracking. By default, distributed link tracking tracks + /// removable media across multiple devices based on the volume name. It also uses the + /// Universal Naming Convention (UNC) path to track remote file systems whose drive letter + /// has changed. Setting SLR_NOLINKINFO disables both types of tracking. + SLR_NOLINKINFO = 0x40, + /// Call the Microsoft Windows Installer + SLR_INVOKE_MSI = 0x80 + } + + [ComImport, Guid("00021401-0000-0000-C000-000000000046")] + public class ShellLink + { + // Making new of this class will call CoCreate e.g. new ShellLink(); + // Cast to one of the interfaces below will QueryInterface. e.g. (IPersistFile)new ShellLink(); + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774950(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Interfaces/IShellLinkW.html + /// The IShellLink interface allows Shell links to be created, modified, and resolved + [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")] + public interface IShellLinkW + { + /// Retrieves the path and file name of a Shell link object + void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WinBase.WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags); + /// Retrieves the list of item identifiers for a Shell link object + void GetIDList(out IntPtr ppidl); + /// Sets the pointer to an item identifier list (PIDL) for a Shell link object. + void SetIDList(IntPtr pidl); + /// Retrieves the description string for a Shell link object + void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); + /// Sets the description for a Shell link object. The description can be any application-defined string + void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); + /// Retrieves the name of the working directory for a Shell link object + void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); + /// Sets the name of the working directory for a Shell link object + void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); + /// Retrieves the command-line arguments associated with a Shell link object + void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); + /// Sets the command-line arguments for a Shell link object + void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); + /// Retrieves the hot key for a Shell link object + void GetHotkey(out short pwHotkey); + /// Sets a hot key for a Shell link object + void SetHotkey(short wHotkey); + /// Retrieves the show command for a Shell link object + void GetShowCmd(out int piShowCmd); + /// Sets the show command for a Shell link object. The show command sets the initial show state of the window. + void SetShowCmd(int iShowCmd); + /// Retrieves the location (path and index) of the icon for a Shell link object + void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, + int cchIconPath, out int piIcon); + /// Sets the location (path and index) of the icon for a Shell link object + void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); + /// Sets the relative path to the Shell link object + void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); + /// Attempts to find the target of a Shell link, even if it has been moved or renamed + void Resolve(IntPtr hwnd, SLR_FLAGS fFlags); + /// Sets the path and file name of a Shell link object + void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774916(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Interfaces/IShellLonkDataList.html + [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("45e2b4ae-b1c3-11d0-b92f-00a0c90312e1")] + public interface IShellLinkDataList + { + void AddDataBlock(IntPtr pDataBlock); + void CopyDataBlock(uint dwSig, out IntPtr ppDataBlock); + void RemoveDataBlock(uint dwSig); + void GetFlags(out uint pdwFlags); + void SetFlags(uint dwFlags); + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms688695(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Interfaces/IPersist.html + [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPersist + { + [PreserveSig] + void GetClassID(out Guid pClassID); + } + + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms687223(v=vs.85).aspx + // http://www.pinvoke.net/default.aspx/Interfaces/IPersistFile.html + [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPersistFile : IPersist + { + new void GetClassID(out Guid pClassID); + + [PreserveSig] + int IsDirty(); + + [PreserveSig] + void Load([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode); + + [PreserveSig] + void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, + [In, MarshalAs(UnmanagedType.Bool)] bool fRemember); + + [PreserveSig] + void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName); + + [PreserveSig] + void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName); + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb761474(v=vs.85).aspx + // http://www.pinvoke.net/default.aspx/Interfaces/IPropertyStore.html + [ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPropertyStore + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCount([Out] out uint cProps); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetAt([In] uint iProp, out Wtypes.PROPERTYKEY pkey); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetValue([In] ref Wtypes.PROPERTYKEY key, out object pv); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetValue([In] ref Wtypes.PROPERTYKEY key, [In] ref object pv); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Commit(); + } + } + + public static class WinBase + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365740(v=vs.85).aspx + // http://www.pinvoke.net/default.aspx/Structures/WIN32_FIND_DATA.html + // The CharSet must match the CharSet of the corresponding PInvoke signature + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct WIN32_FIND_DATAW + { + public uint dwFileAttributes; + public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime; + public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime; + public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime; + public uint nFileSizeHigh; + public uint nFileSizeLow; + public uint dwReserved0; + public uint dwReserved1; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string cFileName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] + public string cAlternateFileName; + } + + public enum STARTF : Int32 + { + STARTF_TITLEISLINKNAME = 0x00000800 + } + + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct STARTUPINFO + { + public Int32 cb; + public string lpReserved; + public string lpDesktop; + public string lpTitle; + public Int32 dwX; + public Int32 dwY; + public Int32 dwXSize; + public Int32 dwYSize; + public Int32 dwXCountChars; + public Int32 dwYCountChars; + public Int32 dwFillAttribute; + public STARTF dwFlags; + public Int16 wShowWindow; + public Int16 cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PROCESS_INFORMATION + { + public IntPtr hProcess; + public IntPtr hThread; + public int dwProcessId; + public int dwThreadId; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct STARTUPINFOEX + { + public STARTUPINFO StartupInfo; + public IntPtr lpAttributeList; + } + + [Flags] + public enum CP_CreationFlags : uint + { + CREATE_SUSPENDED = 0x4, + CREATE_NEW_CONSOLE = 0x10, + } + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern bool CreateProcess(string lpApplicationName, + string lpCommandLine, + IntPtr lpProcessAttributes, + IntPtr lpThreadAttributes, + bool bInheritHandles, + CP_CreationFlags dwCreationFlags, + IntPtr lpEnvironment, + string lpCurrentDirectory, + [In] ref STARTUPINFO lpStartupInfo, + out PROCESS_INFORMATION lpProcessInformation); + + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, IntPtr lpName); + + [DllImport("kernel32.dll")] + public static extern bool TerminateJobObject(IntPtr hJob, uint uExitCode); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern int ResumeThread(IntPtr hThread); + + public enum JOBOBJECTINFOCLASS : uint + { + JobObjectBasicProcessIdList = 3 + } + + [StructLayout(LayoutKind.Sequential)] + public struct JOBOBJECT_BASIC_PROCESS_ID_LIST + { + public uint NumberOfAssignedProcesses; + public uint NumberOfProcessIdsInList; + public IntPtr ProcessId; + public IntPtr ProcessId2; + } + + [DllImport("kernel32.dll")] + public static extern bool QueryInformationJobObject(IntPtr hJob, + JOBOBJECTINFOCLASS JobObjectInformationClass, + IntPtr lpJobObjectInfo, + int cbJobObjectInfoLength, + IntPtr lpReturnLength); + } + + public static class Wtypes + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773381(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Structures/PROPERTYKEY.html + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct PROPERTYKEY + { + public Guid fmtid; + public uint pid; + } + } + + public static class ObjBase + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380337(v=vs.85).aspx + // http://www.pinvoke.net/default.aspx/Enums/StgmConstants.html + [Flags] + public enum STGM + { + STGM_READ = 0x0, + STGM_WRITE = 0x1, + STGM_READWRITE = 0x2, + STGM_SHARE_DENY_NONE = 0x40, + STGM_SHARE_DENY_READ = 0x30, + STGM_SHARE_DENY_WRITE = 0x20, + STGM_SHARE_EXCLUSIVE = 0x10, + STGM_PRIORITY = 0x40000, + STGM_CREATE = 0x1000, + STGM_CONVERT = 0x20000, + STGM_FAILIFTHERE = 0x0, + STGM_DIRECT = 0x0, + STGM_TRANSACTED = 0x10000, + STGM_NOSCRATCH = 0x100000, + STGM_NOSNAPSHOT = 0x200000, + STGM_SIMPLE = 0x8000000, + STGM_DIRECT_SWMR = 0x400000, + STGM_DELETEONRELEASE = 0x4000000 + } + } +} diff --git a/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs b/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs new file mode 100644 index 00000000000..5829c36d058 --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs @@ -0,0 +1,158 @@ +//---------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Helper and wrapper for generating the base test application and its UI Root node. +//---------------------------------------------------------------------------------------------------------------------- +namespace WindowsTerminal.UIA.Tests.Elements +{ + using System; + using System.IO; + + using WindowsTerminal.UIA.Tests.Common; + using WindowsTerminal.UIA.Tests.Common.NativeMethods; + + using OpenQA.Selenium.Remote; + using OpenQA.Selenium.Appium; + using OpenQA.Selenium.Appium.iOS; + using OpenQA.Selenium.Interactions; + + using WEX.Logging.Interop; + using WEX.TestExecution; + using WEX.TestExecution.Markup; + + using System.Runtime.InteropServices; + using System.Security.Principal; + + public class TerminalApp : IDisposable + { + private static readonly string binPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "cmd.exe"); + private static readonly string linkPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + @"Microsoft\Windows\Start Menu\Programs\System Tools\Command Prompt.lnk"); + + protected const string AppDriverUrl = "http://127.0.0.1:4723"; + + private IntPtr job; + + public IOSDriver Session { get; private set; } + public Actions Actions { get; private set; } + public AppiumWebElement UIRoot { get; private set; } + + private bool isDisposed = false; + + private TestContext context; + + public TerminalApp(TestContext context) + { + this.context = context; + + string path = Path.GetFullPath(Path.Combine(context.TestDeploymentDir, @"..\..\..\src\cascadia\CascadiaPackage\bin\x64\debug\Appx\WindowsTerminal.exe")); + if (context.Properties.Contains("WTPath")) + { + path = (string)context.Properties["WTPath"]; + } + + this.CreateProcess(path); + } + + ~TerminalApp() + { + this.Dispose(false); + } + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + public AppiumWebElement GetRoot() + { + return this.UIRoot; + } + + protected virtual void Dispose(bool disposing) + { + if (!this.isDisposed) + { + // ensure we're exited when this is destroyed or disposed of explicitly + this.ExitProcess(); + + this.isDisposed = true; + } + } + + private void CreateProcess(string path) + { + string WindowTitleToFind = "WindowsTerminal.UIA.Tests"; + + job = WinBase.CreateJobObject(IntPtr.Zero, IntPtr.Zero); + NativeMethods.Win32NullHelper(job, "Creating job object to hold binaries under test."); + + Log.Comment("Attempting to launch command-line application at '{0}'", path); + + string binaryToRunPath = path; + string args = $"new-tab --title \"{WindowTitleToFind}\" --suppressApplicationTitle"; + + string launchArgs = $"{binaryToRunPath} {args}"; + + WinBase.STARTUPINFO si = new WinBase.STARTUPINFO(); + si.cb = Marshal.SizeOf(si); + + WinBase.PROCESS_INFORMATION pi = new WinBase.PROCESS_INFORMATION(); + + NativeMethods.Win32BoolHelper(WinBase.CreateProcess(null, + launchArgs, + IntPtr.Zero, + IntPtr.Zero, + false, + WinBase.CP_CreationFlags.CREATE_SUSPENDED, + IntPtr.Zero, + null, + ref si, + out pi), + "Attempting to create child host window process."); + + Log.Comment($"Host window PID: {pi.dwProcessId}"); + + NativeMethods.Win32BoolHelper(WinBase.AssignProcessToJobObject(job, pi.hProcess), "Assigning new host window (suspended) to job object."); + NativeMethods.Win32BoolHelper(-1 != WinBase.ResumeThread(pi.hThread), "Resume host window process now that it is attached and its launch of the child application will be caught in the job object."); + + Globals.WaitForTimeout(); + + DesiredCapabilities appCapabilities = new DesiredCapabilities(); + appCapabilities.SetCapability("app", @"Root"); + Session = new IOSDriver(new Uri(AppDriverUrl), appCapabilities); + + Verify.IsNotNull(Session); + Actions = new Actions(Session); + Verify.IsNotNull(Session); + + Globals.WaitForLongTimeout(); + + UIRoot = Session.FindElementByName(WindowTitleToFind); + + // Set the timeout to 15 seconds after we found the initial window. + Session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(15); + } + + private bool IsRunningAsAdmin() + { + return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); + } + + private void ExitProcess() + { + // Release attachment to the child process console. + WinCon.FreeConsole(); + + this.UIRoot = null; + + if (this.job != IntPtr.Zero) + { + WinBase.TerminateJobObject(this.job, 0); + } + this.job = IntPtr.Zero; + } + } +} diff --git a/src/cascadia/WindowsTerminal_UIATests/Init.cs b/src/cascadia/WindowsTerminal_UIATests/Init.cs new file mode 100644 index 00000000000..80be6215654 --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/Init.cs @@ -0,0 +1,46 @@ +//---------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +//---------------------------------------------------------------------------------------------------------------------- + +using System; +using System.Diagnostics; +using System.IO; +using WEX.Logging.Interop; +using WEX.TestExecution.Markup; + +namespace Host.Tests.UIA +{ + [TestClass] + class Init + { + static Process appDriver; + + [AssemblyInitialize] + public static void SetupAll(TestContext context) + { + Log.Comment("Searching for WinAppDriver in the same directory where this test was launched from..."); + string winAppDriver = Path.Combine(context.TestDeploymentDir, "WinAppDriver.exe"); + + Log.Comment($"Attempting to launch WinAppDriver at: {winAppDriver}"); + Log.Comment($"Working directory: {Environment.CurrentDirectory}"); + + appDriver = Process.Start(winAppDriver); + } + + [AssemblyCleanup] + public static void CleanupAll() + { + try + { + appDriver.Kill(); + } + catch + { + + } + } + } +} diff --git a/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs b/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs new file mode 100644 index 00000000000..203725afe77 --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs @@ -0,0 +1,32 @@ +//---------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +// UI Automation tests for verifying the basic opening/closing of the Terminal. +//---------------------------------------------------------------------------------------------------------------------- + +namespace WindowsTerminal.UIA.Tests +{ + using WEX.TestExecution.Markup; + + using WindowsTerminal.UIA.Tests.Common; + using WindowsTerminal.UIA.Tests.Elements; + + [TestClass] + public class SmokeTests + { + public TestContext TestContext { get; set; } + + [TestMethod] + public void StartTerminal() + { + using (TerminalApp app = new TerminalApp(TestContext)) + { + var root = app.GetRoot(); + root.SendKeys("Hello smoke test!"); + Globals.WaitForLongTimeout(); + } + } + } +} diff --git a/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj new file mode 100644 index 00000000000..8a391cd450a --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj @@ -0,0 +1,130 @@ + + + + {F19DACD5-0C6E-40DC-B6E4-767A3200542C} + Library + Properties + WindowsTerminal.UIA.Tests + WindowsTerminal.UIA.Tests + v4.5 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + $(SolutionDir)\bin\$(Platform)\$(Configuration) + prompt + 4 + + + + + ARM64 + + + x64 + + + x86 + + + true + full + false + DEBUG;TRACE + + + pdbonly + true + TRACE + + + + ..\..\..\packages\Appium.WebDriver.3.0.0.2\lib\net45\appium-dotnet-driver.dll + + + ..\..\..\packages\Castle.Core.4.1.1\lib\net45\Castle.Core.dll + + + ..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + + + + ..\..\..\packages\Microsoft.Taef.10.58.210305002\lib\net45\TE.Managed.dll + + + ..\..\..\packages\Microsoft.Taef.10.58.210305002\lib\net45\TE.Model.Managed.dll + + + + + ..\..\..\packages\Selenium.WebDriver.3.5.0\lib\net40\WebDriver.dll + + + ..\..\..\packages\Selenium.Support.3.5.0\lib\net40\WebDriver.Support.dll + + + ..\..\..\packages\Microsoft.Taef.10.58.210305002\lib\net45\Wex.Common.Managed.dll + + + ..\..\..\packages\Microsoft.Taef.10.58.210305002\lib\net45\Wex.Logger.Interop.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + + + False + + + False + + + False + + + + + + + + copy $(SolutionDir)\dep\WinAppDriver\* $(OutDir)\ + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + diff --git a/src/cascadia/WindowsTerminal_UIATests/app.config b/src/cascadia/WindowsTerminal_UIATests/app.config new file mode 100644 index 00000000000..5d6775b6725 --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/cascadia/WindowsTerminal_UIATests/packages.config b/src/cascadia/WindowsTerminal_UIATests/packages.config new file mode 100644 index 00000000000..615b60fc23d --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file From 16d4b2281749a6bc7cce0102dbd2883afecafc6c Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 May 2021 15:10:31 -0700 Subject: [PATCH 03/41] go go pgo --- build/Helix/PrepareHelixPayload.ps1 | 6 +++ build/Helix/RunTestsInHelix.proj | 1 + build/Helix/runtests.cmd | 2 +- .../pipelines/templates/build-console-pgo.yml | 1 + .../pipelines/templates/pgo-merge-pgd-job.yml | 36 ++++++++++++++++ .../dll/Microsoft.Terminal.Remoting.vcxproj | 5 ++- .../TerminalApp/dll/TerminalApp.vcxproj | 5 ++- .../TerminalConnection.vcxproj | 3 +- .../dll/TerminalControl.vcxproj | 5 ++- ...Microsoft.Terminal.Settings.Editor.vcxproj | 1 + .../Microsoft.Terminal.Settings.Model.vcxproj | 5 ++- .../WindowsTerminal/WindowsTerminal.vcxproj | 6 +-- .../Common/Globals.cs | 22 ++++++++++ .../Common/PgoManager.cs | 42 +++++++++++++++++++ .../Elements/TerminalApp.cs | 4 +- .../WindowsTerminal_UIATests/SmokeTests.cs | 1 + .../WindowsTerminal.UIA.Tests.csproj | 3 ++ src/common.build.post.props | 4 ++ src/common.build.pre.props | 5 +++ src/host/exe/Host.EXE.vcxproj | 6 +-- tools/PGODatabase/NuSpecs/PGO.nuspec.template | 12 ++++++ tools/PGODatabase/NuSpecs/build/PGO.targets | 2 +- 22 files changed, 157 insertions(+), 20 deletions(-) create mode 100644 src/cascadia/WindowsTerminal_UIATests/Common/PgoManager.cs diff --git a/build/Helix/PrepareHelixPayload.ps1 b/build/Helix/PrepareHelixPayload.ps1 index a32464e55d8..a0c8fdcdb51 100644 --- a/build/Helix/PrepareHelixPayload.ps1 +++ b/build/Helix/PrepareHelixPayload.ps1 @@ -52,3 +52,9 @@ Copy-Item "build\helix\HelixTestHelpers.cs" "$payloadDir" Copy-Item "build\helix\runtests.cmd" $payloadDir Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir" Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir" + +# Copy the APPX package from the 'drop' artifact dir +Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir + +# Extract the APPX package +Expand-Archive -LiteralPath $payloadDir\CascadiaPackage_0.0.1.0_$Platform.msix -DestinationPath $payloadDir\appx diff --git a/build/Helix/RunTestsInHelix.proj b/build/Helix/RunTestsInHelix.proj index aaac4ab47ab..2448c1bcfc7 100644 --- a/build/Helix/RunTestsInHelix.proj +++ b/build/Helix/RunTestsInHelix.proj @@ -16,4 +16,5 @@ + \ No newline at end of file diff --git a/build/Helix/runtests.cmd b/build/Helix/runtests.cmd index 77f6180e09a..13de2c6d98f 100644 --- a/build/Helix/runtests.cmd +++ b/build/Helix/runtests.cmd @@ -28,7 +28,7 @@ echo %TIME% powershell -ExecutionPolicy Bypass .\InstallTestAppDependencies.ps1 echo %TIME% -set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll +set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll WindowsTerminal.UIA.Tests.dll set testBinaries= for %%B in (%testBinaryCandidates%) do ( if exist %%B ( diff --git a/build/pipelines/templates/build-console-pgo.yml b/build/pipelines/templates/build-console-pgo.yml index 9590dd955ba..b79c060943f 100644 --- a/build/pipelines/templates/build-console-pgo.yml +++ b/build/pipelines/templates/build-console-pgo.yml @@ -27,6 +27,7 @@ jobs: dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }} condition: succeeded() testSuite: 'PgoInstrumentationSuite' + taefQuery: '@IsPgo=true' rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }} - template: helix-processtestresults-job.yml diff --git a/build/pipelines/templates/pgo-merge-pgd-job.yml b/build/pipelines/templates/pgo-merge-pgd-job.yml index 74eb152ce44..e024d2ddaf8 100644 --- a/build/pipelines/templates/pgo-merge-pgd-job.yml +++ b/build/pipelines/templates/pgo-merge-pgd-job.yml @@ -41,6 +41,42 @@ jobs: displayName: 'Merge OpenConsole pgc files into pgd' workingDirectory: $(pgoArtifactsPath) + - script: | + cd $(buildPlatform) + "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Control*.pgc Microsoft.Terminal.Control.pgd + displayName: 'Merge Microsoft.Terminal.Control pgc files into pgd' + workingDirectory: $(pgoArtifactsPath) + + - script: | + cd $(buildPlatform) + "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Remoting*.pgc Microsoft.Terminal.Remoting.pgd + displayName: 'Merge Microsoft.Terminal.Remoting pgc files into pgd' + workingDirectory: $(pgoArtifactsPath) + + - script: | + cd $(buildPlatform) + "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Editor*.pgc Microsoft.Terminal.Settings.Editor.pgd + displayName: 'Merge Microsoft.Terminal.Settings.Editor pgc files into pgd' + workingDirectory: $(pgoArtifactsPath) + + - script: | + cd $(buildPlatform) + "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Model*.pgc Microsoft.Terminal.Settings.Model.pgd + displayName: 'Merge Microsoft.Terminal.Settings.Model pgc files into pgd' + workingDirectory: $(pgoArtifactsPath) + + - script: | + cd $(buildPlatform) + "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalApp*.pgc TerminalApp.pgd + displayName: 'Merge TerminalApp pgc files into pgd' + workingDirectory: $(pgoArtifactsPath) + + - script: | + cd $(buildPlatform) + "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalConnection*.pgc TerminalConnection.pgd + displayName: 'Merge TerminalConnection pgc files into pgd' + workingDirectory: $(pgoArtifactsPath) + - task: CopyFiles@2 displayName: 'Copy merged pgd to artifact staging' inputs: diff --git a/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.vcxproj b/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.vcxproj index 7e394eac646..a2eaba668e4 100644 --- a/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.vcxproj +++ b/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.vcxproj @@ -10,6 +10,7 @@ Console true + true @@ -61,8 +62,8 @@ User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies) - /INCLUDE:_DllMain@12 - /INCLUDE:DllMain + /INCLUDE:_DllMain@12 %(AdditionalOptions) + /INCLUDE:DllMain %(AdditionalOptions) diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj index f585e025e6c..76eb5156c7c 100644 --- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj @@ -10,6 +10,7 @@ Console true + true @@ -105,8 +106,8 @@ User32.lib;WindowsApp.lib;shell32.lib;WinMM.Lib;%(AdditionalDependencies) - /INCLUDE:_DllMain@12 - /INCLUDE:DllMain + /INCLUDE:_DllMain@12 %(AdditionalOptions) + /INCLUDE:DllMain %(AdditionalOptions) diff --git a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj index 62548452353..8af1cf09af4 100644 --- a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj +++ b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj @@ -7,6 +7,7 @@ DynamicLibrary Console true + true @@ -87,4 +88,4 @@ - \ No newline at end of file + diff --git a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj index b1fd4b3656c..061b74c23f2 100644 --- a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj @@ -10,6 +10,7 @@ Console true + true - /INCLUDE:_DllMain@12 - /INCLUDE:DllMain + /INCLUDE:_DllMain@12 %(AdditionalOptions) + /INCLUDE:DllMain %(AdditionalOptions) diff --git a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj index b83ddad621c..0b4157a87b7 100644 --- a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj +++ b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj @@ -20,6 +20,7 @@ Console true + true true + true @@ -114,8 +115,8 @@ User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies) - /INCLUDE:_DllMain@12 - /INCLUDE:DllMain + /INCLUDE:_DllMain@12 %(AdditionalOptions) + /INCLUDE:DllMain %(AdditionalOptions) diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj index 9c689cb1836..d0b116ff356 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj @@ -17,13 +17,12 @@ 10.0.18362.0 Windows + true - - - + true @@ -172,7 +171,6 @@ - diff --git a/src/cascadia/WindowsTerminal_UIATests/Common/Globals.cs b/src/cascadia/WindowsTerminal_UIATests/Common/Globals.cs index 8a47ab90248..dccd0b5618a 100644 --- a/src/cascadia/WindowsTerminal_UIATests/Common/Globals.cs +++ b/src/cascadia/WindowsTerminal_UIATests/Common/Globals.cs @@ -7,6 +7,7 @@ namespace WindowsTerminal.UIA.Tests.Common { using System; + using WEX.TestExecution.Markup; public static class Globals { @@ -23,5 +24,26 @@ public static void WaitForLongTimeout() { System.Threading.Thread.Sleep(Globals.LongTimeout); } + + + static string[] modules = + { + "WindowsTerminal.exe", + "OpenConsole.exe", + "Microsoft.Terminal.Control.dll", + "Microsoft.Terminal.Remoting.dll", + "Microsoft.Terminal.Settings.Editor.dll", + "Microsoft.Terminal.Settings.Model.dll", + "TerminalApp.dll", + "TerminalConnection.dll" + }; + + public static void SweepAllModules(TestContext context) + { + foreach (var mod in modules) + { + PgoManager.PgoSweepIfInstrumented(context, mod); + } + } } } diff --git a/src/cascadia/WindowsTerminal_UIATests/Common/PgoManager.cs b/src/cascadia/WindowsTerminal_UIATests/Common/PgoManager.cs new file mode 100644 index 00000000000..7c901728245 --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/Common/PgoManager.cs @@ -0,0 +1,42 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using WEX.Logging.Interop; +using WEX.TestExecution.Markup; + +namespace WindowsTerminal.UIA.Tests.Common +{ + public static class PgoManager + { + public static void PgoSweepIfInstrumented(TestContext context, string assemblyName) + { +#if PGO_INSTRUMENT + string pgcFileName = context.TestName; + Log.Comment($"Running pgosweep on '{assemblyName}' for test: {pgcFileName}"); + try + { + var startInfo = new ProcessStartInfo() { + FileName = Path.GetFullPath(Path.Combine(context.TestDeploymentDir, "pgosweep.exe")), + Arguments = $"{assemblyName} {assemblyName}-{pgcFileName}.pgc", + UseShellExecute = false, + RedirectStandardOutput = true + }; + using (var process = Process.Start(startInfo)) + { + var output = new StringBuilder(); + while (!process.HasExited) + { + Log.Comment(process.StandardOutput.ReadToEnd()); + } + } + } + catch (Exception ex) + { + Log.Comment("Failed trying to pgosweep. " + ex.ToString()); + throw; + } +#endif + } + } +} diff --git a/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs b/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs index 5829c36d058..90fcfb084eb 100644 --- a/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs +++ b/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs @@ -46,7 +46,7 @@ public TerminalApp(TestContext context) { this.context = context; - string path = Path.GetFullPath(Path.Combine(context.TestDeploymentDir, @"..\..\..\src\cascadia\CascadiaPackage\bin\x64\debug\Appx\WindowsTerminal.exe")); + string path = Path.GetFullPath(Path.Combine(context.TestDeploymentDir, @"appx\WindowsTerminal.exe")); if (context.Properties.Contains("WTPath")) { path = (string)context.Properties["WTPath"]; @@ -143,6 +143,8 @@ private bool IsRunningAsAdmin() private void ExitProcess() { + Globals.SweepAllModules(this.context); + // Release attachment to the child process console. WinCon.FreeConsole(); diff --git a/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs b/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs index 203725afe77..1808bdceec3 100644 --- a/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs +++ b/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs @@ -19,6 +19,7 @@ public class SmokeTests public TestContext TestContext { get; set; } [TestMethod] + [TestProperty("IsPGO", "true")] public void StartTerminal() { using (TerminalApp app = new TerminalApp(TestContext)) diff --git a/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj index 8a391cd450a..abcf31ffbed 100644 --- a/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj +++ b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj @@ -19,6 +19,7 @@ 4 + Instrument ARM64 @@ -39,6 +40,7 @@ pdbonly true TRACE + $(DefineConstants);PGO_INSTRUMENT @@ -89,6 +91,7 @@ + diff --git a/src/common.build.post.props b/src/common.build.post.props index e3e563b900d..437c237aec4 100644 --- a/src/common.build.post.props +++ b/src/common.build.post.props @@ -33,6 +33,10 @@ + + + + diff --git a/src/common.build.pre.props b/src/common.build.pre.props index bbb553640a4..24e38f123e2 100644 --- a/src/common.build.pre.props +++ b/src/common.build.pre.props @@ -14,6 +14,8 @@ $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ $(IntDir) + Instrument + @@ -156,6 +158,9 @@ + + + diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj index 7c26324266e..2036cde80d5 100644 --- a/src/host/exe/Host.EXE.vcxproj +++ b/src/host/exe/Host.EXE.vcxproj @@ -7,10 +7,9 @@ Host.EXE OpenConsole Application + true - - @@ -91,7 +90,6 @@ WinMM.Lib;%(AdditionalDependencies) - - \ No newline at end of file + diff --git a/tools/PGODatabase/NuSpecs/PGO.nuspec.template b/tools/PGODatabase/NuSpecs/PGO.nuspec.template index 32bf2daaa09..1356db21f72 100644 --- a/tools/PGODatabase/NuSpecs/PGO.nuspec.template +++ b/tools/PGODatabase/NuSpecs/PGO.nuspec.template @@ -17,5 +17,17 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/PGODatabase/NuSpecs/build/PGO.targets b/tools/PGODatabase/NuSpecs/build/PGO.targets index 10d996c2707..d070bae5a3d 100644 --- a/tools/PGODatabase/NuSpecs/build/PGO.targets +++ b/tools/PGODatabase/NuSpecs/build/PGO.targets @@ -2,7 +2,7 @@ - $(MSBuildThisFileDirectory)..\tools\$(PlatformShortName)\WindowsTerminal.pgd + $(MSBuildThisFileDirectory)..\tools\$(PlatformShortName)\$(ProjectName).pgd From 0ed0c334233a5f43d08b597ad9585e9b68a97555 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 May 2021 15:13:00 -0700 Subject: [PATCH 04/41] spaces --- build/pipelines/templates/pgo-merge-pgd-job.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/pipelines/templates/pgo-merge-pgd-job.yml b/build/pipelines/templates/pgo-merge-pgd-job.yml index e024d2ddaf8..a06e0c638c9 100644 --- a/build/pipelines/templates/pgo-merge-pgd-job.yml +++ b/build/pipelines/templates/pgo-merge-pgd-job.yml @@ -53,13 +53,13 @@ jobs: displayName: 'Merge Microsoft.Terminal.Remoting pgc files into pgd' workingDirectory: $(pgoArtifactsPath) - - script: | + - script: | cd $(buildPlatform) "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Editor*.pgc Microsoft.Terminal.Settings.Editor.pgd displayName: 'Merge Microsoft.Terminal.Settings.Editor pgc files into pgd' workingDirectory: $(pgoArtifactsPath) - - script: | + - script: | cd $(buildPlatform) "%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Model*.pgc Microsoft.Terminal.Settings.Model.pgd displayName: 'Merge Microsoft.Terminal.Settings.Model pgc files into pgd' From dcb54c22ad0813c7934faa46fbafb8cc33ed91dd Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 May 2021 15:14:11 -0700 Subject: [PATCH 05/41] remove matrix --- build/pipelines/templates/pgo-merge-pgd-job.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/pipelines/templates/pgo-merge-pgd-job.yml b/build/pipelines/templates/pgo-merge-pgd-job.yml index a06e0c638c9..c00bc42e8a5 100644 --- a/build/pipelines/templates/pgo-merge-pgd-job.yml +++ b/build/pipelines/templates/pgo-merge-pgd-job.yml @@ -10,8 +10,6 @@ jobs: variables: artifactsPath: $(Build.SourcesDirectory)\Artifacts pgoArtifactsPath: $(artifactsPath)\${{ parameters.pgoArtifact }} - strategy: - matrix: ${{ parameters.matrix }} steps: # The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves. From 9d5a662908aa2f91684d107e19d21db47a330065 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 May 2021 15:44:02 -0700 Subject: [PATCH 06/41] skip msix regressions check for pgo instrument --- build/pipelines/templates/build-console-steps.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/pipelines/templates/build-console-steps.yml b/build/pipelines/templates/build-console-steps.yml index 22bc6094c9a..b3260079e09 100644 --- a/build/pipelines/templates/build-console-steps.yml +++ b/build/pipelines/templates/build-console-steps.yml @@ -68,6 +68,9 @@ steps: - task: PowerShell@2 displayName: 'Check MSIX for common regressions' + # PGO runtime needs its own CRT and it's in the package for convenience. + # That will make this script mad so skip since we're not shipping the PGO Instrumentation one anyway. + condition: ne(variables['PGOBuildMode'], 'Instrument') inputs: targetType: inline script: | From aa72fe0f8d8288b46af56880c1cf58d46d894495 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 May 2021 15:48:01 -0700 Subject: [PATCH 07/41] move publish step to the top so it can merge both architectures --- build/pipelines/pgo.yml | 7 +++++++ build/pipelines/templates/build-console-pgo.yml | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/build/pipelines/pgo.yml b/build/pipelines/pgo.yml index f221f10387a..996bbc3bd93 100644 --- a/build/pipelines/pgo.yml +++ b/build/pipelines/pgo.yml @@ -25,3 +25,10 @@ stages: - template: ./templates/build-console-pgo.yml parameters: platform: x86 + - stage: Publish_PGO_Databases + displayName: Publish PGO databases + dependsOn: ['Build_x64', 'Build_x86'] + jobs: + - template: pgo-build-and-publish-nuget-job.yml + parameters: + pgoArtifact: 'PGO' diff --git a/build/pipelines/templates/build-console-pgo.yml b/build/pipelines/templates/build-console-pgo.yml index b79c060943f..029a1f35864 100644 --- a/build/pipelines/templates/build-console-pgo.yml +++ b/build/pipelines/templates/build-console-pgo.yml @@ -45,9 +45,3 @@ jobs: dependsOn: - ProcessTestResults pgoArtifact: 'PGO' - -- template: pgo-build-and-publish-nuget-job.yml - parameters: - dependsOn: - - MergePGD - pgoArtifact: 'PGO' \ No newline at end of file From a23e3bdf05d7eebd86451e9aa53233d236df8d7e Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 May 2021 15:49:28 -0700 Subject: [PATCH 08/41] fix template path --- build/pipelines/pgo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pipelines/pgo.yml b/build/pipelines/pgo.yml index 996bbc3bd93..91574083045 100644 --- a/build/pipelines/pgo.yml +++ b/build/pipelines/pgo.yml @@ -29,6 +29,6 @@ stages: displayName: Publish PGO databases dependsOn: ['Build_x64', 'Build_x86'] jobs: - - template: pgo-build-and-publish-nuget-job.yml + - template: ./templates/pgo-build-and-publish-nuget-job.yml parameters: pgoArtifact: 'PGO' From 9a1d7a551596722835993cb33e6f62f83ccc199d Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 May 2021 16:13:24 -0700 Subject: [PATCH 09/41] get managed libs from a different spot as coreclr folder is gone now. expand match to find all pgds --- build/Helix/PrepareHelixPayload.ps1 | 2 +- build/pipelines/templates/build-console-steps.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/Helix/PrepareHelixPayload.ps1 b/build/Helix/PrepareHelixPayload.ps1 index a0c8fdcdb51..647d9dab75d 100644 --- a/build/Helix/PrepareHelixPayload.ps1 +++ b/build/Helix/PrepareHelixPayload.ps1 @@ -20,7 +20,7 @@ New-Item -ItemType Directory -Force -Path $payloadDir # Copy files from nuget packages Copy-Item "$nugetPackagesDir\microsoft.windows.apps.test.1.0.181203002\lib\netcoreapp2.1\*.dll" $payloadDir Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\*" $payloadDir -Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\CoreClr\*" $payloadDir +Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\NetFx4.5\*" $payloadDir New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\" diff --git a/build/pipelines/templates/build-console-steps.yml b/build/pipelines/templates/build-console-steps.yml index b3260079e09..c676cd2d308 100644 --- a/build/pipelines/templates/build-console-steps.yml +++ b/build/pipelines/templates/build-console-steps.yml @@ -119,7 +119,7 @@ steps: displayName: 'Copy PGO databases needed for PGO instrumentation run' inputs: Contents: | - $(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.pgd + **/*.pgd TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/PGO' OverWrite: true flattenFolders: true From 6662ec30ddbf327ca9196f8dfbde310ffe659c40 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 May 2021 16:37:59 -0700 Subject: [PATCH 10/41] add rename and unzip logic --- build/Helix/PrepareHelixPayload.ps1 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build/Helix/PrepareHelixPayload.ps1 b/build/Helix/PrepareHelixPayload.ps1 index 647d9dab75d..45ecb224e99 100644 --- a/build/Helix/PrepareHelixPayload.ps1 +++ b/build/Helix/PrepareHelixPayload.ps1 @@ -54,7 +54,11 @@ Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir" Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir" # Copy the APPX package from the 'drop' artifact dir -Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir +Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir\CascadiaPackage.zip + +# Rename it to extension of ZIP because Expand-Archive is real sassy on the build machines +# and refuses to unzip it because of its file extension while on a desktop, it just +# does the job without complaining. # Extract the APPX package -Expand-Archive -LiteralPath $payloadDir\CascadiaPackage_0.0.1.0_$Platform.msix -DestinationPath $payloadDir\appx +Expand-Archive -LiteralPath $payloadDir\CascadiaPackage.zip -DestinationPath $payloadDir\appx From 34dad1f20cfedb9a9b6a04412b18cb18974026bd Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 09:22:18 -0700 Subject: [PATCH 11/41] duh I only have 1 test --- build/pipelines/templates/build-console-pgo.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/pipelines/templates/build-console-pgo.yml b/build/pipelines/templates/build-console-pgo.yml index 029a1f35864..e6462831a97 100644 --- a/build/pipelines/templates/build-console-pgo.yml +++ b/build/pipelines/templates/build-console-pgo.yml @@ -2,8 +2,8 @@ parameters: configuration: 'Release' platform: '' additionalBuildArguments: '' - minimumExpectedTestsExecutedCount: 10 # Sanity check for minimum expected tests to be reported - rerunPassesRequiredToAvoidFailure: 5 + minimumExpectedTestsExecutedCount: 1 # Sanity check for minimum expected tests to be reported + rerunPassesRequiredToAvoidFailure: 0 jobs: - job: Build${{ parameters.platform }}${{ parameters.configuration }} From 650ae2f217500834d15a59e576288ed8fcd2efde Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 11:45:54 -0700 Subject: [PATCH 12/41] adjust helix run and script --- build/Helix/ProcessHelixFiles.ps1 | 14 ++++++++------ build/pipelines/templates/helix-runtests-job.yml | 13 ++----------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/build/Helix/ProcessHelixFiles.ps1 b/build/Helix/ProcessHelixFiles.ps1 index 0d828bdb863..ac8b939fdb4 100644 --- a/build/Helix/ProcessHelixFiles.ps1 +++ b/build/Helix/ProcessHelixFiles.ps1 @@ -51,19 +51,21 @@ $webClient = New-Object System.Net.WebClient foreach ($testRun in $testRuns.value) { + Write-Host "testRunUri = $testRun.url" $testResults = Invoke-RestMethod -Uri "$($testRun.url)/results?api-version=5.0" -Method Get -Headers $azureDevOpsRestApiHeaders $isTestRunNameShown = $false foreach ($testResult in $testResults.value) { - if ("comment" -in $testResult) - { + $info = ConvertFrom-Json $testResult.comment $helixJobId = $info.HelixJobId $helixWorkItemName = $info.HelixWorkItemName $workItem = "$helixJobId-$helixWorkItemName" + Write-Host "Helix Work Item = $workItem" + if (-not $workItems.Contains($workItem)) { $workItems.Add($workItem) @@ -89,9 +91,9 @@ foreach ($testRun in $testRuns.value) foreach($pgcFile in $pgcFiles) { - $flavorPath = $pgcFile.Name.Split('.')[0] - $archPath = $pgcFile.Name.Split('.')[1] - $fileName = $pgcFile.Name.Remove(0, $flavorPath.length + $archPath.length + 2) + $flavorPath = $testResult.automatedTestName.Split('.')[0] + $archPath = $testResult.automatedTestName.Split('.')[1] + $fileName = $pgcFile.Name $fullPath = "$OutputFolder\PGO\$flavorPath\$archPath" $destination = "$fullPath\$fileName" @@ -107,6 +109,6 @@ foreach ($testRun in $testRuns.value) } } } - } + } } diff --git a/build/pipelines/templates/helix-runtests-job.yml b/build/pipelines/templates/helix-runtests-job.yml index 5cd059da716..8f84d6afc90 100644 --- a/build/pipelines/templates/helix-runtests-job.yml +++ b/build/pipelines/templates/helix-runtests-job.yml @@ -12,17 +12,8 @@ parameters: taefQuery: '' # if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline: useBuildOutputFromPipeline: $(System.DefinitionId) - matrix: - # Release_x86: - # buildPlatform: 'x86' - # buildConfiguration: 'release' - # openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml' - # closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml' - Release_x64: - buildPlatform: 'x64' - buildConfiguration: 'release' - openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml' - closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml' + openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml' + closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml' jobs: - job: ${{ parameters.name }} From bedf00fd95adeb5ba908c2dc1e04d6d3bf93033e Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 11:46:47 -0700 Subject: [PATCH 13/41] remove matrix --- build/pipelines/templates/helix-runtests-job.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/build/pipelines/templates/helix-runtests-job.yml b/build/pipelines/templates/helix-runtests-job.yml index 8f84d6afc90..8c2d0e5d52d 100644 --- a/build/pipelines/templates/helix-runtests-job.yml +++ b/build/pipelines/templates/helix-runtests-job.yml @@ -24,7 +24,6 @@ jobs: timeoutInMinutes: 120 strategy: maxParallel: ${{ parameters.maxParallel }} - matrix: ${{ parameters.matrix }} variables: artifactsDir: $(Build.SourcesDirectory)\Artifacts taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\$(buildPlatform) From 1065a4c7dbc3e9302a46b7b6e2074acc6fe64912 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 12:11:38 -0700 Subject: [PATCH 14/41] bucket chain platform/config params --- build/pipelines/templates/build-console-pgo.yml | 2 ++ build/pipelines/templates/helix-runtests-job.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/build/pipelines/templates/build-console-pgo.yml b/build/pipelines/templates/build-console-pgo.yml index e6462831a97..cd12733c962 100644 --- a/build/pipelines/templates/build-console-pgo.yml +++ b/build/pipelines/templates/build-console-pgo.yml @@ -28,6 +28,8 @@ jobs: condition: succeeded() testSuite: 'PgoInstrumentationSuite' taefQuery: '@IsPgo=true' + buildConfiguration: ${{parameters.configuration}} + buildPlatform: ${{parameters.platform}} rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }} - template: helix-processtestresults-job.yml diff --git a/build/pipelines/templates/helix-runtests-job.yml b/build/pipelines/templates/helix-runtests-job.yml index 8c2d0e5d52d..e1370ab5990 100644 --- a/build/pipelines/templates/helix-runtests-job.yml +++ b/build/pipelines/templates/helix-runtests-job.yml @@ -12,6 +12,8 @@ parameters: taefQuery: '' # if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline: useBuildOutputFromPipeline: $(System.DefinitionId) + buildPlatform: '' + buildConfiguration: '' openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml' closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml' From 99d0f1c5a2494a9abfc4fc75d326c6bba6b3dd3c Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 12:49:51 -0700 Subject: [PATCH 15/41] shuffle config/platform again. make test content package --- build/Helix/PrepareHelixPayload.ps1 | 1 + build/Helix/packages.config | 1 + build/pipelines/templates/build-console-pgo.yml | 4 ++-- build/pipelines/templates/helix-runtests-job.yml | 13 +++++++++---- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/build/Helix/PrepareHelixPayload.ps1 b/build/Helix/PrepareHelixPayload.ps1 index 45ecb224e99..28e92fce124 100644 --- a/build/Helix/PrepareHelixPayload.ps1 +++ b/build/Helix/PrepareHelixPayload.ps1 @@ -24,6 +24,7 @@ Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Plat New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\" +Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent\content\*" "$payloadDir\content\" function Copy-If-Exists { diff --git a/build/Helix/packages.config b/build/Helix/packages.config index 8bf9ce1972e..68c524ec1d7 100644 --- a/build/Helix/packages.config +++ b/build/Helix/packages.config @@ -1,6 +1,7 @@ + diff --git a/build/pipelines/templates/build-console-pgo.yml b/build/pipelines/templates/build-console-pgo.yml index cd12733c962..49dcd3a6c9d 100644 --- a/build/pipelines/templates/build-console-pgo.yml +++ b/build/pipelines/templates/build-console-pgo.yml @@ -28,8 +28,8 @@ jobs: condition: succeeded() testSuite: 'PgoInstrumentationSuite' taefQuery: '@IsPgo=true' - buildConfiguration: ${{parameters.configuration}} - buildPlatform: ${{parameters.platform}} + configuration: ${{ parameters.configuration }} + platform: ${{ parameters.platform }} rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }} - template: helix-processtestresults-job.yml diff --git a/build/pipelines/templates/helix-runtests-job.yml b/build/pipelines/templates/helix-runtests-job.yml index e1370ab5990..748b88b3c21 100644 --- a/build/pipelines/templates/helix-runtests-job.yml +++ b/build/pipelines/templates/helix-runtests-job.yml @@ -10,12 +10,16 @@ parameters: maxParallel: 4 rerunPassesRequiredToAvoidFailure: 5 taefQuery: '' + configuration: '' + platform: '' # if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline: useBuildOutputFromPipeline: $(System.DefinitionId) - buildPlatform: '' - buildConfiguration: '' - openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml' - closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml' + matrix: + DoTheThing: + buildPlatform: '${{ parameters.platform }}' + buildConfiguration: '${{ parameters.configuration }}' + openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml' + closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml' jobs: - job: ${{ parameters.name }} @@ -26,6 +30,7 @@ jobs: timeoutInMinutes: 120 strategy: maxParallel: ${{ parameters.maxParallel }} + matrix: ${{ parameters.matrix }} variables: artifactsDir: $(Build.SourcesDirectory)\Artifacts taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\$(buildPlatform) From f4f09a63c4eb0e8b08f75d32bd6445d3123a9c6d Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 12:54:34 -0700 Subject: [PATCH 16/41] Try another way --- build/pipelines/templates/helix-runtests-job.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/build/pipelines/templates/helix-runtests-job.yml b/build/pipelines/templates/helix-runtests-job.yml index 748b88b3c21..5e8450117c9 100644 --- a/build/pipelines/templates/helix-runtests-job.yml +++ b/build/pipelines/templates/helix-runtests-job.yml @@ -14,12 +14,7 @@ parameters: platform: '' # if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline: useBuildOutputFromPipeline: $(System.DefinitionId) - matrix: - DoTheThing: - buildPlatform: '${{ parameters.platform }}' - buildConfiguration: '${{ parameters.configuration }}' - openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml' - closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml' + openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml' jobs: - job: ${{ parameters.name }} @@ -30,8 +25,10 @@ jobs: timeoutInMinutes: 120 strategy: maxParallel: ${{ parameters.maxParallel }} - matrix: ${{ parameters.matrix }} variables: + buildConfiguration: ${{ parameters.configuration }} + buildPlatform: ${{ parameters.platform }} + openHelixTargetQueues: ${{ parameters.openHelixTargetQueues }} artifactsDir: $(Build.SourcesDirectory)\Artifacts taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\$(buildPlatform) helixCommonArgs: '/binaryLogger:$(Build.SourcesDirectory)/${{parameters.name}}.$(buildPlatform).$(buildConfiguration).binlog /p:HelixBuild=$(Build.BuildId).$(buildPlatform).$(buildConfiguration) /p:Platform=$(buildPlatform) /p:Configuration=$(buildConfiguration) /p:HelixType=${{parameters.helixType}} /p:TestSuite=${{parameters.testSuite}} /p:ProjFilesPath=$(Build.ArtifactStagingDirectory) /p:rerunPassesRequiredToAvoidFailure=${{parameters.rerunPassesRequiredToAvoidFailure}}' From bc1eaf811093e22fbd8bfce74d979c12289525bf Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 13:03:38 -0700 Subject: [PATCH 17/41] add big test, add comments --- .../Elements/TerminalApp.cs | 2 ++ .../WindowsTerminal_UIATests/SmokeTests.cs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs b/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs index 90fcfb084eb..34ac5b6154c 100644 --- a/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs +++ b/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs @@ -46,6 +46,8 @@ public TerminalApp(TestContext context) { this.context = context; + // If running locally, set WTPath to where we can find a loose deployment of Windows Terminal + // On the build machines, the scripts lay it out at the appx\ subfolder of the test deployment directory string path = Path.GetFullPath(Path.Combine(context.TestDeploymentDir, @"appx\WindowsTerminal.exe")); if (context.Properties.Contains("WTPath")) { diff --git a/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs b/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs index 1808bdceec3..27c59aab54d 100644 --- a/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs +++ b/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs @@ -8,6 +8,7 @@ namespace WindowsTerminal.UIA.Tests { + using OpenQA.Selenium; using WEX.TestExecution.Markup; using WindowsTerminal.UIA.Tests.Common; @@ -29,5 +30,20 @@ public void StartTerminal() Globals.WaitForLongTimeout(); } } + + [TestMethod] + [TestProperty("IsPGO", "true")] + public void RunBigText() + { + using (TerminalApp app = new TerminalApp(TestContext)) + { + var root = app.GetRoot(); + // Relative to the test deployment root, this is where the content file is stored. + // Override necessary to run locally + root.SendKeys(@"cat content\big.txt"); + root.SendKeys(Keys.Enter); + System.Threading.Thread.Sleep(25000); + } + } } } From 0c685a8b368e7b9a25623e73bd60b99892afd2ed Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 13:13:11 -0700 Subject: [PATCH 18/41] duh version number --- build/Helix/PrepareHelixPayload.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Helix/PrepareHelixPayload.ps1 b/build/Helix/PrepareHelixPayload.ps1 index 28e92fce124..a6f6df1c7d6 100644 --- a/build/Helix/PrepareHelixPayload.ps1 +++ b/build/Helix/PrepareHelixPayload.ps1 @@ -24,7 +24,7 @@ Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Plat New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\" -Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent\content\*" "$payloadDir\content\" +Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent.1.0.0\content\*" "$payloadDir\content\" function Copy-If-Exists { From 18d19f8a66a399b30cffcff702ee60cf75c33e60 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 13:37:47 -0700 Subject: [PATCH 19/41] omg you have to make the directory --- build/Helix/PrepareHelixPayload.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/build/Helix/PrepareHelixPayload.ps1 b/build/Helix/PrepareHelixPayload.ps1 index a6f6df1c7d6..687806092ec 100644 --- a/build/Helix/PrepareHelixPayload.ps1 +++ b/build/Helix/PrepareHelixPayload.ps1 @@ -24,6 +24,7 @@ Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Plat New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\" +New-Item -ItemType Directory -Force -Path "$payloadDir\content\" Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent.1.0.0\content\*" "$payloadDir\content\" function Copy-If-Exists From e0f24369511cfd3e83162b05532636dd205c0b69 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 15:20:42 -0700 Subject: [PATCH 20/41] try to fix x86 file pickup and conflict in writing proj files to drop --- build/Helix/RunTestsInHelix.proj | 8 +-- .../templates/build-console-steps.yml | 62 ++++++++++++++++++- .../templates/helix-createprojfile-steps.yml | 2 +- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/build/Helix/RunTestsInHelix.proj b/build/Helix/RunTestsInHelix.proj index 2448c1bcfc7..db00314ff06 100644 --- a/build/Helix/RunTestsInHelix.proj +++ b/build/Helix/RunTestsInHelix.proj @@ -13,8 +13,8 @@ - - - - + + + + \ No newline at end of file diff --git a/build/pipelines/templates/build-console-steps.yml b/build/pipelines/templates/build-console-steps.yml index c676cd2d308..ff58b5f87a7 100644 --- a/build/pipelines/templates/build-console-steps.yml +++ b/build/pipelines/templates/build-console-steps.yml @@ -77,6 +77,62 @@ steps: $Package = Get-ChildItem -Recurse -Filter "CascadiaPackage_*.msix" .\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path $Package.FullName +- task: powershell@2 + displayName: 'Source Index PDBs' + condition: ne(variables['PGOBuildMode'], 'Instrument') + inputs: + targetType: filePath + filePath: build\scripts\Index-Pdbs.ps1 + arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion) + errorActionPreference: silentlyContinue + +- task: PowerShell@2 + displayName: 'Rationalize build platform' + inputs: + targetType: inline + script: | + $Arch = "$(BuildPlatform)" + If ($Arch -Eq "x86") { $Arch = "Win32" } + Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}" + +- task: PowerShell@2 + displayName: 'Run Unit Tests' + inputs: + targetType: filePath + filePath: build\scripts\Run-Tests.ps1 + arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' + condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86'))) + +- task: PowerShell@2 + displayName: 'Run Feature Tests (x64 only)' + inputs: + targetType: filePath + filePath: build\scripts\Run-Tests.ps1 + arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' + condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), eq(variables['BuildPlatform'], 'x64')) + +- task: PowerShell@2 + displayName: 'Convert Test Logs from WTL to xUnit format' + inputs: + targetType: filePath + filePath: build\Helix\ConvertWttLogToXUnit.ps1 + arguments: -WttInputPath '${{ parameters.testLogPath }}' -WttSingleRerunInputPath 'unused.wtl' -WttMultipleRerunInputPath 'unused2.wtl' -XUnitOutputPath 'onBuildMachineResults.xml' -TestNamePrefix '$(BuildConfiguration).$(BuildPlatform)' + condition: and(ne(variables['PGOBuildMode'], 'Instrument'),or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86'))) + +- task: PublishTestResults@2 + displayName: 'Upload converted test logs' + condition: ne(variables['PGOBuildMode'], 'Instrument') + inputs: + testResultsFormat: 'xUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest + testResultsFiles: '**/onBuildMachineResults.xml' + #searchFolder: '$(System.DefaultWorkingDirectory)' # Optional + #mergeTestResults: false # Optional + #failTaskOnFailedTests: false # Optional + testRunTitle: 'On Build Machine Tests' # Optional + buildPlatform: $(BuildPlatform) # Optional + buildConfiguration: $(BuildConfiguration) # Optional + #publishRunAttachments: true # Optional + - task: CopyFiles@2 displayName: 'Copy result logs to Artifacts' inputs: @@ -105,9 +161,9 @@ steps: displayName: 'Copy outputs needed for test runs to Artifacts' inputs: Contents: | - $(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.exe - $(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.dll - $(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.xml + $(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.exe + $(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.dll + $(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml **/Microsoft.VCLibs.*.appx **/TestHostApp/* TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test' diff --git a/build/pipelines/templates/helix-createprojfile-steps.yml b/build/pipelines/templates/helix-createprojfile-steps.yml index 179f667eaf0..e0817036bb5 100644 --- a/build/pipelines/templates/helix-createprojfile-steps.yml +++ b/build/pipelines/templates/helix-createprojfile-steps.yml @@ -12,4 +12,4 @@ steps: inputs: targetType: filePath filePath: build\Helix\GenerateTestProjFile.ps1 - arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}' \ No newline at end of file + arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}' \ No newline at end of file From 6062d90bbf8f4ff878f3f452f2abd1802d6ad9cd Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 15:45:29 -0700 Subject: [PATCH 21/41] just make the directories already sheesh --- build/pipelines/templates/helix-runtests-job.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build/pipelines/templates/helix-runtests-job.yml b/build/pipelines/templates/helix-runtests-job.yml index 5e8450117c9..07dfea672d5 100644 --- a/build/pipelines/templates/helix-runtests-job.yml +++ b/build/pipelines/templates/helix-runtests-job.yml @@ -91,6 +91,14 @@ jobs: filename: 'dir' arguments: '/s $(Build.SourcesDirectory)\HelixPayload' + - task: PowerShell@2 + displayName: 'Make artifact directories' + inputs: + targetType: inline + script: | + New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\" + New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\" + - template: helix-createprojfile-steps.yml parameters: condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite')) From 8eeb56802ba1a1082b4635e4dd6538342f2cbaef Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 15:48:21 -0700 Subject: [PATCH 22/41] shrink artifacts by not stowing pdbs --- build/pipelines/templates/build-console-steps.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/build/pipelines/templates/build-console-steps.yml b/build/pipelines/templates/build-console-steps.yml index ff58b5f87a7..a4fb8d008dc 100644 --- a/build/pipelines/templates/build-console-steps.yml +++ b/build/pipelines/templates/build-console-steps.yml @@ -166,6 +166,7 @@ steps: $(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml **/Microsoft.VCLibs.*.appx **/TestHostApp/* + !**/*.pdb TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test' OverWrite: true flattenFolders: true From 467e5bcbfc3b0bc16415df4f12770b9ca7063c17 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 15:52:28 -0700 Subject: [PATCH 23/41] attempt more artifact shrink discarding unnecessary things --- build/pipelines/templates/build-console-steps.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build/pipelines/templates/build-console-steps.yml b/build/pipelines/templates/build-console-steps.yml index a4fb8d008dc..c70c7b47521 100644 --- a/build/pipelines/templates/build-console-steps.yml +++ b/build/pipelines/templates/build-console-steps.yml @@ -165,8 +165,13 @@ steps: $(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.dll $(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml **/Microsoft.VCLibs.*.appx - **/TestHostApp/* + **/TestHostApp/*.exe + **/TestHostApp/*.dll + **/TestHostApp/*.xml !**/*.pdb + !**/*.ipdb + !**/*.obj + !**/*.pch TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test' OverWrite: true flattenFolders: true From 3616c2d473398a4be69ecc50fc048835990831bc Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 16:39:28 -0700 Subject: [PATCH 24/41] Try x64 only --- build/pipelines/pgo.yml | 17 +++++++++-------- tools/PGODatabase/NuSpecs/PGO.nuspec.template | 16 ++++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/build/pipelines/pgo.yml b/build/pipelines/pgo.yml index 91574083045..8b1b75d6ec6 100644 --- a/build/pipelines/pgo.yml +++ b/build/pipelines/pgo.yml @@ -18,16 +18,17 @@ stages: - template: ./templates/build-console-pgo.yml parameters: platform: x64 - - stage: Build_x86 - displayName: Build x86 - dependsOn: [] - jobs: - - template: ./templates/build-console-pgo.yml - parameters: - platform: x86 + # - stage: Build_x86 + # displayName: Build x86 + # dependsOn: [] + # jobs: + # - template: ./templates/build-console-pgo.yml + # parameters: + # platform: x86 - stage: Publish_PGO_Databases displayName: Publish PGO databases - dependsOn: ['Build_x64', 'Build_x86'] + # dependsOn: ['Build_x64', 'Build_x86'] + dependsOn: ['Build_x64'] jobs: - template: ./templates/pgo-build-and-publish-nuget-job.yml parameters: diff --git a/tools/PGODatabase/NuSpecs/PGO.nuspec.template b/tools/PGODatabase/NuSpecs/PGO.nuspec.template index 1356db21f72..78ee4daa911 100644 --- a/tools/PGODatabase/NuSpecs/PGO.nuspec.template +++ b/tools/PGODatabase/NuSpecs/PGO.nuspec.template @@ -13,21 +13,21 @@ - + - + - + - + - + - + - + - + \ No newline at end of file From c5ae06d51f15da2374df42dbb8c94958fff825be Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 May 2021 16:39:53 -0700 Subject: [PATCH 25/41] Revert "Try x64 only" This reverts commit 3616c2d473398a4be69ecc50fc048835990831bc. --- build/pipelines/pgo.yml | 17 ++++++++--------- tools/PGODatabase/NuSpecs/PGO.nuspec.template | 16 ++++++++-------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/build/pipelines/pgo.yml b/build/pipelines/pgo.yml index 8b1b75d6ec6..91574083045 100644 --- a/build/pipelines/pgo.yml +++ b/build/pipelines/pgo.yml @@ -18,17 +18,16 @@ stages: - template: ./templates/build-console-pgo.yml parameters: platform: x64 - # - stage: Build_x86 - # displayName: Build x86 - # dependsOn: [] - # jobs: - # - template: ./templates/build-console-pgo.yml - # parameters: - # platform: x86 + - stage: Build_x86 + displayName: Build x86 + dependsOn: [] + jobs: + - template: ./templates/build-console-pgo.yml + parameters: + platform: x86 - stage: Publish_PGO_Databases displayName: Publish PGO databases - # dependsOn: ['Build_x64', 'Build_x86'] - dependsOn: ['Build_x64'] + dependsOn: ['Build_x64', 'Build_x86'] jobs: - template: ./templates/pgo-build-and-publish-nuget-job.yml parameters: diff --git a/tools/PGODatabase/NuSpecs/PGO.nuspec.template b/tools/PGODatabase/NuSpecs/PGO.nuspec.template index 78ee4daa911..1356db21f72 100644 --- a/tools/PGODatabase/NuSpecs/PGO.nuspec.template +++ b/tools/PGODatabase/NuSpecs/PGO.nuspec.template @@ -13,21 +13,21 @@ - + - + - + - + - + - + - + - + \ No newline at end of file From c6008f0b1dd71eff7884d3f0d45d140287db1b17 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Sat, 8 May 2021 16:05:38 -0700 Subject: [PATCH 26/41] I don't know why this 403'd, try again. --- build/Helix/ProcessHelixFiles.ps1 | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/build/Helix/ProcessHelixFiles.ps1 b/build/Helix/ProcessHelixFiles.ps1 index ac8b939fdb4..81f47deba34 100644 --- a/build/Helix/ProcessHelixFiles.ps1 +++ b/build/Helix/ProcessHelixFiles.ps1 @@ -9,11 +9,6 @@ Param( $helixLinkFile = "$OutputFolder\LinksToHelixTestFiles.html" -$accessTokenParam = "" -if($HelixAccessToken) -{ - $accessTokenParam = "?access_token=$HelixAccessToken" -} function Generate-File-Links { @@ -57,7 +52,6 @@ foreach ($testRun in $testRuns.value) foreach ($testResult in $testResults.value) { - $info = ConvertFrom-Json $testResult.comment $helixJobId = $info.HelixJobId $helixWorkItemName = $info.HelixWorkItemName @@ -104,7 +98,10 @@ foreach ($testRun in $testRuns.value) New-Item $fullPath -ItemType Directory } - $link = "$($pgcFile.Link)$accessTokenParam" + $link = $pgcFile.Link + + Write-Host "Downloading $link to $destination" + $webClient.DownloadFile($link, $destination) } } From c95e0f81e3bf097727e561b79c68dc6fc8b122bf Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Sat, 8 May 2021 16:06:34 -0700 Subject: [PATCH 27/41] Revert "Revert "Try x64 only"" This reverts commit c5ae06d51f15da2374df42dbb8c94958fff825be. --- build/pipelines/pgo.yml | 17 +++++++++-------- tools/PGODatabase/NuSpecs/PGO.nuspec.template | 16 ++++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/build/pipelines/pgo.yml b/build/pipelines/pgo.yml index 91574083045..8b1b75d6ec6 100644 --- a/build/pipelines/pgo.yml +++ b/build/pipelines/pgo.yml @@ -18,16 +18,17 @@ stages: - template: ./templates/build-console-pgo.yml parameters: platform: x64 - - stage: Build_x86 - displayName: Build x86 - dependsOn: [] - jobs: - - template: ./templates/build-console-pgo.yml - parameters: - platform: x86 + # - stage: Build_x86 + # displayName: Build x86 + # dependsOn: [] + # jobs: + # - template: ./templates/build-console-pgo.yml + # parameters: + # platform: x86 - stage: Publish_PGO_Databases displayName: Publish PGO databases - dependsOn: ['Build_x64', 'Build_x86'] + # dependsOn: ['Build_x64', 'Build_x86'] + dependsOn: ['Build_x64'] jobs: - template: ./templates/pgo-build-and-publish-nuget-job.yml parameters: diff --git a/tools/PGODatabase/NuSpecs/PGO.nuspec.template b/tools/PGODatabase/NuSpecs/PGO.nuspec.template index 1356db21f72..78ee4daa911 100644 --- a/tools/PGODatabase/NuSpecs/PGO.nuspec.template +++ b/tools/PGODatabase/NuSpecs/PGO.nuspec.template @@ -13,21 +13,21 @@ - + - + - + - + - + - + - + - + \ No newline at end of file From d868f9eb09e944fdc17f7c6a7914c6cf05e28a29 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Sat, 8 May 2021 18:37:05 -0700 Subject: [PATCH 28/41] Try to fix PGO artifact name. Update helpers from MUX. Use retries functions for url query and downloads as obviously MUX had a problem with it being sporatic too. --- build/Helix/AzurePipelinesHelperScripts.ps1 | 143 ++++++++++++++++++ build/Helix/ProcessHelixFiles.ps1 | 89 ++++++----- .../pipelines/templates/build-console-pgo.yml | 1 + 3 files changed, 188 insertions(+), 45 deletions(-) diff --git a/build/Helix/AzurePipelinesHelperScripts.ps1 b/build/Helix/AzurePipelinesHelperScripts.ps1 index 5574a9b532b..8934a8548d1 100644 --- a/build/Helix/AzurePipelinesHelperScripts.ps1 +++ b/build/Helix/AzurePipelinesHelperScripts.ps1 @@ -29,4 +29,147 @@ function GetQueryTestRunsUri $baseUri = GetAzureDevOpsBaseUri -CollectionUri $CollectionUri -TeamProject $TeamProject $queryUri = "$baseUri/_apis/test/runs?buildUri=$BuildUri$includeRunDetailsParameter&api-version=5.0" return $queryUri +} + +function Get-HelixJobTypeFromTestRun +{ + Param ($testRun) + + $testRunSingleResultUri = "$($testRun.url)/results?`$top=1&`$skip=0&api-version=5.1" + $singleTestResult = Invoke-RestMethod -Uri $testRunSingleResultUri -Method Get -Headers $azureDevOpsRestApiHeaders + $count = $singleTestResult.value.Length + if($count -eq 0) + { + # If the count is 0, then results have not yet been reported for this run. + # We only care about completed runs with results, so it is ok to just return 'UNKNOWN' for this run. + return "UNKNOWN" + } + else + { + $info = ConvertFrom-Json $singleTestResult.value.comment + $helixJobId = $info.HelixJobId + $job = Invoke-RestMethodWithRetries "https://helix.dot.net/api/2019-06-17/jobs/${helixJobId}?access_token=${HelixAccessToken}" + return $job.Type + } +} + +function Append-HelixAccessTokenToUrl +{ + Param ([string]$url, [string]$token) + if($url.Contains("?")) + { + $url = "$($url)&access_token=$($token)" + } + else + { + $url = "$($url)?access_token=$($token)" + } + return $url +} + + +# The Helix Rest api is sometimes unreliable. So we call these apis with retry logic. +# Note: The Azure DevOps apis are stable and do not need to be called with this retry logic. +$helixApiRetries = 0 +$helixApiRetriesMax = 10 + +function Download-StringWithRetries +{ + Param ([string]$fileName, [string]$url) + + $result = "" + $done = $false + + while(!($done)) + { + try + { + Write-Host "Downloading $fileName" + $result = (New-Object System.Net.WebClient).DownloadString($url) + $done = $true + } + catch + { + Write-Host "Failed to download $fileName $($PSItem.Exception)" + + $helixApiRetries = $helixApiRetries + 1 + if($helixApiRetries -lt $helixApiRetriesMax) + { + Write-Host "Sleep and retry download of $fileName" + Start-Sleep 60 + } + else + { + throw "Failed to download $fileName" + } + } + } + + return $result +} + +function Invoke-RestMethodWithRetries +{ + Param ([string]$url,$Headers) + + $result = @() + $done = $false + + while(!($done)) + { + try + { + $result = Invoke-RestMethod -Uri $url -Method Get -Headers $Headers + $done = $true + } + catch + { + Write-Host "Failed to invoke Rest method $($PSItem.Exception)" + + $helixApiRetries = $helixApiRetries + 1 + if($helixApiRetries -lt $helixApiRetriesMax) + { + Write-Host "Sleep and retry invoke" + Start-Sleep 60 + } + else + { + throw "Failed to invoke Rest method" + } + } + } + + return $result +} + +function Download-FileWithRetries +{ + Param ([string]$fileurl, [string]$destination) + + $done = $false + + while(!($done)) + { + try + { + Write-Host "Downloading $destination" + $webClient.DownloadFile($fileurl, $destination) + $done = $true + } + catch + { + Write-Host "Failed to download $destination $($PSItem.Exception)" + + $helixApiRetries = $helixApiRetries + 1 + if($helixApiRetries -lt $helixApiRetriesMax) + { + Write-Host "Sleep and retry download of $destination" + Start-Sleep 60 + } + else + { + throw "Failed to download $destination" + } + } + } } \ No newline at end of file diff --git a/build/Helix/ProcessHelixFiles.ps1 b/build/Helix/ProcessHelixFiles.ps1 index 81f47deba34..f74187219c1 100644 --- a/build/Helix/ProcessHelixFiles.ps1 +++ b/build/Helix/ProcessHelixFiles.ps1 @@ -40,72 +40,71 @@ $azureDevOpsRestApiHeaders = @{ $queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails Write-Host "queryUri = $queryUri" -$testRuns = Invoke-RestMethod -Uri $queryUri -Method Get -Headers $azureDevOpsRestApiHeaders +$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders $webClient = New-Object System.Net.WebClient [System.Collections.Generic.List[string]]$workItems = @() foreach ($testRun in $testRuns.value) { Write-Host "testRunUri = $testRun.url" - $testResults = Invoke-RestMethod -Uri "$($testRun.url)/results?api-version=5.0" -Method Get -Headers $azureDevOpsRestApiHeaders + $testResults = Invoke-RestMethodWithRetries "$($testRun.url)/results?api-version=5.0" -Headers $azureDevOpsRestApiHeaders $isTestRunNameShown = $false foreach ($testResult in $testResults.value) { - $info = ConvertFrom-Json $testResult.comment - $helixJobId = $info.HelixJobId - $helixWorkItemName = $info.HelixWorkItemName + $info = ConvertFrom-Json $testResult.comment + $helixJobId = $info.HelixJobId + $helixWorkItemName = $info.HelixWorkItemName - $workItem = "$helixJobId-$helixWorkItemName" + $workItem = "$helixJobId-$helixWorkItemName" - Write-Host "Helix Work Item = $workItem" + Write-Host "Helix Work Item = $workItem" - if (-not $workItems.Contains($workItem)) + if (-not $workItems.Contains($workItem)) + { + $workItems.Add($workItem) + $filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam" + $files = Invoke-RestMethodWithRetries $filesQueryUri + + $screenShots = $files | where { $_.Name.EndsWith(".jpg") } + $dumps = $files | where { $_.Name.EndsWith(".dmp") } + $pgcFiles = $files | where { $_.Name.EndsWith(".pgc") } + if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0) { - $workItems.Add($workItem) - $filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam" - $files = Invoke-RestMethod -Uri $filesQueryUri -Method Get - - $screenShots = $files | where { $_.Name.EndsWith(".jpg") } - $dumps = $files | where { $_.Name.EndsWith(".dmp") } - $pgcFiles = $files | where { $_.Name.EndsWith(".pgc") } - if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0) + if(-Not $isTestRunNameShown) { - if(-Not $isTestRunNameShown) - { - Out-File -FilePath $helixLinkFile -Append -InputObject "

$($testRun.name)

" - $isTestRunNameShown = $true - } - Out-File -FilePath $helixLinkFile -Append -InputObject "

$helixWorkItemName

" - Generate-File-Links $screenShots "Screenshots" - Generate-File-Links $dumps "CrashDumps" - Generate-File-Links $pgcFiles "PGC files" - $misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) } - Generate-File-Links $misc "Misc" - - foreach($pgcFile in $pgcFiles) - { - $flavorPath = $testResult.automatedTestName.Split('.')[0] - $archPath = $testResult.automatedTestName.Split('.')[1] - $fileName = $pgcFile.Name - $fullPath = "$OutputFolder\PGO\$flavorPath\$archPath" - $destination = "$fullPath\$fileName" + Out-File -FilePath $helixLinkFile -Append -InputObject "

$($testRun.name)

" + $isTestRunNameShown = $true + } + Out-File -FilePath $helixLinkFile -Append -InputObject "

$helixWorkItemName

" + Generate-File-Links $screenShots "Screenshots" + Generate-File-Links $dumps "CrashDumps" + Generate-File-Links $pgcFiles "PGC files" + $misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) } + Generate-File-Links $misc "Misc" + + foreach($pgcFile in $pgcFiles) + { + $flavorPath = $testResult.automatedTestName.Split('.')[0] + $archPath = $testResult.automatedTestName.Split('.')[1] + $fileName = $pgcFile.Name + $fullPath = "$OutputFolder\PGO\$flavorPath\$archPath" + $destination = "$fullPath\$fileName" - Write-Host "Copying $($pgcFile.Name) to $destination" + Write-Host "Copying $($pgcFile.Name) to $destination" - if (-Not (Test-Path $fullPath)) - { - New-Item $fullPath -ItemType Directory - } + if (-Not (Test-Path $fullPath)) + { + New-Item $fullPath -ItemType Directory + } - $link = $pgcFile.Link + $link = $pgcFile.Link - Write-Host "Downloading $link to $destination" + Write-Host "Downloading $link to $destination" - $webClient.DownloadFile($link, $destination) - } + Download-FileWithRetries $link $destination } } - + } } } diff --git a/build/pipelines/templates/build-console-pgo.yml b/build/pipelines/templates/build-console-pgo.yml index 49dcd3a6c9d..201bb75012a 100644 --- a/build/pipelines/templates/build-console-pgo.yml +++ b/build/pipelines/templates/build-console-pgo.yml @@ -35,6 +35,7 @@ jobs: - template: helix-processtestresults-job.yml parameters: name: 'ProcessTestResults' + pgoArtifact: 'PGO' dependsOn: - RunTestsInHelix condition: succeededOrFailed() From f9360120e3c1414c1742629b89ab849842dda33d Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Sat, 8 May 2021 19:58:07 -0700 Subject: [PATCH 29/41] PGO databases need to go into the PGO artifact. --- build/pipelines/templates/build-console-steps.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/build/pipelines/templates/build-console-steps.yml b/build/pipelines/templates/build-console-steps.yml index c70c7b47521..d75b84ccb12 100644 --- a/build/pipelines/templates/build-console-steps.yml +++ b/build/pipelines/templates/build-console-steps.yml @@ -177,18 +177,25 @@ steps: flattenFolders: true condition: succeeded() +- task: PublishBuildArtifacts@1 + displayName: 'Publish All Build Artifacts' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)' + ArtifactName: 'drop' + - task: CopyFiles@2 displayName: 'Copy PGO databases needed for PGO instrumentation run' inputs: Contents: | **/*.pgd - TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/PGO' + TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO/$(BuildPlatform)' OverWrite: true flattenFolders: true condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument')) - task: PublishBuildArtifacts@1 - displayName: 'Publish All Build Artifacts' + displayName: 'Publish All PGO Artifacts' inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)' - ArtifactName: 'drop' + PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO' + ArtifactName: 'PGO' + condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument')) From de60ad7a586c832d5a3308f2a1618a8303e57129 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Mon, 10 May 2021 10:08:04 -0700 Subject: [PATCH 30/41] bucket chain platform data through to PGD merging --- build/pipelines/templates/build-console-pgo.yml | 1 + build/pipelines/templates/pgo-merge-pgd-job.yml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/build/pipelines/templates/build-console-pgo.yml b/build/pipelines/templates/build-console-pgo.yml index 201bb75012a..8af4ec5d86c 100644 --- a/build/pipelines/templates/build-console-pgo.yml +++ b/build/pipelines/templates/build-console-pgo.yml @@ -48,3 +48,4 @@ jobs: dependsOn: - ProcessTestResults pgoArtifact: 'PGO' + platform: ${{ parameters.platform }} diff --git a/build/pipelines/templates/pgo-merge-pgd-job.yml b/build/pipelines/templates/pgo-merge-pgd-job.yml index c00bc42e8a5..970ef68a574 100644 --- a/build/pipelines/templates/pgo-merge-pgd-job.yml +++ b/build/pipelines/templates/pgo-merge-pgd-job.yml @@ -1,6 +1,7 @@ parameters: dependsOn: '' pgoArtifact: PGO + platform: '' jobs: - job: MergePGD @@ -10,6 +11,7 @@ jobs: variables: artifactsPath: $(Build.SourcesDirectory)\Artifacts pgoArtifactsPath: $(artifactsPath)\${{ parameters.pgoArtifact }} + buildPlatform: ${{ parameters.platform }} steps: # The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves. From ef5d257ff8cdea0ad4e09a5be3e1e025dae75825 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Mon, 10 May 2021 14:21:04 -0700 Subject: [PATCH 31/41] Fix up some of the paths to be less relative and more absolute. Remove mode overrides used for testing and set modes in the YAML instead. --- build/pipelines/templates/build-console-int.yml | 1 + .../WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj | 1 - src/common.build.post.props | 2 +- src/common.build.pre.props | 2 -- src/host/exe/Host.EXE.vcxproj | 3 ++- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/build/pipelines/templates/build-console-int.yml b/build/pipelines/templates/build-console-int.yml index bf8664d15a6..cc051df3f23 100644 --- a/build/pipelines/templates/build-console-int.yml +++ b/build/pipelines/templates/build-console-int.yml @@ -9,6 +9,7 @@ jobs: variables: BuildConfiguration: ${{ parameters.configuration }} BuildPlatform: ${{ parameters.platform }} + PGOBuildMode: 'Optimize' pool: name: Package ES Lab E diff --git a/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj index abcf31ffbed..e3e45422d49 100644 --- a/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj +++ b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj @@ -19,7 +19,6 @@ 4 - Instrument ARM64 diff --git a/src/common.build.post.props b/src/common.build.post.props index 437c237aec4..87416a8981a 100644 --- a/src/common.build.post.props +++ b/src/common.build.post.props @@ -34,7 +34,7 @@ - + diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj index 2036cde80d5..3967d752f35 100644 --- a/src/host/exe/Host.EXE.vcxproj +++ b/src/host/exe/Host.EXE.vcxproj @@ -9,6 +9,7 @@ Application true + @@ -91,5 +92,5 @@ - + From 1b9523bf9c3e8223e30a815ba8d7614fa778680c Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 11 May 2021 11:02:41 -0700 Subject: [PATCH 32/41] fix spelling, revert vscode change --- .github/actions/spelling/expect/expect.txt | 67 +++++++++++----------- .github/actions/spelling/expect/web.txt | 1 - .vscode/settings.json | 6 +- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 85792449ea0..afdb17fd245 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -21,13 +21,13 @@ ACTCTXW activatable ACTIVEBORDER ACTIVECAPTION +adaa ADDALIAS ADDB ADDREF addressof ADDSTRING ADDTOOL -aef AEnd AFew AFill @@ -98,7 +98,6 @@ ASingle asm asmv asmx -aspnet aspx astextplain AStomps @@ -123,7 +122,6 @@ AVerify AVI awch azuredevopspodcast -azurewebsites azzle backend backgrounded @@ -174,7 +172,6 @@ BODGY BOLDFONT BOOLIFY bools -boostorg Bopomofo Borland BOTTOMLEFT @@ -187,7 +184,6 @@ branchconfig BRK Browsable bsearch -BSODs bstr BTNFACE buf @@ -202,7 +198,7 @@ BValue byref bytearray bytebuffer -Cac +cac callee cang capslock @@ -302,7 +298,7 @@ codepage codepath codepoint codeproject -COINIT +coinit COLLECTIONURI colorizing colororacle @@ -487,11 +483,11 @@ CYSIZEFRAME CYSMICON CYVIRTUALSCREEN CYVSCROLL -dahall dai DATABLOCK DATAVIEW DATAW +datetime DBatch dbcs DBCSCHAR @@ -575,7 +571,6 @@ defaultsettings DEFAULTTONEAREST DEFAULTTONULL DEFAULTTOPRIMARY -DEFCON defectdefs DEFERERASE deff @@ -603,7 +598,6 @@ desktopwindowxamlsource dest DESTINATIONNAME devblogs -developercommunity devicecode devicefamily devops @@ -671,18 +665,19 @@ DUNIT dup'ed dvi dw +dwl DWLP dwm dwmapi dword dwrite dwriteglyphrundescriptionclustermap -dwl dxgi dxgidwm dxinterop dxttbmp eachother +eae eaf EASTEUROPE eb @@ -705,6 +700,7 @@ elems elif elseif emacs +emplate EMPTYBOX enabledelayedexpansion endian @@ -768,12 +764,11 @@ fcb fcharset fclose fcntl +fd fdc FDD -fde fdopen fdw -fea fesb FFDE FFrom @@ -790,6 +785,7 @@ FILESYSPATH filesystem FILETIME FILETYPE +fileurl FILEW FILLATTR FILLCONSOLEOUTPUT @@ -808,7 +804,6 @@ flyout fmodern fmtarg fmtid -fmtlib FOLDERID FONTCHANGE fontdlg @@ -856,6 +851,7 @@ fuzzwrapper fwdecl fwe fwlink +Fx GAUSSIAN gb gci @@ -864,6 +860,7 @@ gcy gdi gdip gdirenderer +GENPROFILE geopol GETALIAS GETALIASES @@ -983,6 +980,7 @@ hfont hglobal hh hhh +HHmm hhook hhx HIBYTE @@ -1013,10 +1011,9 @@ horiz HORZ hostable hostlib -hotkeys HPA HPAINTBUFFER -HPCON +hpcon hpj hpp HPR @@ -1172,7 +1169,6 @@ IRenderer IScheme ISelection IShell -isocpp issuecomment IState IStoryboard @@ -1290,7 +1286,7 @@ listptr listptrsize lk lld -llvm +LLVM llx LMENU LMNOP @@ -1435,7 +1431,6 @@ mingw minimizeall minkernel MINMAXINFO -mintty minwin minwindef Mip @@ -1443,6 +1438,7 @@ mkdir MMBB mmcc MMCPL +MMdd mmsystem MNC MNOPQ @@ -1482,7 +1478,7 @@ MSIL msix msrc msvcrt -msvcrtd +MSVCRTD MSVS msys msysgit @@ -1494,6 +1490,7 @@ munges mutex mutexes muxes +MUXPGO myapplet mydir myignite @@ -1508,7 +1505,7 @@ namestream nano natvis nbsp -Nc +nc NCCALCSIZE NCCREATE NCLBUTTONDOWN @@ -1542,6 +1539,7 @@ nfe nlength Nls NLSMODE +nmake NOACTIVATE NOAPPLYNOW NOCLIP @@ -1622,6 +1620,7 @@ NTVDM ntverp NTWIN nuget +NUGETEXETOOLPATH nullness nullonfailure nullopt @@ -1631,7 +1630,7 @@ numlock numpad NUMSCROLL nupkg -NVDA +nuspec NVIDIA NVR Nx @@ -1662,11 +1661,11 @@ ONECOREWINDOWS onehalf ONLCR Oo -openconsoleproxy openbash opencode opencon openconsole +openconsoleproxy OPENIF OPENLINK openps @@ -1774,7 +1773,10 @@ PFNCONSOLECREATEIOTHREAD PFONT PFONTENUMDATA PFS +pgd pgdn +pgorepro +pgort pguid pgup PHANDLE @@ -1784,7 +1786,6 @@ pid pidl PIDLIST pii -pinam pinvoke pipename pipestr @@ -1928,7 +1929,6 @@ pythonw qi QJ qo -QOL QRSTU qsort queryable @@ -1999,7 +1999,7 @@ REGSTR reingest Relayout RELBINPATH -remoting +Remoting renamer renderengine rendersize @@ -2077,8 +2077,8 @@ runut runxamlformat rvalue RVERTICAL -rxvt RWIN +rxvt safearray SAFECAST safemath @@ -2287,6 +2287,7 @@ STX stylecop SUA subcompartment +subfolder subkey SUBLANG sublicensable @@ -2522,14 +2523,14 @@ unicode UNICODESTRING UNICODETEXT UNICRT -UNINIT +uninit uninitialize uninstall Uniscribe unittest unittesting universaltest -Unk +unk unknwn unmark UNORM @@ -2537,7 +2538,6 @@ unparseable unpause Unregister Unregistering -unte untests untextured untimes @@ -2594,7 +2594,6 @@ Vcount vcpkg vcprintf vcproj -vcrt vcvarsall vcxitems vcxproj @@ -2830,7 +2829,6 @@ wx wxh xa xact -xamarin xaml Xamlmeta xargs @@ -2848,8 +2846,8 @@ XCount xdy XEncoding xes -Xes XES +Xes xff XFile XFORM @@ -2872,8 +2870,8 @@ XSubstantial xtended xterm XTest -XTPUSHSGR XTPOPSGR +XTPUSHSGR xunit xutr xvalue @@ -2896,6 +2894,7 @@ YVIRTUALSCREEN Yw YWalk yx +yy YZ Zc ZCmd diff --git a/.github/actions/spelling/expect/web.txt b/.github/actions/spelling/expect/web.txt index b68cd0a783f..ec76321ef4f 100644 --- a/.github/actions/spelling/expect/web.txt +++ b/.github/actions/spelling/expect/web.txt @@ -15,5 +15,4 @@ winui appshellintegration cppreference gfycat -what3words Guake diff --git a/.vscode/settings.json b/.vscode/settings.json index 03fd8e97206..1b6028e5aea 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,9 +41,5 @@ "**/obj/**": true, "**/packages/**": true, "**/generated files/**": true - }, - "vscode-nmake-tools.workspaceBuildDirectories": [ - "d:\\src\\terminal" - ], - "C_Cpp.default.configurationProvider": "microsoft.vscode-nmake-tools" + } } \ No newline at end of file From 848eaa5f9c5be4d90ce575d84b4c1bb72deebf18 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 11 May 2021 14:43:57 -0700 Subject: [PATCH 33/41] Fix bug in PGO optimize database matcher projectname-->targetname. Add more PGO tests and rev content package. Make the tests more flexible by allowing dynamic override of paths for content and binary. --- OpenConsole.sln | 3 - build/Helix/PrepareHelixPayload.ps1 | 2 +- build/Helix/packages.config | 2 +- .../Elements/TerminalApp.cs | 30 +++- .../WindowsTerminal_UIATests/SmokeTests.cs | 138 +++++++++++++++++- tools/PGODatabase/NuSpecs/build/PGO.targets | 2 +- 6 files changed, 159 insertions(+), 18 deletions(-) diff --git a/OpenConsole.sln b/OpenConsole.sln index 3d2dde08d04..982e629b81e 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -396,9 +396,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Control", "src\ca EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests", "src\cascadia\WindowsTerminal_UIATests\WindowsTerminal.UIA.Tests.csproj", "{F19DACD5-0C6E-40DC-B6E4-767A3200542C}" - ProjectSection(ProjectDependencies) = postProject - {CA5CAD1A-224A-4171-B13A-F16E576FDD12} = {CA5CAD1A-224A-4171-B13A-F16E576FDD12} - EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/build/Helix/PrepareHelixPayload.ps1 b/build/Helix/PrepareHelixPayload.ps1 index 687806092ec..a68136346bb 100644 --- a/build/Helix/PrepareHelixPayload.ps1 +++ b/build/Helix/PrepareHelixPayload.ps1 @@ -25,7 +25,7 @@ New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\" Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\" New-Item -ItemType Directory -Force -Path "$payloadDir\content\" -Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent.1.0.0\content\*" "$payloadDir\content\" +Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent.1.0.1\content\*" "$payloadDir\content\" function Copy-If-Exists { diff --git a/build/Helix/packages.config b/build/Helix/packages.config index 68c524ec1d7..cfe7b481599 100644 --- a/build/Helix/packages.config +++ b/build/Helix/packages.config @@ -1,7 +1,7 @@ - + diff --git a/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs b/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs index 34ac5b6154c..f288fba6252 100644 --- a/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs +++ b/src/cascadia/WindowsTerminal_UIATests/Elements/TerminalApp.cs @@ -23,13 +23,10 @@ namespace WindowsTerminal.UIA.Tests.Elements using System.Runtime.InteropServices; using System.Security.Principal; + using OpenQA.Selenium; public class TerminalApp : IDisposable { - private static readonly string binPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "cmd.exe"); - private static readonly string linkPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - @"Microsoft\Windows\Start Menu\Programs\System Tools\Command Prompt.lnk"); - protected const string AppDriverUrl = "http://127.0.0.1:4723"; private IntPtr job; @@ -42,7 +39,13 @@ public class TerminalApp : IDisposable private TestContext context; - public TerminalApp(TestContext context) + public string ContentPath { get; private set; } + public string GetFullTestContentPath(string filename) + { + return Path.GetFullPath(Path.Combine(ContentPath, filename)); + } + + public TerminalApp(TestContext context, string shellToLaunch = "powershell.exe") { this.context = context; @@ -53,8 +56,19 @@ public TerminalApp(TestContext context) { path = (string)context.Properties["WTPath"]; } + Log.Comment($"Windows Terminal will be launched from '{path}'"); + + // Same goes for the content directory. Set WTTestContent for where the content files are + // for running tests. + // On the build machines, the scripts lay it out at the content\ subfolder. + ContentPath = @"content"; + if (context.Properties.Contains("WTTestContent")) + { + ContentPath = (string)context.Properties["WTTestContent"]; + } + Log.Comment($"Test Content will be loaded from '{Path.GetFullPath(ContentPath)}'"); - this.CreateProcess(path); + this.CreateProcess(path, shellToLaunch); } ~TerminalApp() @@ -84,7 +98,7 @@ protected virtual void Dispose(bool disposing) } } - private void CreateProcess(string path) + private void CreateProcess(string path, string shellToLaunch) { string WindowTitleToFind = "WindowsTerminal.UIA.Tests"; @@ -94,7 +108,7 @@ private void CreateProcess(string path) Log.Comment("Attempting to launch command-line application at '{0}'", path); string binaryToRunPath = path; - string args = $"new-tab --title \"{WindowTitleToFind}\" --suppressApplicationTitle"; + string args = $"new-tab --title \"{WindowTitleToFind}\" --suppressApplicationTitle \"{shellToLaunch}\""; string launchArgs = $"{binaryToRunPath} {args}"; diff --git a/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs b/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs index 27c59aab54d..b8105dafc17 100644 --- a/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs +++ b/src/cascadia/WindowsTerminal_UIATests/SmokeTests.cs @@ -33,17 +33,147 @@ public void StartTerminal() [TestMethod] [TestProperty("IsPGO", "true")] - public void RunBigText() + public void RunBigTextPowershell() { using (TerminalApp app = new TerminalApp(TestContext)) { var root = app.GetRoot(); - // Relative to the test deployment root, this is where the content file is stored. - // Override necessary to run locally - root.SendKeys(@"cat content\big.txt"); + var contentPath = app.GetFullTestContentPath("big.txt"); + root.SendKeys($"cat \"{contentPath}\""); root.SendKeys(Keys.Enter); System.Threading.Thread.Sleep(25000); } } + + [TestMethod] + [TestProperty("IsPGO", "true")] + public void RunBigTextPowershellBulk () + { + using (TerminalApp app = new TerminalApp(TestContext)) + { + var root = app.GetRoot(); + var contentPath = app.GetFullTestContentPath("big.txt"); + root.SendKeys($"Get-Content -ReadCount 0 \"{contentPath}\" | Out-Default"); + root.SendKeys(Keys.Enter); + System.Threading.Thread.Sleep(25000); + } + } + + [TestMethod] + [TestProperty("IsPGO", "true")] + public void RunBigTextCmd() + { + using (TerminalApp app = new TerminalApp(TestContext, "cmd.exe")) + { + var root = app.GetRoot(); + var contentPath = app.GetFullTestContentPath("big.txt"); + root.SendKeys($"type \"{contentPath}\""); + root.SendKeys(Keys.Enter); + System.Threading.Thread.Sleep(25000); + } + } + + [TestMethod] + [TestProperty("IsPGO", "true")] + public void RunCmatrixCmd() + { + using (TerminalApp app = new TerminalApp(TestContext, "cmd.exe")) + { + var root = app.GetRoot(); + root.SendKeys("chcp 65001" + Keys.Enter); // This output needs UTF-8 + var contentPath = app.GetFullTestContentPath("cmatrix.txt"); + root.SendKeys($"type \"{contentPath}\""); + root.SendKeys(Keys.Enter); + System.Threading.Thread.Sleep(10000); + } + } + + [TestMethod] + [TestProperty("IsPGO", "true")] + public void RunCacafireCmd() + { + using (TerminalApp app = new TerminalApp(TestContext, "cmd.exe")) + { + var root = app.GetRoot(); + root.SendKeys("chcp 65001" + Keys.Enter); // This output needs UTF-8 + var contentPath = app.GetFullTestContentPath("cacafire.txt"); + root.SendKeys($"type \"{contentPath}\""); + root.SendKeys(Keys.Enter); + System.Threading.Thread.Sleep(25000); + } + } + + [TestMethod] + [TestProperty("IsPGO", "true")] + public void RunChafaCmd() + { + using (TerminalApp app = new TerminalApp(TestContext, "cmd.exe")) + { + var root = app.GetRoot(); + root.SendKeys("chcp 65001" + Keys.Enter); // This output needs UTF-8 + var contentPath = app.GetFullTestContentPath("chafa.txt"); + root.SendKeys($"type \"{contentPath}\""); + root.SendKeys(Keys.Enter); + System.Threading.Thread.Sleep(10000); + } + } + + [TestMethod] + [TestProperty("IsPGO", "true")] + public void RunMakeKillPanes() + { + using (TerminalApp app = new TerminalApp(TestContext)) + { + var root = app.GetRoot(); + + root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "+"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "+"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "-"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "-"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W"); + Globals.WaitForTimeout(); + + Globals.WaitForLongTimeout(); + } + } + + [TestMethod] + [TestProperty("IsPGO", "true")] + public void RunMakeKillTabs() + { + using (TerminalApp app = new TerminalApp(TestContext)) + { + var root = app.GetRoot(); + + root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "T"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "T"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "T"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "T"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W"); + Globals.WaitForTimeout(); + root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W"); + Globals.WaitForTimeout(); + + Globals.WaitForLongTimeout(); + } + } } } diff --git a/tools/PGODatabase/NuSpecs/build/PGO.targets b/tools/PGODatabase/NuSpecs/build/PGO.targets index d070bae5a3d..e940572f242 100644 --- a/tools/PGODatabase/NuSpecs/build/PGO.targets +++ b/tools/PGODatabase/NuSpecs/build/PGO.targets @@ -2,7 +2,7 @@ - $(MSBuildThisFileDirectory)..\tools\$(PlatformShortName)\$(ProjectName).pgd + $(MSBuildThisFileDirectory)..\tools\$(PlatformShortName)\$(TargetName).pgd From cc85baa9fdc999cf92f87ba8deb29587d8fff0d6 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 11 May 2021 15:32:18 -0700 Subject: [PATCH 34/41] Drop nativemethods. Use correct hostx86/hostx64 based on tooling var. Delete a bunch of commented things. Use wildcard in nuspec. fix spelling --- .github/actions/spelling/expect/expect.txt | 1 + build/Helix/runtests.cmd | 1 - build/pipelines/pgo.yml | 8 - .../Common/NativeMethods.cs | 861 ------------------ src/common.pgo.runtime.props | 4 +- tools/PGODatabase/NuSpecs/PGO.nuspec.template | 17 +- 6 files changed, 5 insertions(+), 887 deletions(-) delete mode 100644 src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index afdb17fd245..8f15d107731 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -199,6 +199,7 @@ byref bytearray bytebuffer cac +cacafire callee cang capslock diff --git a/build/Helix/runtests.cmd b/build/Helix/runtests.cmd index 13de2c6d98f..5c543a141bf 100644 --- a/build/Helix/runtests.cmd +++ b/build/Helix/runtests.cmd @@ -46,7 +46,6 @@ move te.wtl te_original.wtl copy /y te_original.wtl %HELIX_WORKITEM_UPLOAD_ROOT% copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT% -:: for /f "tokens=* delims=" %%a in ('dir /b *.pgc') do ren "%%a" "%testnameprefix%.%%~na.pgc" copy /y *.pgc %HELIX_WORKITEM_UPLOAD_ROOT% set FailedTestQuery= diff --git a/build/pipelines/pgo.yml b/build/pipelines/pgo.yml index 8b1b75d6ec6..1c93a56d8cd 100644 --- a/build/pipelines/pgo.yml +++ b/build/pipelines/pgo.yml @@ -18,16 +18,8 @@ stages: - template: ./templates/build-console-pgo.yml parameters: platform: x64 - # - stage: Build_x86 - # displayName: Build x86 - # dependsOn: [] - # jobs: - # - template: ./templates/build-console-pgo.yml - # parameters: - # platform: x86 - stage: Publish_PGO_Databases displayName: Publish PGO databases - # dependsOn: ['Build_x64', 'Build_x86'] dependsOn: ['Build_x64'] jobs: - template: ./templates/pgo-build-and-publish-nuget-job.yml diff --git a/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs b/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs deleted file mode 100644 index e465ae0b1e3..00000000000 --- a/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs +++ /dev/null @@ -1,861 +0,0 @@ -//---------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// Wrapper class for storing P/Invoke and COM Interop definitions. -//---------------------------------------------------------------------------------------------------------------------- - -namespace WindowsTerminal.UIA.Tests.Common.NativeMethods -{ - using System; - using System.Drawing; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - using System.Text; - - using Microsoft.Win32; - using WEX.TestExecution; - using WEX.Logging.Interop; - - // Small extension method helpers to make C# feel closer to native. - public static class NativeExtensions - { - public static int LoWord(this int val) - { - return val & 0xffff; - } - - public static int HiWord(this int val) - { - return (val >> 16) & 0xffff; - } - } - - public static class NativeMethods - { - public static void Win32BoolHelper(bool result, string actionMessage) - { - if (!result) - { - string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error()); - Log.Comment(errorMsg); - } - - Verify.IsTrue(result, actionMessage); - } - - public static void Win32NullHelper(IntPtr result, string actionMessage) - { - if (result == IntPtr.Zero) - { - string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error()); - Log.Comment(errorMsg); - } - - Verify.IsNotNull(result, actionMessage); - } - } - - public static class WinCon - { - [Flags()] - public enum CONSOLE_SELECTION_INFO_FLAGS : uint - { - CONSOLE_NO_SELECTION = 0x0, - CONSOLE_SELECTION_IN_PROGRESS = 0x1, - CONSOLE_SELECTION_NOT_EMPTY = 0x2, - CONSOLE_MOUSE_SELECTION = 0x4, - CONSOLE_MOUSE_DOWN = 0x8 - } - - public enum CONSOLE_STD_HANDLE : int - { - STD_INPUT_HANDLE = -10, - STD_OUTPUT_HANDLE = -11, - STD_ERROR_HANDLE = -12 - } - - public enum CONSOLE_ATTRIBUTES : ushort - { - FOREGROUND_BLUE = 0x1, - FOREGROUND_GREEN = 0x2, - FOREGROUND_RED = 0x4, - FOREGROUND_INTENSITY = 0x8, - FOREGROUND_YELLOW = FOREGROUND_RED | FOREGROUND_GREEN, - FOREGROUND_CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE, - FOREGROUND_MAGENTA = FOREGROUND_RED | FOREGROUND_BLUE, - FOREGROUND_COLORS = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, - FOREGROUND_ALL = FOREGROUND_COLORS | FOREGROUND_INTENSITY, - BACKGROUND_BLUE = 0x10, - BACKGROUND_GREEN = 0x20, - BACKGROUND_RED = 0x40, - BACKGROUND_INTENSITY = 0x80, - BACKGROUND_YELLOW = BACKGROUND_RED | BACKGROUND_GREEN, - BACKGROUND_CYAN = BACKGROUND_GREEN | BACKGROUND_BLUE, - BACKGROUND_MAGENTA = BACKGROUND_RED | BACKGROUND_BLUE, - BACKGROUND_COLORS = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN, - BACKGROUND_ALL = BACKGROUND_COLORS | BACKGROUND_INTENSITY, - COMMON_LVB_LEADING_BYTE = 0x100, - COMMON_LVB_TRAILING_BYTE = 0x200, - COMMON_LVB_GRID_HORIZONTAL = 0x400, - COMMON_LVB_GRID_LVERTICAL = 0x800, - COMMON_LVB_GRID_RVERTICAL = 0x1000, - COMMON_LVB_REVERSE_VIDEO = 0x4000, - COMMON_LVB_UNDERSCORE = 0x8000 - } - - public enum CONSOLE_OUTPUT_MODES : uint - { - ENABLE_PROCESSED_OUTPUT = 0x1, - ENABLE_WRAP_AT_EOL_OUTPUT = 0x2, - ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4 - } - - //CHAR_INFO struct, which was a union in the old days - // so we want to use LayoutKind.Explicit to mimic it as closely - // as we can - [StructLayout(LayoutKind.Explicit)] - public struct CHAR_INFO - { - [FieldOffset(0)] - internal char UnicodeChar; - [FieldOffset(0)] - internal char AsciiChar; - [FieldOffset(2)] //2 bytes seems to work properly - internal CONSOLE_ATTRIBUTES Attributes; - } - - [StructLayout(LayoutKind.Sequential)] - public struct COORD - { - public short X; - public short Y; - - public override string ToString() - { - return string.Format("(X:{0} Y:{1})", X, Y); - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct SMALL_RECT - { - public short Left; - public short Top; - public short Right; - public short Bottom; - - public short Width - { - get - { - // The API returns bottom/right as the inclusive lower-right - // corner, so we need +1 for the true width - return (short)(this.Right - this.Left + 1); - } - } - - public short Height - { - get - { - // The API returns bottom/right as the inclusive lower-right - // corner, so we need +1 for the true height - return (short)(this.Bottom - this.Top + 1); - } - } - - public override string ToString() - { - return string.Format("(L:{0} T:{1} R:{2} B:{3})", Left, Top, Right, Bottom); - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct CONSOLE_CURSOR_INFO - { - public uint dwSize; - public bool bVisible; - } - - [StructLayout(LayoutKind.Sequential)] - public struct CONSOLE_FONT_INFO - { - public int nFont; - public COORD dwFontSize; - } - - [StructLayout(LayoutKind.Sequential)] - public struct CONSOLE_SELECTION_INFO - { - public CONSOLE_SELECTION_INFO_FLAGS Flags; - public COORD SelectionAnchor; - public SMALL_RECT Selection; - - public override string ToString() - { - return string.Format("Flags:{0:X} Anchor:{1} Selection:{2}", Flags, SelectionAnchor, Selection); - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct CONSOLE_SCREEN_BUFFER_INFO - { - public COORD dwSize; - public COORD dwCursorPosition; - public CONSOLE_ATTRIBUTES wAttributes; - public SMALL_RECT srWindow; - public COORD dwMaximumWindowSize; - } - - [StructLayout(LayoutKind.Sequential)] - public struct CONSOLE_SCREEN_BUFFER_INFO_EX - { - public uint cbSize; - public COORD dwSize; - public COORD dwCursorPosition; - public CONSOLE_ATTRIBUTES wAttributes; - public SMALL_RECT srWindow; - public COORD dwMaximumWindowSize; - - public CONSOLE_ATTRIBUTES wPopupAttributes; - public bool bFullscreenSupported; - - internal COLORREF black; - internal COLORREF darkBlue; - internal COLORREF darkGreen; - internal COLORREF darkCyan; - internal COLORREF darkRed; - internal COLORREF darkMagenta; - internal COLORREF darkYellow; - internal COLORREF gray; - internal COLORREF darkGray; - internal COLORREF blue; - internal COLORREF green; - internal COLORREF cyan; - internal COLORREF red; - internal COLORREF magenta; - internal COLORREF yellow; - internal COLORREF white; - } - - [StructLayout(LayoutKind.Sequential)] - public struct COLORREF - { - internal uint ColorDWORD; - - public COLORREF(Color color) - { - ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16); - } - - public COLORREF(uint r, uint g, uint b) - { - ColorDWORD = r + (g << 8) + (b << 16); - } - - public Color GetColor() - { - return Color.FromArgb((int)(0x000000FFU & ColorDWORD), - (int)(0x0000FF00U & ColorDWORD) >> 8, (int)(0x00FF0000U & ColorDWORD) >> 16); - } - - public void SetColor(Color color) - { - ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16); - } - } - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr GetStdHandle(CONSOLE_STD_HANDLE nStdHandle); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool AttachConsole(UInt32 dwProcessId); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool FreeConsole(); - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern bool SetConsoleTitle(string ConsoleTitle); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool GetConsoleMode(IntPtr hConsoleOutputHandle, out CONSOLE_OUTPUT_MODES lpMode); - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern uint GetConsoleTitle(StringBuilder lpConsoleTitle, int nSize); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr GetConsoleWindow(); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool GetConsoleSelectionInfo(out CONSOLE_SELECTION_INFO lpConsoleSelectionInfo); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool bAbsolute, [In] ref SMALL_RECT lpConsoleWindow); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool GetConsoleCursorInfo(IntPtr hConsoleOutput, out CONSOLE_CURSOR_INFO lpConsoleCursorInfo); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool GetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfo); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool SetConsoleScreenBufferInfoEx(IntPtr ConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfoEx); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool GetCurrentConsoleFont(IntPtr hConsoleOutput, bool bMaximumWindow, out CONSOLE_FONT_INFO lpConsoleCurrentFont); - - [DllImport("kernel32.dll", EntryPoint = "ReadConsoleOutputW", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool ReadConsoleOutput( - IntPtr hConsoleOutput, - /* This pointer is treated as the origin of a two-dimensional array of CHAR_INFO structures - whose size is specified by the dwBufferSize parameter.*/ - [MarshalAs(UnmanagedType.LPArray), Out] CHAR_INFO[,] lpBuffer, - COORD dwBufferSize, - COORD dwBufferCoord, - ref SMALL_RECT lpReadRegion); - - [DllImport("kernel32.dll", EntryPoint = "WriteConsoleOutputCharacterW", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool WriteConsoleOutputCharacter( - IntPtr hConsoleOutput, - string lpCharacter, - UInt32 nLength, - COORD dwWriteCoord, - ref UInt32 lpNumberOfCharsWritten); - - } - - /// - /// The definitions within this file match the winconp.h file that is generated from wincon.w - /// Please see /windows/published/main/wincon.w - /// - public static class WinConP - { - private static readonly Guid PKEY_Console_FormatId = new Guid(0x0C570607, 0x0396, 0x43DE, new byte[] { 0x9D, 0x61, 0xE3, 0x21, 0xD7, 0xDF, 0x50, 0x26 }); - - public static readonly Wtypes.PROPERTYKEY PKEY_Console_ForceV2 = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 1 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_WrapText = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 2 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_FilterOnPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 3 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_CtrlKeysDisabled = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 4 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_LineSelection = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 5 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_WindowTransparency = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 6 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_TrimZeros = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 7 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorType = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 8 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorColor = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 9 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_InterceptCopyPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 10 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultForeground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 11 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultBackground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 12 }; - public static readonly Wtypes.PROPERTYKEY PKEY_Console_TerminalScrolling = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 13 }; - - public static readonly uint NT_CONSOLE_PROPS_SIG = 0xA0000002; - public static readonly uint NT_FE_CONSOLE_PROPS_SIG = 0xA0000004; - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct NT_CONSOLE_PROPS - { - public Shell32.DATABLOCK_HEADER dbh; - public short wFillAttribute; - public short wPopupFillAttribute; - public WinCon.COORD dwScreenBufferSize; - public WinCon.COORD dwWindowSize; - public WinCon.COORD dwWindowOrigin; - public int nFont; - public int nInputBufferSize; - public WinCon.COORD dwFontSize; - public uint uFontFamily; - public uint uFontWeight; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] - public string FaceName; - public uint uCursorSize; - public int bFullScreen; - public int bQuickEdit; - public int bInsertMode; - public int bAutoPosition; - public uint uHistoryBufferSize; - public uint uNumberOfHistoryBuffers; - public int bHistoryNoDup; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] - public int[] ColorTable; - public uint CursorType; - public WinCon.COLORREF CursorColor; - public bool InterceptCopyPaste; - public WinCon.COLORREF DefaultForeground; - public WinCon.COLORREF DefaultBackground; - public bool TerminalScrolling; - } - - [StructLayout(LayoutKind.Sequential)] - public struct NT_FE_CONSOLE_PROPS - { - Shell32.DATABLOCK_HEADER dbh; - uint uCodePage; - } - } - - public static class User32 - { - // http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897(v=vs.85).aspx - [StructLayout(LayoutKind.Sequential)] - public struct RECT - { - public Int32 left; - public Int32 top; - public Int32 right; - public Int32 bottom; - } - - [StructLayout(LayoutKind.Sequential)] - public struct POINT - { - public Int32 x; - public Int32 y; - } - - public const int WHEEL_DELTA = 120; - - [DllImport("user32.dll")] - public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); - - [DllImport("user32.dll")] - public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); - - public const int GWL_STYLE = (-16); - public const int GWL_EXSTYLE = (-20); - - [DllImport("user32.dll", SetLastError = true)] - public static extern int GetWindowLong(IntPtr hWnd, int nIndex); - - [DllImport("user32.dll")] - public static extern bool AdjustWindowRectEx(ref RECT lpRect, int dwStyle, bool bMenu, int dwExStyle); - - [DllImport("user32.dll")] - public static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint); - - public enum WindowMessages : UInt32 - { - WM_KEYDOWN = 0x0100, - WM_KEYUP = 0x0101, - WM_CHAR = 0x0102, - WM_MOUSEWHEEL = 0x020A, - WM_MOUSEHWHEEL = 0x020E, - WM_USER = 0x0400, - CM_SET_KEY_STATE = WM_USER + 18 - } - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - public static extern IntPtr SendMessage(IntPtr hWnd, WindowMessages Msg, Int32 wParam, IntPtr lParam); - - public enum SPI : uint - { - SPI_GETWHEELSCROLLLINES = 0x0068, - SPI_GETWHEELSCROLLCHARACTERS = 0x006C - } - - [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] - public static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, ref uint pvParam, uint fWinIni); - - - public enum WinEventId : uint - { - EVENT_CONSOLE_CARET = 0x4001, - EVENT_CONSOLE_UPDATE_REGION = 0x4002, - EVENT_CONSOLE_UPDATE_SIMPLE = 0x4003, - EVENT_CONSOLE_UPDATE_SCROLL = 0x4004, - EVENT_CONSOLE_LAYOUT = 0x4005, - EVENT_CONSOLE_START_APPLICATION = 0x4006, - EVENT_CONSOLE_END_APPLICATION = 0x4007 - } - - [Flags] - public enum WinEventFlags : uint - { - WINEVENT_OUTOFCONTEXT = 0x0000, // Events are ASYNC - WINEVENT_SKIPOWNTHREAD = 0x0001, // Don't call back for events on installer's thread - WINEVENT_SKIPOWNPROCESS = 0x0002, // Don't call back for events on installer's process - WINEVENT_INCONTEXT = 0x0004, // Events are SYNC, this causes your dll to be injected into every process - } - - public delegate void WinEventDelegate(IntPtr hWinEventHook, WinEventId eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime); - - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr SetWinEventHook(WinEventId eventMin, WinEventId eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, WinEventFlags dwFlags); - - [DllImport("user32.dll")] - public static extern bool UnhookWinEvent(IntPtr hWinEventHook); - - [DllImport("user32.dll", SetLastError = true)] - public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); - - public struct MSG - { - public IntPtr hwnd; - public uint message; - public IntPtr wParam; - public IntPtr lParam; - public uint time; - public POINT pt; - } - - public enum PM : uint - { - PM_NOREMOVE = 0x0000, - PM_REMOVE = 0x0001, - PM_NOYIELD = 0x0002, - } - - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PM wRemoveMsg); - - [DllImport("user32.dll", SetLastError = true)] - public static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax); - - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr DispatchMessage(ref MSG lpmsg); - } - - public static class Shell32 - { - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773249(v=vs.85).aspx - [StructLayout(LayoutKind.Sequential)] - public struct DATABLOCK_HEADER - { - public int cbSize; - public int dwSignature; - } - - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774944(v=vs.85).aspx - // http://pinvoke.net/default.aspx/Enums/SLGP_FLAGS.html - /// IShellLink.GetPath fFlags: Flags that specify the type of path information to retrieve - [Flags()] - public enum SLGP_FLAGS - { - /// Retrieves the standard short (8.3 format) file name - SLGP_SHORTPATH = 0x1, - /// Retrieves the Universal Naming Convention (UNC) path name of the file - SLGP_UNCPRIORITY = 0x2, - /// Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded - SLGP_RAWPATH = 0x4 - } - - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774952(v=vs.85).aspx - // http://pinvoke.net/default.aspx/Enums/SLR_FLAGS.html - /// IShellLink.Resolve fFlags - [Flags()] - public enum SLR_FLAGS - { - /// - /// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set, - /// the high-order word of fFlags can be set to a time-out value that specifies the - /// maximum amount of time to be spent resolving the link. The function returns if the - /// link cannot be resolved within the time-out duration. If the high-order word is set - /// to zero, the time-out duration will be set to the default value of 3,000 milliseconds - /// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out - /// duration, in milliseconds. - /// - SLR_NO_UI = 0x1, - /// Obsolete and no longer used - SLR_ANY_MATCH = 0x2, - /// If the link object has changed, update its path and list of identifiers. - /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine - /// whether or not the link object has changed. - SLR_UPDATE = 0x4, - /// Do not update the link information - SLR_NOUPDATE = 0x8, - /// Do not execute the search heuristics - SLR_NOSEARCH = 0x10, - /// Do not use distributed link tracking - SLR_NOTRACK = 0x20, - /// Disable distributed link tracking. By default, distributed link tracking tracks - /// removable media across multiple devices based on the volume name. It also uses the - /// Universal Naming Convention (UNC) path to track remote file systems whose drive letter - /// has changed. Setting SLR_NOLINKINFO disables both types of tracking. - SLR_NOLINKINFO = 0x40, - /// Call the Microsoft Windows Installer - SLR_INVOKE_MSI = 0x80 - } - - [ComImport, Guid("00021401-0000-0000-C000-000000000046")] - public class ShellLink - { - // Making new of this class will call CoCreate e.g. new ShellLink(); - // Cast to one of the interfaces below will QueryInterface. e.g. (IPersistFile)new ShellLink(); - } - - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774950(v=vs.85).aspx - // http://pinvoke.net/default.aspx/Interfaces/IShellLinkW.html - /// The IShellLink interface allows Shell links to be created, modified, and resolved - [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")] - public interface IShellLinkW - { - /// Retrieves the path and file name of a Shell link object - void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WinBase.WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags); - /// Retrieves the list of item identifiers for a Shell link object - void GetIDList(out IntPtr ppidl); - /// Sets the pointer to an item identifier list (PIDL) for a Shell link object. - void SetIDList(IntPtr pidl); - /// Retrieves the description string for a Shell link object - void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); - /// Sets the description for a Shell link object. The description can be any application-defined string - void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - /// Retrieves the name of the working directory for a Shell link object - void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); - /// Sets the name of the working directory for a Shell link object - void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - /// Retrieves the command-line arguments associated with a Shell link object - void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); - /// Sets the command-line arguments for a Shell link object - void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - /// Retrieves the hot key for a Shell link object - void GetHotkey(out short pwHotkey); - /// Sets a hot key for a Shell link object - void SetHotkey(short wHotkey); - /// Retrieves the show command for a Shell link object - void GetShowCmd(out int piShowCmd); - /// Sets the show command for a Shell link object. The show command sets the initial show state of the window. - void SetShowCmd(int iShowCmd); - /// Retrieves the location (path and index) of the icon for a Shell link object - void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - /// Sets the location (path and index) of the icon for a Shell link object - void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - /// Sets the relative path to the Shell link object - void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); - /// Attempts to find the target of a Shell link, even if it has been moved or renamed - void Resolve(IntPtr hwnd, SLR_FLAGS fFlags); - /// Sets the path and file name of a Shell link object - void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774916(v=vs.85).aspx - // http://pinvoke.net/default.aspx/Interfaces/IShellLonkDataList.html - [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("45e2b4ae-b1c3-11d0-b92f-00a0c90312e1")] - public interface IShellLinkDataList - { - void AddDataBlock(IntPtr pDataBlock); - void CopyDataBlock(uint dwSig, out IntPtr ppDataBlock); - void RemoveDataBlock(uint dwSig); - void GetFlags(out uint pdwFlags); - void SetFlags(uint dwFlags); - } - - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms688695(v=vs.85).aspx - // http://pinvoke.net/default.aspx/Interfaces/IPersist.html - [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IPersist - { - [PreserveSig] - void GetClassID(out Guid pClassID); - } - - - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms687223(v=vs.85).aspx - // http://www.pinvoke.net/default.aspx/Interfaces/IPersistFile.html - [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IPersistFile : IPersist - { - new void GetClassID(out Guid pClassID); - - [PreserveSig] - int IsDirty(); - - [PreserveSig] - void Load([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode); - - [PreserveSig] - void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, - [In, MarshalAs(UnmanagedType.Bool)] bool fRemember); - - [PreserveSig] - void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName); - - [PreserveSig] - void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName); - } - - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb761474(v=vs.85).aspx - // http://www.pinvoke.net/default.aspx/Interfaces/IPropertyStore.html - [ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IPropertyStore - { - [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void GetCount([Out] out uint cProps); - - [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void GetAt([In] uint iProp, out Wtypes.PROPERTYKEY pkey); - - [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void GetValue([In] ref Wtypes.PROPERTYKEY key, out object pv); - - [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void SetValue([In] ref Wtypes.PROPERTYKEY key, [In] ref object pv); - - [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void Commit(); - } - } - - public static class WinBase - { - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365740(v=vs.85).aspx - // http://www.pinvoke.net/default.aspx/Structures/WIN32_FIND_DATA.html - // The CharSet must match the CharSet of the corresponding PInvoke signature - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - public enum STARTF : Int32 - { - STARTF_TITLEISLINKNAME = 0x00000800 - } - - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct STARTUPINFO - { - public Int32 cb; - public string lpReserved; - public string lpDesktop; - public string lpTitle; - public Int32 dwX; - public Int32 dwY; - public Int32 dwXSize; - public Int32 dwYSize; - public Int32 dwXCountChars; - public Int32 dwYCountChars; - public Int32 dwFillAttribute; - public STARTF dwFlags; - public Int16 wShowWindow; - public Int16 cbReserved2; - public IntPtr lpReserved2; - public IntPtr hStdInput; - public IntPtr hStdOutput; - public IntPtr hStdError; - } - - [StructLayout(LayoutKind.Sequential)] - public struct PROCESS_INFORMATION - { - public IntPtr hProcess; - public IntPtr hThread; - public int dwProcessId; - public int dwThreadId; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct STARTUPINFOEX - { - public STARTUPINFO StartupInfo; - public IntPtr lpAttributeList; - } - - [Flags] - public enum CP_CreationFlags : uint - { - CREATE_SUSPENDED = 0x4, - CREATE_NEW_CONSOLE = 0x10, - } - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] - public static extern bool CreateProcess(string lpApplicationName, - string lpCommandLine, - IntPtr lpProcessAttributes, - IntPtr lpThreadAttributes, - bool bInheritHandles, - CP_CreationFlags dwCreationFlags, - IntPtr lpEnvironment, - string lpCurrentDirectory, - [In] ref STARTUPINFO lpStartupInfo, - out PROCESS_INFORMATION lpProcessInformation); - - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, IntPtr lpName); - - [DllImport("kernel32.dll")] - public static extern bool TerminateJobObject(IntPtr hJob, uint uExitCode); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern int ResumeThread(IntPtr hThread); - - public enum JOBOBJECTINFOCLASS : uint - { - JobObjectBasicProcessIdList = 3 - } - - [StructLayout(LayoutKind.Sequential)] - public struct JOBOBJECT_BASIC_PROCESS_ID_LIST - { - public uint NumberOfAssignedProcesses; - public uint NumberOfProcessIdsInList; - public IntPtr ProcessId; - public IntPtr ProcessId2; - } - - [DllImport("kernel32.dll")] - public static extern bool QueryInformationJobObject(IntPtr hJob, - JOBOBJECTINFOCLASS JobObjectInformationClass, - IntPtr lpJobObjectInfo, - int cbJobObjectInfoLength, - IntPtr lpReturnLength); - } - - public static class Wtypes - { - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773381(v=vs.85).aspx - // http://pinvoke.net/default.aspx/Structures/PROPERTYKEY.html - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct PROPERTYKEY - { - public Guid fmtid; - public uint pid; - } - } - - public static class ObjBase - { - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380337(v=vs.85).aspx - // http://www.pinvoke.net/default.aspx/Enums/StgmConstants.html - [Flags] - public enum STGM - { - STGM_READ = 0x0, - STGM_WRITE = 0x1, - STGM_READWRITE = 0x2, - STGM_SHARE_DENY_NONE = 0x40, - STGM_SHARE_DENY_READ = 0x30, - STGM_SHARE_DENY_WRITE = 0x20, - STGM_SHARE_EXCLUSIVE = 0x10, - STGM_PRIORITY = 0x40000, - STGM_CREATE = 0x1000, - STGM_CONVERT = 0x20000, - STGM_FAILIFTHERE = 0x0, - STGM_DIRECT = 0x0, - STGM_TRANSACTED = 0x10000, - STGM_NOSCRATCH = 0x100000, - STGM_NOSNAPSHOT = 0x200000, - STGM_SIMPLE = 0x8000000, - STGM_DIRECT_SWMR = 0x400000, - STGM_DELETEONRELEASE = 0x4000000 - } - } -} diff --git a/src/common.pgo.runtime.props b/src/common.pgo.runtime.props index 55c8091ed2a..2f0197843ee 100644 --- a/src/common.pgo.runtime.props +++ b/src/common.pgo.runtime.props @@ -7,7 +7,9 @@ x64 x64 x64 - $(VCToolsInstallDir)bin\Host$(PlatformShortName)\$(PlatformShortName) + Hostx86 + Hostx64 + $(VCToolsInstallDir)bin\$(HostFolderName)\$(PlatformShortName) $(VCToolsInstallDir)bin\$(PlatformShortName) diff --git a/tools/PGODatabase/NuSpecs/PGO.nuspec.template b/tools/PGODatabase/NuSpecs/PGO.nuspec.template index 78ee4daa911..b2529649d83 100644 --- a/tools/PGODatabase/NuSpecs/PGO.nuspec.template +++ b/tools/PGODatabase/NuSpecs/PGO.nuspec.template @@ -13,21 +13,6 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file From d2333ac93ccfeb585b3b31fab23959f4c7c9da6c Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 11 May 2021 16:02:30 -0700 Subject: [PATCH 35/41] fix some notes in readme. update solution configs for new UIA test project. do platformshortname inside the pgo targets instead of relying on MAGIC --- .github/actions/spelling/expect/expect.txt | 1 + OpenConsole.sln | 34 ++++++------------- .../WindowsTerminal.UIA.Tests.csproj | 3 +- tools/PGODatabase/NuSpecs/build/PGO.targets | 5 +++ tools/PGODatabase/readme.md | 4 +-- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 8f15d107731..864a1144006 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -1012,6 +1012,7 @@ horiz HORZ hostable hostlib +Hostx HPA HPAINTBUFFER hpcon diff --git a/OpenConsole.sln b/OpenConsole.sln index 982e629b81e..60c2f768228 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -3258,49 +3258,35 @@ Global {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x64.Build.0 = Release|x64 {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.ActiveCfg = Release|Win32 {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.Build.0 = Release|Win32 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|Any CPU.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|Any CPU.Build.0 = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|Any CPU.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM.ActiveCfg = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM64.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM64.Build.0 = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x64Test.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x64Test.Build.0 = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x86Test.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x86Test.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x64Test.ActiveCfg = Debug|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x86Test.ActiveCfg = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x64.ActiveCfg = Debug|x64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x64.Build.0 = Debug|x64 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x86.ActiveCfg = Debug|Win32 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x86.Build.0 = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|Any CPU.ActiveCfg = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM.ActiveCfg = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM64.ActiveCfg = Debug|ARM64 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM64.Build.0 = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x64.ActiveCfg = Debug|x64 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x64.Build.0 = Debug|x64 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x86.ActiveCfg = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x86.Build.0 = Debug|Win32 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|Any CPU.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|Any CPU.Build.0 = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|Any CPU.ActiveCfg = Debug|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM.ActiveCfg = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM64.Build.0 = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x64Test.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x64Test.Build.0 = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x86Test.Build.0 = Debug|ARM64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x64Test.ActiveCfg = Debug|x64 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x64.ActiveCfg = Debug|x64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x64.Build.0 = Debug|x64 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x86.ActiveCfg = Debug|Win32 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x86.Build.0 = Debug|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|Any CPU.ActiveCfg = Release|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM.ActiveCfg = Release|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM64.ActiveCfg = Release|ARM64 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM64.Build.0 = Release|ARM64 - {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|DotNet_x64Test.ActiveCfg = Release|x64 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.ActiveCfg = Release|x64 {F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.Build.0 = Release|x64 diff --git a/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj index e3e45422d49..4323bebceda 100644 --- a/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj +++ b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj @@ -89,7 +89,6 @@ - @@ -129,4 +128,4 @@ - + \ No newline at end of file diff --git a/tools/PGODatabase/NuSpecs/build/PGO.targets b/tools/PGODatabase/NuSpecs/build/PGO.targets index e940572f242..96b7f8c9ae9 100644 --- a/tools/PGODatabase/NuSpecs/build/PGO.targets +++ b/tools/PGODatabase/NuSpecs/build/PGO.targets @@ -2,6 +2,11 @@ + $(Platform) + x86 + x64 + x64 + x64 $(MSBuildThisFileDirectory)..\tools\$(PlatformShortName)\$(TargetName).pgd diff --git a/tools/PGODatabase/readme.md b/tools/PGODatabase/readme.md index c06300f36fa..935b0a86762 100644 --- a/tools/PGODatabase/readme.md +++ b/tools/PGODatabase/readme.md @@ -4,7 +4,7 @@ ## Description -We generate PGO database NuGet package which is versioned based on product release version and branch name/time stamp of the code that was used for instrumentation and training. In CI/release builds an initialization step enumerates all available versions, filters out those for other releases and branches. Given a list of applicable versions, it will find the one that is closest (BEFORE) the time-stamp of the last commit or a fork-point from instrumented branch. That package version will be installed and version references will be updated. The PGO branch is determined by variable $pgoBranch in tools/MUXPGODatabase/config.ps1. It will need to be updated if a forked branch should be PGO'd. +We generate PGO database NuGet package which is versioned based on product release version and branch name/time stamp of the code that was used for instrumentation and training. In CI/release builds an initialization step enumerates all available versions, filters out those for other releases and branches. Given a list of applicable versions, it will find the one that is closest (BEFORE) the time-stamp of the last commit or a fork-point from instrumented branch. That package version will be installed and version references will be updated. The PGO branch is determined by variable $pgoBranch in tools/PGODatabase/config.ps1. It will need to be updated if a forked branch should be PGO'd. ## Scenarios @@ -36,7 +36,7 @@ E.g. ### Optimizing release branch -A branch which will be PGO’d requires a slightly different handling. Let’s say release/2.4 forked from main on commit 4abd4d54. Initially, it will be configured to track main and 18b956f6 will be optimized with 2.4.2001312033-main. When the configuration is changed to start tracking release/2.4 (change branch name $pgoBranch in tools/MUXPGODatabase/config.ps1 script), it will start tracking its own branch. +A branch which will be PGO’d requires a slightly different handling. Let’s say release/2.4 forked from main on commit 4abd4d54. Initially, it will be configured to track main and 18b956f6 will be optimized with 2.4.2001312033-main. When the configuration is changed to start tracking release/2.4 (change branch name $pgoBranch in tools/PGODatabase/config.ps1 script), it will start tracking its own branch. E.g. From 9bb2fe78134d4f61e14e89489066d89fb416235b Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 12 May 2021 11:51:10 -0700 Subject: [PATCH 36/41] Add optimize validation script. Move nuget pack to use the azdo tasks over custom script. Allow Terminal UIA tests to run for normal times too. --- .../templates/build-console-steps.yml | 12 ++++++ .../templates/helix-runtests-job.yml | 2 +- .../pgo-build-and-publish-nuget-job.yml | 15 +++++-- tools/NugetWrapper.cmd | 26 ------------ tools/PGODatabase/restore-pgodb.ps1 | 4 +- tools/PGODatabase/verify-pgo.ps1 | 41 +++++++++++++++++++ 6 files changed, 67 insertions(+), 33 deletions(-) delete mode 100644 tools/NugetWrapper.cmd create mode 100644 tools/PGODatabase/verify-pgo.ps1 diff --git a/build/pipelines/templates/build-console-steps.yml b/build/pipelines/templates/build-console-steps.yml index d75b84ccb12..95df0aca8d3 100644 --- a/build/pipelines/templates/build-console-steps.yml +++ b/build/pipelines/templates/build-console-steps.yml @@ -95,6 +95,18 @@ steps: If ($Arch -Eq "x86") { $Arch = "Win32" } Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}" +- task: PowerShell@2 + displayName: 'Validate binaries are optimized' + condition: eq(variables['pgoBuildMode'], 'Optimize') + inputs: + targetType: inline + script: | + $Binaries = 'OpenConsole.exe', 'WindowsTerminal.exe', 'TerminalApp.dll', 'TerminalConnection.dll', 'Microsoft.Terminal.Control.dll', 'Microsoft.Terminal.Remoting.dll', 'Microsoft.Terminal.Settings.Editor.dll', 'Microsoft.Terminal.Settings.Model.dll' + foreach ($BinFile in $Binaries) + { + & "$(Build.SourcesDirectory)\tools\PGODatabase\verify-pgo.ps1" "$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/$BinFile" + } + - task: PowerShell@2 displayName: 'Run Unit Tests' inputs: diff --git a/build/pipelines/templates/helix-runtests-job.yml b/build/pipelines/templates/helix-runtests-job.yml index 07dfea672d5..d1868f58be5 100644 --- a/build/pipelines/templates/helix-runtests-job.yml +++ b/build/pipelines/templates/helix-runtests-job.yml @@ -126,7 +126,7 @@ jobs: - template: helix-createprojfile-steps.yml parameters: - condition: and(succeeded(),eq('${{ parameters.testSuite }}','PgoInstrumentationSuite')) + condition: and(succeeded(),or(eq('${{ parameters.testSuite }}','PgoInstrumentationSuite'),eq('${{ parameters.testSuite }}','DevTestSuite'))) testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\WindowsTerminal.UIA.Tests.dll' outputProjFileName: 'RunTestsInHelix-WindowsTerminalUIATests.proj' testSuite: '${{ parameters.testSuite }}' diff --git a/build/pipelines/templates/pgo-build-and-publish-nuget-job.yml b/build/pipelines/templates/pgo-build-and-publish-nuget-job.yml index d5d5a03e7c3..85bc6c353c0 100644 --- a/build/pipelines/templates/pgo-build-and-publish-nuget-job.yml +++ b/build/pipelines/templates/pgo-build-and-publish-nuget-job.yml @@ -20,6 +20,11 @@ jobs: inputs: artifactName: ${{ parameters.pgoArtifact }} downloadPath: $(artifactsPath) + + - task: NuGetToolInstaller@0 + displayName: 'Use NuGet 5.2.0' + inputs: + versionSpec: 5.2.0 - task: CopyFiles@2 displayName: 'Copy pgd files to NuGet build directory' @@ -36,11 +41,13 @@ jobs: workingDirectory: $(pgoToolsPath) arguments: $(nuspecPath)\$(nuspecFilename).template $(nuspecPath)\$(nuspecFilename) - - task: CmdLine@1 - displayName: 'Build NuGet package' + - task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 + displayName: 'NuGet pack' inputs: - filename: '$(Build.SourcesDirectory)\tools\NugetWrapper.cmd' - arguments: pack "$(nuspecPath)\$(nuspecFilename)" -BasePath "$(nuspecPath)" -OutputDirectory "$(Build.ArtifactStagingDirectory)" -properties PROGRAMFILES="%ProgramFiles(x86)%" + command: pack + packagesToPack: '$(nuspecPath)\$(nuspecFilename)' + basePath: '$(nuspecPath)' + packDestination: '$(Build.ArtifactStagingDirectory)' - task: PublishBuildArtifacts@1 inputs: diff --git a/tools/NugetWrapper.cmd b/tools/NugetWrapper.cmd deleted file mode 100644 index da2868bf1a1..00000000000 --- a/tools/NugetWrapper.cmd +++ /dev/null @@ -1,26 +0,0 @@ -@echo OFF -setlocal - -:: From our friends at Microsoft-UI-XAML -:: https://github.com/microsoft/microsoft-ui-xaml/blob/main/tools/NugetWrapper.cmd - -if "%VisualStudioVersion%" == "" set VisualStudioVersion=15.0 - -if defined NUGETEXETOOLPATH goto :AzurePipelines - -if not exist %TEMP%\nuget.5.2.0.exe ( - echo Nuget.exe not found in the temp dir, downloading. - powershell -Command "& { Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/v5.2.0/nuget.exe -outfile $env:TEMP\nuget.5.2.0.exe }" -) - -%TEMP%\nuget.5.2.0.exe %* - -exit /B %ERRORLEVEL% - - - -:AzurePipelines -echo NUGETEXETOOLPATH = %NUGETEXETOOLPATH% - -%NUGETEXETOOLPATH% %* -exit /B %ERRORLEVEL% \ No newline at end of file diff --git a/tools/PGODatabase/restore-pgodb.ps1 b/tools/PGODatabase/restore-pgodb.ps1 index 46e5fb8cc4d..5fba8417ac2 100644 --- a/tools/PGODatabase/restore-pgodb.ps1 +++ b/tools/PGODatabase/restore-pgodb.ps1 @@ -8,8 +8,8 @@ $currentVersion = MakeVersion $releaseVersionMajor $releaseVersionMinor ( GetDat Write-Host ( "PGO OPTIMIZE: requesting {0} version {1}" -f $packageId, ( FormatVersion $currentVersion ) ) -$packageSource = Register-PackageSource -ForceBootstrap -Name MUX_Dependencies -Location $feedUri -ProviderName NuGet -Trusted -$packages = ( Find-Package $packageId -Source MUX_Dependencies -AllowPrereleaseVersions -AllVersions ) | Sort-Object -Property Version -Descending +$packageSource = Register-PackageSource -ForceBootstrap -Name TerminalDependencies -Location $feedUri -ProviderName NuGet -Trusted +$packages = ( Find-Package $packageId -Source TerminalDependencies -AllowPrereleaseVersions -AllVersions ) | Sort-Object -Property Version -Descending $best = $null diff --git a/tools/PGODatabase/verify-pgo.ps1 b/tools/PGODatabase/verify-pgo.ps1 new file mode 100644 index 00000000000..776b93e0f97 --- /dev/null +++ b/tools/PGODatabase/verify-pgo.ps1 @@ -0,0 +1,41 @@ +Param( + [Parameter(Mandatory = $true, Position = 1)] + [string] $module) + +if ( !( Test-Path $module ) ) +{ + throw "File does not exist $module" +} + +$output = ( & dumpbin.exe /headers /coffgroup $module ) + +$regex1 = [regex] '^\s*[A-F0-9]+ coffgrp(\s+[A-F0-9]+){4} \(PGU\)$' +$regex2 = [regex] '^\s*([A-F0-9]+\s+){2}\.text\$zz$' + +$matchFlags = 0 + +foreach ( $line in $output ) +{ + if ( $line -match $regex1 ) + { + $matchFlags = $matchFlags -bor 1 + } + + if ( $line -match $regex2 ) + { + $matchFlags = $matchFlags -bor 2 + } +} + +$optimized = $matchFlags -eq 3 + +$message = "$module is $( if ( $optimized ) { "optimized" } else { "not optimized" } )" + +if ( -not $optimized ) +{ + throw $message +} +else +{ + write-host $message +} \ No newline at end of file From 2458f82c6b29fc5c777a02f0cde6a47af65548f1 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 12 May 2021 12:01:06 -0700 Subject: [PATCH 37/41] spellcheck! --- .github/actions/spelling/expect/expect.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index c7ea7ecd404..4fe700e0ccd 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -18,7 +18,6 @@ ACIOSS ACover actctx ACTCTXW -actionmap activatable ACTIVEBORDER ACTIVECAPTION @@ -300,6 +299,8 @@ codepage codepath codepoint codeproject +coffgroup +coffgrp coinit COLLECTIONURI colorizing @@ -662,6 +663,7 @@ DTest dtor DTTERM DUMMYUNIONNAME +dumpbin DUNICODE DUNIT dup'ed @@ -1493,7 +1495,6 @@ munges mutex mutexes muxes -MUXPGO myapplet mydir myignite @@ -1542,7 +1543,6 @@ nfe nlength Nls NLSMODE -nmake NOACTIVATE NOAPPLYNOW NOCLIP @@ -1623,7 +1623,6 @@ NTVDM ntverp NTWIN nuget -NUGETEXETOOLPATH nullness nullonfailure nullopt @@ -1780,6 +1779,7 @@ pgd pgdn pgorepro pgort +PGU pguid pgup PHANDLE @@ -2013,7 +2013,6 @@ Replymessage repositorypath rescap Resequence -reserialize RESETCONTENT resheader resizable @@ -2541,7 +2540,7 @@ UNORM unparseable unpause Unregister -Unregistering +unregistering untests untextured untimes @@ -2849,9 +2848,9 @@ xcopy XCount xdy XEncoding -xes XES Xes +xes xff XFile XFORM @@ -2911,3 +2910,4 @@ zsh zu zxcvbnm zy +zz From 1cf265df0a67aeea462e3b43b62a180cd06c52e2 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 12 May 2021 12:45:57 -0700 Subject: [PATCH 38/41] Put back Native Methods. Straight copy of conhost's ones for ease. --- .../Common/NativeMethods.cs | 861 ++++++++++++++++++ .../WindowsTerminal.UIA.Tests.csproj | 1 + 2 files changed, 862 insertions(+) create mode 100644 src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs diff --git a/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs b/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs new file mode 100644 index 00000000000..e465ae0b1e3 --- /dev/null +++ b/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs @@ -0,0 +1,861 @@ +//---------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Wrapper class for storing P/Invoke and COM Interop definitions. +//---------------------------------------------------------------------------------------------------------------------- + +namespace WindowsTerminal.UIA.Tests.Common.NativeMethods +{ + using System; + using System.Drawing; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Text; + + using Microsoft.Win32; + using WEX.TestExecution; + using WEX.Logging.Interop; + + // Small extension method helpers to make C# feel closer to native. + public static class NativeExtensions + { + public static int LoWord(this int val) + { + return val & 0xffff; + } + + public static int HiWord(this int val) + { + return (val >> 16) & 0xffff; + } + } + + public static class NativeMethods + { + public static void Win32BoolHelper(bool result, string actionMessage) + { + if (!result) + { + string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error()); + Log.Comment(errorMsg); + } + + Verify.IsTrue(result, actionMessage); + } + + public static void Win32NullHelper(IntPtr result, string actionMessage) + { + if (result == IntPtr.Zero) + { + string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error()); + Log.Comment(errorMsg); + } + + Verify.IsNotNull(result, actionMessage); + } + } + + public static class WinCon + { + [Flags()] + public enum CONSOLE_SELECTION_INFO_FLAGS : uint + { + CONSOLE_NO_SELECTION = 0x0, + CONSOLE_SELECTION_IN_PROGRESS = 0x1, + CONSOLE_SELECTION_NOT_EMPTY = 0x2, + CONSOLE_MOUSE_SELECTION = 0x4, + CONSOLE_MOUSE_DOWN = 0x8 + } + + public enum CONSOLE_STD_HANDLE : int + { + STD_INPUT_HANDLE = -10, + STD_OUTPUT_HANDLE = -11, + STD_ERROR_HANDLE = -12 + } + + public enum CONSOLE_ATTRIBUTES : ushort + { + FOREGROUND_BLUE = 0x1, + FOREGROUND_GREEN = 0x2, + FOREGROUND_RED = 0x4, + FOREGROUND_INTENSITY = 0x8, + FOREGROUND_YELLOW = FOREGROUND_RED | FOREGROUND_GREEN, + FOREGROUND_CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE, + FOREGROUND_MAGENTA = FOREGROUND_RED | FOREGROUND_BLUE, + FOREGROUND_COLORS = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, + FOREGROUND_ALL = FOREGROUND_COLORS | FOREGROUND_INTENSITY, + BACKGROUND_BLUE = 0x10, + BACKGROUND_GREEN = 0x20, + BACKGROUND_RED = 0x40, + BACKGROUND_INTENSITY = 0x80, + BACKGROUND_YELLOW = BACKGROUND_RED | BACKGROUND_GREEN, + BACKGROUND_CYAN = BACKGROUND_GREEN | BACKGROUND_BLUE, + BACKGROUND_MAGENTA = BACKGROUND_RED | BACKGROUND_BLUE, + BACKGROUND_COLORS = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN, + BACKGROUND_ALL = BACKGROUND_COLORS | BACKGROUND_INTENSITY, + COMMON_LVB_LEADING_BYTE = 0x100, + COMMON_LVB_TRAILING_BYTE = 0x200, + COMMON_LVB_GRID_HORIZONTAL = 0x400, + COMMON_LVB_GRID_LVERTICAL = 0x800, + COMMON_LVB_GRID_RVERTICAL = 0x1000, + COMMON_LVB_REVERSE_VIDEO = 0x4000, + COMMON_LVB_UNDERSCORE = 0x8000 + } + + public enum CONSOLE_OUTPUT_MODES : uint + { + ENABLE_PROCESSED_OUTPUT = 0x1, + ENABLE_WRAP_AT_EOL_OUTPUT = 0x2, + ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4 + } + + //CHAR_INFO struct, which was a union in the old days + // so we want to use LayoutKind.Explicit to mimic it as closely + // as we can + [StructLayout(LayoutKind.Explicit)] + public struct CHAR_INFO + { + [FieldOffset(0)] + internal char UnicodeChar; + [FieldOffset(0)] + internal char AsciiChar; + [FieldOffset(2)] //2 bytes seems to work properly + internal CONSOLE_ATTRIBUTES Attributes; + } + + [StructLayout(LayoutKind.Sequential)] + public struct COORD + { + public short X; + public short Y; + + public override string ToString() + { + return string.Format("(X:{0} Y:{1})", X, Y); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct SMALL_RECT + { + public short Left; + public short Top; + public short Right; + public short Bottom; + + public short Width + { + get + { + // The API returns bottom/right as the inclusive lower-right + // corner, so we need +1 for the true width + return (short)(this.Right - this.Left + 1); + } + } + + public short Height + { + get + { + // The API returns bottom/right as the inclusive lower-right + // corner, so we need +1 for the true height + return (short)(this.Bottom - this.Top + 1); + } + } + + public override string ToString() + { + return string.Format("(L:{0} T:{1} R:{2} B:{3})", Left, Top, Right, Bottom); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_CURSOR_INFO + { + public uint dwSize; + public bool bVisible; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_FONT_INFO + { + public int nFont; + public COORD dwFontSize; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_SELECTION_INFO + { + public CONSOLE_SELECTION_INFO_FLAGS Flags; + public COORD SelectionAnchor; + public SMALL_RECT Selection; + + public override string ToString() + { + return string.Format("Flags:{0:X} Anchor:{1} Selection:{2}", Flags, SelectionAnchor, Selection); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_SCREEN_BUFFER_INFO + { + public COORD dwSize; + public COORD dwCursorPosition; + public CONSOLE_ATTRIBUTES wAttributes; + public SMALL_RECT srWindow; + public COORD dwMaximumWindowSize; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CONSOLE_SCREEN_BUFFER_INFO_EX + { + public uint cbSize; + public COORD dwSize; + public COORD dwCursorPosition; + public CONSOLE_ATTRIBUTES wAttributes; + public SMALL_RECT srWindow; + public COORD dwMaximumWindowSize; + + public CONSOLE_ATTRIBUTES wPopupAttributes; + public bool bFullscreenSupported; + + internal COLORREF black; + internal COLORREF darkBlue; + internal COLORREF darkGreen; + internal COLORREF darkCyan; + internal COLORREF darkRed; + internal COLORREF darkMagenta; + internal COLORREF darkYellow; + internal COLORREF gray; + internal COLORREF darkGray; + internal COLORREF blue; + internal COLORREF green; + internal COLORREF cyan; + internal COLORREF red; + internal COLORREF magenta; + internal COLORREF yellow; + internal COLORREF white; + } + + [StructLayout(LayoutKind.Sequential)] + public struct COLORREF + { + internal uint ColorDWORD; + + public COLORREF(Color color) + { + ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16); + } + + public COLORREF(uint r, uint g, uint b) + { + ColorDWORD = r + (g << 8) + (b << 16); + } + + public Color GetColor() + { + return Color.FromArgb((int)(0x000000FFU & ColorDWORD), + (int)(0x0000FF00U & ColorDWORD) >> 8, (int)(0x00FF0000U & ColorDWORD) >> 16); + } + + public void SetColor(Color color) + { + ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16); + } + } + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GetStdHandle(CONSOLE_STD_HANDLE nStdHandle); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool AttachConsole(UInt32 dwProcessId); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool FreeConsole(); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern bool SetConsoleTitle(string ConsoleTitle); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleMode(IntPtr hConsoleOutputHandle, out CONSOLE_OUTPUT_MODES lpMode); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern uint GetConsoleTitle(StringBuilder lpConsoleTitle, int nSize); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GetConsoleWindow(); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleSelectionInfo(out CONSOLE_SELECTION_INFO lpConsoleSelectionInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool bAbsolute, [In] ref SMALL_RECT lpConsoleWindow); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleCursorInfo(IntPtr hConsoleOutput, out CONSOLE_CURSOR_INFO lpConsoleCursorInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool SetConsoleScreenBufferInfoEx(IntPtr ConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfoEx); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetCurrentConsoleFont(IntPtr hConsoleOutput, bool bMaximumWindow, out CONSOLE_FONT_INFO lpConsoleCurrentFont); + + [DllImport("kernel32.dll", EntryPoint = "ReadConsoleOutputW", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool ReadConsoleOutput( + IntPtr hConsoleOutput, + /* This pointer is treated as the origin of a two-dimensional array of CHAR_INFO structures + whose size is specified by the dwBufferSize parameter.*/ + [MarshalAs(UnmanagedType.LPArray), Out] CHAR_INFO[,] lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + ref SMALL_RECT lpReadRegion); + + [DllImport("kernel32.dll", EntryPoint = "WriteConsoleOutputCharacterW", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool WriteConsoleOutputCharacter( + IntPtr hConsoleOutput, + string lpCharacter, + UInt32 nLength, + COORD dwWriteCoord, + ref UInt32 lpNumberOfCharsWritten); + + } + + /// + /// The definitions within this file match the winconp.h file that is generated from wincon.w + /// Please see /windows/published/main/wincon.w + /// + public static class WinConP + { + private static readonly Guid PKEY_Console_FormatId = new Guid(0x0C570607, 0x0396, 0x43DE, new byte[] { 0x9D, 0x61, 0xE3, 0x21, 0xD7, 0xDF, 0x50, 0x26 }); + + public static readonly Wtypes.PROPERTYKEY PKEY_Console_ForceV2 = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 1 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_WrapText = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 2 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_FilterOnPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 3 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_CtrlKeysDisabled = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 4 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_LineSelection = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 5 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_WindowTransparency = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 6 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_TrimZeros = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 7 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorType = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 8 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorColor = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 9 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_InterceptCopyPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 10 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultForeground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 11 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultBackground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 12 }; + public static readonly Wtypes.PROPERTYKEY PKEY_Console_TerminalScrolling = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 13 }; + + public static readonly uint NT_CONSOLE_PROPS_SIG = 0xA0000002; + public static readonly uint NT_FE_CONSOLE_PROPS_SIG = 0xA0000004; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct NT_CONSOLE_PROPS + { + public Shell32.DATABLOCK_HEADER dbh; + public short wFillAttribute; + public short wPopupFillAttribute; + public WinCon.COORD dwScreenBufferSize; + public WinCon.COORD dwWindowSize; + public WinCon.COORD dwWindowOrigin; + public int nFont; + public int nInputBufferSize; + public WinCon.COORD dwFontSize; + public uint uFontFamily; + public uint uFontWeight; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string FaceName; + public uint uCursorSize; + public int bFullScreen; + public int bQuickEdit; + public int bInsertMode; + public int bAutoPosition; + public uint uHistoryBufferSize; + public uint uNumberOfHistoryBuffers; + public int bHistoryNoDup; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public int[] ColorTable; + public uint CursorType; + public WinCon.COLORREF CursorColor; + public bool InterceptCopyPaste; + public WinCon.COLORREF DefaultForeground; + public WinCon.COLORREF DefaultBackground; + public bool TerminalScrolling; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NT_FE_CONSOLE_PROPS + { + Shell32.DATABLOCK_HEADER dbh; + uint uCodePage; + } + } + + public static class User32 + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public Int32 left; + public Int32 top; + public Int32 right; + public Int32 bottom; + } + + [StructLayout(LayoutKind.Sequential)] + public struct POINT + { + public Int32 x; + public Int32 y; + } + + public const int WHEEL_DELTA = 120; + + [DllImport("user32.dll")] + public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); + + [DllImport("user32.dll")] + public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); + + public const int GWL_STYLE = (-16); + public const int GWL_EXSTYLE = (-20); + + [DllImport("user32.dll", SetLastError = true)] + public static extern int GetWindowLong(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll")] + public static extern bool AdjustWindowRectEx(ref RECT lpRect, int dwStyle, bool bMenu, int dwExStyle); + + [DllImport("user32.dll")] + public static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint); + + public enum WindowMessages : UInt32 + { + WM_KEYDOWN = 0x0100, + WM_KEYUP = 0x0101, + WM_CHAR = 0x0102, + WM_MOUSEWHEEL = 0x020A, + WM_MOUSEHWHEEL = 0x020E, + WM_USER = 0x0400, + CM_SET_KEY_STATE = WM_USER + 18 + } + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr SendMessage(IntPtr hWnd, WindowMessages Msg, Int32 wParam, IntPtr lParam); + + public enum SPI : uint + { + SPI_GETWHEELSCROLLLINES = 0x0068, + SPI_GETWHEELSCROLLCHARACTERS = 0x006C + } + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, ref uint pvParam, uint fWinIni); + + + public enum WinEventId : uint + { + EVENT_CONSOLE_CARET = 0x4001, + EVENT_CONSOLE_UPDATE_REGION = 0x4002, + EVENT_CONSOLE_UPDATE_SIMPLE = 0x4003, + EVENT_CONSOLE_UPDATE_SCROLL = 0x4004, + EVENT_CONSOLE_LAYOUT = 0x4005, + EVENT_CONSOLE_START_APPLICATION = 0x4006, + EVENT_CONSOLE_END_APPLICATION = 0x4007 + } + + [Flags] + public enum WinEventFlags : uint + { + WINEVENT_OUTOFCONTEXT = 0x0000, // Events are ASYNC + WINEVENT_SKIPOWNTHREAD = 0x0001, // Don't call back for events on installer's thread + WINEVENT_SKIPOWNPROCESS = 0x0002, // Don't call back for events on installer's process + WINEVENT_INCONTEXT = 0x0004, // Events are SYNC, this causes your dll to be injected into every process + } + + public delegate void WinEventDelegate(IntPtr hWinEventHook, WinEventId eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr SetWinEventHook(WinEventId eventMin, WinEventId eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, WinEventFlags dwFlags); + + [DllImport("user32.dll")] + public static extern bool UnhookWinEvent(IntPtr hWinEventHook); + + [DllImport("user32.dll", SetLastError = true)] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + + public struct MSG + { + public IntPtr hwnd; + public uint message; + public IntPtr wParam; + public IntPtr lParam; + public uint time; + public POINT pt; + } + + public enum PM : uint + { + PM_NOREMOVE = 0x0000, + PM_REMOVE = 0x0001, + PM_NOYIELD = 0x0002, + } + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PM wRemoveMsg); + + [DllImport("user32.dll", SetLastError = true)] + public static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr DispatchMessage(ref MSG lpmsg); + } + + public static class Shell32 + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773249(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + public struct DATABLOCK_HEADER + { + public int cbSize; + public int dwSignature; + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774944(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Enums/SLGP_FLAGS.html + /// IShellLink.GetPath fFlags: Flags that specify the type of path information to retrieve + [Flags()] + public enum SLGP_FLAGS + { + /// Retrieves the standard short (8.3 format) file name + SLGP_SHORTPATH = 0x1, + /// Retrieves the Universal Naming Convention (UNC) path name of the file + SLGP_UNCPRIORITY = 0x2, + /// Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded + SLGP_RAWPATH = 0x4 + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774952(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Enums/SLR_FLAGS.html + /// IShellLink.Resolve fFlags + [Flags()] + public enum SLR_FLAGS + { + /// + /// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set, + /// the high-order word of fFlags can be set to a time-out value that specifies the + /// maximum amount of time to be spent resolving the link. The function returns if the + /// link cannot be resolved within the time-out duration. If the high-order word is set + /// to zero, the time-out duration will be set to the default value of 3,000 milliseconds + /// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out + /// duration, in milliseconds. + /// + SLR_NO_UI = 0x1, + /// Obsolete and no longer used + SLR_ANY_MATCH = 0x2, + /// If the link object has changed, update its path and list of identifiers. + /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine + /// whether or not the link object has changed. + SLR_UPDATE = 0x4, + /// Do not update the link information + SLR_NOUPDATE = 0x8, + /// Do not execute the search heuristics + SLR_NOSEARCH = 0x10, + /// Do not use distributed link tracking + SLR_NOTRACK = 0x20, + /// Disable distributed link tracking. By default, distributed link tracking tracks + /// removable media across multiple devices based on the volume name. It also uses the + /// Universal Naming Convention (UNC) path to track remote file systems whose drive letter + /// has changed. Setting SLR_NOLINKINFO disables both types of tracking. + SLR_NOLINKINFO = 0x40, + /// Call the Microsoft Windows Installer + SLR_INVOKE_MSI = 0x80 + } + + [ComImport, Guid("00021401-0000-0000-C000-000000000046")] + public class ShellLink + { + // Making new of this class will call CoCreate e.g. new ShellLink(); + // Cast to one of the interfaces below will QueryInterface. e.g. (IPersistFile)new ShellLink(); + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774950(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Interfaces/IShellLinkW.html + /// The IShellLink interface allows Shell links to be created, modified, and resolved + [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")] + public interface IShellLinkW + { + /// Retrieves the path and file name of a Shell link object + void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WinBase.WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags); + /// Retrieves the list of item identifiers for a Shell link object + void GetIDList(out IntPtr ppidl); + /// Sets the pointer to an item identifier list (PIDL) for a Shell link object. + void SetIDList(IntPtr pidl); + /// Retrieves the description string for a Shell link object + void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); + /// Sets the description for a Shell link object. The description can be any application-defined string + void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); + /// Retrieves the name of the working directory for a Shell link object + void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); + /// Sets the name of the working directory for a Shell link object + void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); + /// Retrieves the command-line arguments associated with a Shell link object + void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); + /// Sets the command-line arguments for a Shell link object + void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); + /// Retrieves the hot key for a Shell link object + void GetHotkey(out short pwHotkey); + /// Sets a hot key for a Shell link object + void SetHotkey(short wHotkey); + /// Retrieves the show command for a Shell link object + void GetShowCmd(out int piShowCmd); + /// Sets the show command for a Shell link object. The show command sets the initial show state of the window. + void SetShowCmd(int iShowCmd); + /// Retrieves the location (path and index) of the icon for a Shell link object + void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, + int cchIconPath, out int piIcon); + /// Sets the location (path and index) of the icon for a Shell link object + void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); + /// Sets the relative path to the Shell link object + void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); + /// Attempts to find the target of a Shell link, even if it has been moved or renamed + void Resolve(IntPtr hwnd, SLR_FLAGS fFlags); + /// Sets the path and file name of a Shell link object + void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774916(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Interfaces/IShellLonkDataList.html + [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("45e2b4ae-b1c3-11d0-b92f-00a0c90312e1")] + public interface IShellLinkDataList + { + void AddDataBlock(IntPtr pDataBlock); + void CopyDataBlock(uint dwSig, out IntPtr ppDataBlock); + void RemoveDataBlock(uint dwSig); + void GetFlags(out uint pdwFlags); + void SetFlags(uint dwFlags); + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms688695(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Interfaces/IPersist.html + [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPersist + { + [PreserveSig] + void GetClassID(out Guid pClassID); + } + + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms687223(v=vs.85).aspx + // http://www.pinvoke.net/default.aspx/Interfaces/IPersistFile.html + [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPersistFile : IPersist + { + new void GetClassID(out Guid pClassID); + + [PreserveSig] + int IsDirty(); + + [PreserveSig] + void Load([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode); + + [PreserveSig] + void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, + [In, MarshalAs(UnmanagedType.Bool)] bool fRemember); + + [PreserveSig] + void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName); + + [PreserveSig] + void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName); + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb761474(v=vs.85).aspx + // http://www.pinvoke.net/default.aspx/Interfaces/IPropertyStore.html + [ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPropertyStore + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCount([Out] out uint cProps); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetAt([In] uint iProp, out Wtypes.PROPERTYKEY pkey); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetValue([In] ref Wtypes.PROPERTYKEY key, out object pv); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetValue([In] ref Wtypes.PROPERTYKEY key, [In] ref object pv); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Commit(); + } + } + + public static class WinBase + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365740(v=vs.85).aspx + // http://www.pinvoke.net/default.aspx/Structures/WIN32_FIND_DATA.html + // The CharSet must match the CharSet of the corresponding PInvoke signature + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct WIN32_FIND_DATAW + { + public uint dwFileAttributes; + public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime; + public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime; + public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime; + public uint nFileSizeHigh; + public uint nFileSizeLow; + public uint dwReserved0; + public uint dwReserved1; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string cFileName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] + public string cAlternateFileName; + } + + public enum STARTF : Int32 + { + STARTF_TITLEISLINKNAME = 0x00000800 + } + + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct STARTUPINFO + { + public Int32 cb; + public string lpReserved; + public string lpDesktop; + public string lpTitle; + public Int32 dwX; + public Int32 dwY; + public Int32 dwXSize; + public Int32 dwYSize; + public Int32 dwXCountChars; + public Int32 dwYCountChars; + public Int32 dwFillAttribute; + public STARTF dwFlags; + public Int16 wShowWindow; + public Int16 cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PROCESS_INFORMATION + { + public IntPtr hProcess; + public IntPtr hThread; + public int dwProcessId; + public int dwThreadId; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct STARTUPINFOEX + { + public STARTUPINFO StartupInfo; + public IntPtr lpAttributeList; + } + + [Flags] + public enum CP_CreationFlags : uint + { + CREATE_SUSPENDED = 0x4, + CREATE_NEW_CONSOLE = 0x10, + } + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern bool CreateProcess(string lpApplicationName, + string lpCommandLine, + IntPtr lpProcessAttributes, + IntPtr lpThreadAttributes, + bool bInheritHandles, + CP_CreationFlags dwCreationFlags, + IntPtr lpEnvironment, + string lpCurrentDirectory, + [In] ref STARTUPINFO lpStartupInfo, + out PROCESS_INFORMATION lpProcessInformation); + + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, IntPtr lpName); + + [DllImport("kernel32.dll")] + public static extern bool TerminateJobObject(IntPtr hJob, uint uExitCode); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern int ResumeThread(IntPtr hThread); + + public enum JOBOBJECTINFOCLASS : uint + { + JobObjectBasicProcessIdList = 3 + } + + [StructLayout(LayoutKind.Sequential)] + public struct JOBOBJECT_BASIC_PROCESS_ID_LIST + { + public uint NumberOfAssignedProcesses; + public uint NumberOfProcessIdsInList; + public IntPtr ProcessId; + public IntPtr ProcessId2; + } + + [DllImport("kernel32.dll")] + public static extern bool QueryInformationJobObject(IntPtr hJob, + JOBOBJECTINFOCLASS JobObjectInformationClass, + IntPtr lpJobObjectInfo, + int cbJobObjectInfoLength, + IntPtr lpReturnLength); + } + + public static class Wtypes + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773381(v=vs.85).aspx + // http://pinvoke.net/default.aspx/Structures/PROPERTYKEY.html + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct PROPERTYKEY + { + public Guid fmtid; + public uint pid; + } + } + + public static class ObjBase + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380337(v=vs.85).aspx + // http://www.pinvoke.net/default.aspx/Enums/StgmConstants.html + [Flags] + public enum STGM + { + STGM_READ = 0x0, + STGM_WRITE = 0x1, + STGM_READWRITE = 0x2, + STGM_SHARE_DENY_NONE = 0x40, + STGM_SHARE_DENY_READ = 0x30, + STGM_SHARE_DENY_WRITE = 0x20, + STGM_SHARE_EXCLUSIVE = 0x10, + STGM_PRIORITY = 0x40000, + STGM_CREATE = 0x1000, + STGM_CONVERT = 0x20000, + STGM_FAILIFTHERE = 0x0, + STGM_DIRECT = 0x0, + STGM_TRANSACTED = 0x10000, + STGM_NOSCRATCH = 0x100000, + STGM_NOSNAPSHOT = 0x200000, + STGM_SIMPLE = 0x8000000, + STGM_DIRECT_SWMR = 0x400000, + STGM_DELETEONRELEASE = 0x4000000 + } + } +} diff --git a/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj index 4323bebceda..19e9ca3197c 100644 --- a/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj +++ b/src/cascadia/WindowsTerminal_UIATests/WindowsTerminal.UIA.Tests.csproj @@ -89,6 +89,7 @@ + From 849a4bbe87b93e9e9d48e46635deedb9b43390ef Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 12 May 2021 14:54:00 -0700 Subject: [PATCH 39/41] try link.exe to see if it is there without me having to go find it. --- tools/PGODatabase/verify-pgo.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/PGODatabase/verify-pgo.ps1 b/tools/PGODatabase/verify-pgo.ps1 index 776b93e0f97..1c5c0efea9e 100644 --- a/tools/PGODatabase/verify-pgo.ps1 +++ b/tools/PGODatabase/verify-pgo.ps1 @@ -7,7 +7,7 @@ if ( !( Test-Path $module ) ) throw "File does not exist $module" } -$output = ( & dumpbin.exe /headers /coffgroup $module ) +$output = ( & link.exe /dump /headers /coffgroup $module ) $regex1 = [regex] '^\s*[A-F0-9]+ coffgrp(\s+[A-F0-9]+){4} \(PGU\)$' $regex2 = [regex] '^\s*([A-F0-9]+\s+){2}\.text\$zz$' From 8624f70a712e352196e3a41f0b0cd9b65ae3952f Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 13 May 2021 11:22:30 -0700 Subject: [PATCH 40/41] attempt to resolve developer command prompt so we can validate pgo --- tools/PGODatabase/verify-pgo.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/PGODatabase/verify-pgo.ps1 b/tools/PGODatabase/verify-pgo.ps1 index 1c5c0efea9e..5e4f18d94d1 100644 --- a/tools/PGODatabase/verify-pgo.ps1 +++ b/tools/PGODatabase/verify-pgo.ps1 @@ -7,6 +7,10 @@ if ( !( Test-Path $module ) ) throw "File does not exist $module" } +$vsPath = &(Join-Path ${env:ProgramFiles(x86)} "\Microsoft Visual Studio\Installer\vswhere.exe") -property installationpath +Import-Module (Get-ChildItem $vsPath -Recurse -File -Filter Microsoft.VisualStudio.DevShell.dll).FullName +Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation + $output = ( & link.exe /dump /headers /coffgroup $module ) $regex1 = [regex] '^\s*[A-F0-9]+ coffgrp(\s+[A-F0-9]+){4} \(PGU\)$' From 93298524f8710d70207b395e55238692a6a84744 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 13 May 2021 13:48:32 -0700 Subject: [PATCH 41/41] update spelling --- .github/actions/spelling/expect/expect.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 4fe700e0ccd..79a82b1d2ab 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -663,7 +663,6 @@ DTest dtor DTTERM DUMMYUNIONNAME -dumpbin DUNICODE DUNIT dup'ed @@ -1142,6 +1141,7 @@ INPUTPROCESSORPROFILE inputrc Inputreadhandledata INSERTMODE +installationpath intellisense INTERACTIVITYBASE INTERCEPTCOPYPASTE @@ -2848,9 +2848,8 @@ xcopy XCount xdy XEncoding -XES -Xes xes +Xes xff XFile XFORM