aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBob Arnson <bob@firegiant.com>2025-02-14 22:29:39 -0500
committerBob Arnson <github@bobs.org>2025-03-03 14:25:07 -0500
commitca6e44d496b0c589fdaabad69a00643f539c47cd (patch)
treeedf84727cecfc03092a2851b465d97622c5048eb /src
parentba7fd5837ea149b2e319cc577fad27ce1162a064 (diff)
downloadwix-ca6e44d496b0c589fdaabad69a00643f539c47cd.tar.gz
wix-ca6e44d496b0c589fdaabad69a00643f539c47cd.tar.bz2
wix-ca6e44d496b0c589fdaabad69a00643f539c47cd.zip
Convert ext\ to MSTest and traversal projects.
- Move ext\ unit tests to MSTest. - MSBuildify ext projects with MSTest execution. - Fork test support projects for MSTest: - WixInternal.TestSupport - WixInternal.Core.TestPackage
Diffstat (limited to 'src')
-rw-r--r--src/Directory.Build.props4
-rw-r--r--src/Directory.csproj.targets20
-rw-r--r--src/clean.cmd2
-rw-r--r--src/ext/Bal/bal.cmd55
-rw-r--r--src/ext/Bal/bal_t.proj33
-rw-r--r--src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs49
-rw-r--r--src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs95
-rw-r--r--src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/WixToolsetTest.BootstrapperApplications.csproj7
-rw-r--r--src/ext/ComPlus/complus.cmd21
-rw-r--r--src/ext/ComPlus/complus_t.proj17
-rw-r--r--src/ext/ComPlus/test/WixToolsetTest.ComPlus/ComPlusExtensionFixture.cs9
-rw-r--r--src/ext/ComPlus/test/WixToolsetTest.ComPlus/WixToolsetTest.ComPlus.csproj7
-rw-r--r--src/ext/Dependency/dependency.cmd21
-rw-r--r--src/ext/Dependency/dependency_t.proj17
-rw-r--r--src/ext/Dependency/test/WixToolsetTest.Dependency/DependencyExtensionFixture.cs9
-rw-r--r--src/ext/Dependency/test/WixToolsetTest.Dependency/WixToolsetTest.Dependency.csproj7
-rw-r--r--src/ext/DirectX/directx.cmd24
-rw-r--r--src/ext/DirectX/directx_t.proj17
-rw-r--r--src/ext/DirectX/test/WixToolsetTest.DirectX/DirectXExtensionFixture.cs9
-rw-r--r--src/ext/DirectX/test/WixToolsetTest.DirectX/WixToolsetTest.DirectX.csproj7
-rw-r--r--src/ext/Firewall/firewall.cmd21
-rw-r--r--src/ext/Firewall/firewall_t.proj17
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs61
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj7
-rw-r--r--src/ext/Http/http.cmd21
-rw-r--r--src/ext/Http/http_t.proj17
-rw-r--r--src/ext/Http/test/WixToolsetTest.Http/HttpExtensionFixture.cs11
-rw-r--r--src/ext/Http/test/WixToolsetTest.Http/WixToolsetTest.Http.csproj7
-rw-r--r--src/ext/Iis/iis.cmd21
-rw-r--r--src/ext/Iis/iis_t.proj17
-rw-r--r--src/ext/Iis/test/WixToolsetTest.Iis/IisExtensionFixture.cs9
-rw-r--r--src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj7
-rw-r--r--src/ext/Msmq/msmq.cmd21
-rw-r--r--src/ext/Msmq/msmq_t.proj17
-rw-r--r--src/ext/Msmq/test/WixToolsetTest.Msmq/MsmqExtensionFixture.cs12
-rw-r--r--src/ext/Msmq/test/WixToolsetTest.Msmq/WixToolsetTest.Msmq.csproj7
-rw-r--r--src/ext/NetFx/netfx.cmd48
-rw-r--r--src/ext/NetFx/netfx_t.proj26
-rw-r--r--src/ext/NetFx/test/WixToolsetTest.Netfx/NetfxExtensionFixture.cs67
-rw-r--r--src/ext/NetFx/test/WixToolsetTest.Netfx/WixToolsetTest.Netfx.csproj7
-rw-r--r--src/ext/PowerShell/powershell_t.proj17
-rw-r--r--src/ext/PowerShell/ps.cmd21
-rw-r--r--src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs13
-rw-r--r--src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj7
-rw-r--r--src/ext/Sql/sql.cmd21
-rw-r--r--src/ext/Sql/sql_t.proj17
-rw-r--r--src/ext/Sql/test/WixToolsetTest.Sql/SqlExtensionFixture.cs9
-rw-r--r--src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.csproj7
-rw-r--r--src/ext/UI/test/WixToolsetTest.UI/UIExtensionFixture.cs89
-rw-r--r--src/ext/UI/test/WixToolsetTest.UI/WixToolsetTest.UI.csproj7
-rw-r--r--src/ext/UI/ui.cmd42
-rw-r--r--src/ext/UI/ui_t.proj17
-rw-r--r--src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs61
-rw-r--r--src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj7
-rw-r--r--src/ext/Util/util.cmd45
-rw-r--r--src/ext/Util/util_t.proj17
-rw-r--r--src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/VisualStudioExtensionFixture.cs11
-rw-r--r--src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/WixToolsetTest.VisualStudio.csproj7
-rw-r--r--src/ext/VisualStudio/visualstudio_t.proj17
-rw-r--r--src/ext/VisualStudio/vs.cmd21
-rw-r--r--src/ext/ext.cmd53
-rw-r--r--src/ext/ext_t.proj30
-rw-r--r--src/internal/SetBuildNumber/Directory.Packages.props.pp6
-rw-r--r--src/internal/SetBuildNumber/global.json.pp3
-rw-r--r--src/internal/WixInternal.MSTestSupport/Builder.cs204
-rw-r--r--src/internal/WixInternal.MSTestSupport/DisposableFileSystem.cs94
-rw-r--r--src/internal/WixInternal.MSTestSupport/DotnetRunner.cs57
-rw-r--r--src/internal/WixInternal.MSTestSupport/ExternalExecutable.cs374
-rw-r--r--src/internal/WixInternal.MSTestSupport/ExternalExecutableResult.cs19
-rw-r--r--src/internal/WixInternal.MSTestSupport/FakeBuildEngine.cs33
-rw-r--r--src/internal/WixInternal.MSTestSupport/MsbuildRunner.cs112
-rw-r--r--src/internal/WixInternal.MSTestSupport/MsbuildRunnerResult.cs19
-rw-r--r--src/internal/WixInternal.MSTestSupport/MsbuildUtilities.cs99
-rw-r--r--src/internal/WixInternal.MSTestSupport/Pushd.cs46
-rw-r--r--src/internal/WixInternal.MSTestSupport/Query.cs207
-rw-r--r--src/internal/WixInternal.MSTestSupport/RobocopyRunner.cs16
-rw-r--r--src/internal/WixInternal.MSTestSupport/TestData.cs78
-rw-r--r--src/internal/WixInternal.MSTestSupport/TestDataFolderFileSystem.cs42
-rw-r--r--src/internal/WixInternal.MSTestSupport/VswhereRunner.cs41
-rw-r--r--src/internal/WixInternal.MSTestSupport/WixAssert.cs164
-rw-r--r--src/internal/WixInternal.MSTestSupport/WixInternal.MSTestSupport.csproj27
-rw-r--r--src/internal/WixInternal.TestSupport/WixAssert.cs143
-rw-r--r--src/internal/WixInternal.TestSupport/XunitExtensions/WixAssert.cs26
-rw-r--r--src/internal/internal.sln36
-rw-r--r--src/internal/internal_t.proj1
-rw-r--r--src/wix.runsettings7
-rw-r--r--src/wix/WixInternal.Core.MSTestPackage/BundleExtractor.cs156
-rw-r--r--src/wix/WixInternal.Core.MSTestPackage/ExtractBAContainerResult.cs156
-rw-r--r--src/wix/WixInternal.Core.MSTestPackage/TestMessageListener.cs57
-rw-r--r--src/wix/WixInternal.Core.MSTestPackage/WixInternal.Core.MSTestPackage.csproj35
-rw-r--r--src/wix/WixInternal.Core.MSTestPackage/WixMessageFormatter.cs40
-rw-r--r--src/wix/WixInternal.Core.MSTestPackage/WixRunner.cs90
-rw-r--r--src/wix/WixInternal.Core.MSTestPackage/WixRunnerResult.cs62
-rw-r--r--src/wix/WixInternal.Core.MSTestPackage/XmlNodeExtensions.cs115
-rw-r--r--src/wix/pack_t.proj1
-rw-r--r--src/wix/wix.sln18
96 files changed, 3204 insertions, 767 deletions
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 2de04127..883aba42 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -11,7 +11,9 @@
11 <ProjectName Condition=" '$(ProjectName)' == '' ">$(MSBuildProjectName)</ProjectName> 11 <ProjectName Condition=" '$(ProjectName)' == '' ">$(MSBuildProjectName)</ProjectName>
12 <RootBuildFolder>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))</RootBuildFolder> 12 <RootBuildFolder>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))</RootBuildFolder>
13 <RootPackagesFolder>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\packages\))</RootPackagesFolder> 13 <RootPackagesFolder>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\packages\))</RootPackagesFolder>
14 <PdbsFolder>$(RootBuildFolder)logs\pdbs\$(Configuration)\</PdbsFolder> 14 <LogsFolder>$(RootBuildFolder)logs\</LogsFolder>
15 <TestResultsFolder>$(LogsFolder)TestResults\</TestResultsFolder>
16 <PdbsFolder>$(LogsFolder)pdbs\$(Configuration)\</PdbsFolder>
15 <ArtifactsFolder>$(RootBuildFolder)artifacts\</ArtifactsFolder> 17 <ArtifactsFolder>$(RootBuildFolder)artifacts\</ArtifactsFolder>
16 <ToolsFolder>$(RootBuildFolder).tools</ToolsFolder> 18 <ToolsFolder>$(RootBuildFolder).tools</ToolsFolder>
17 <PackageOutputPath>$(ArtifactsFolder)</PackageOutputPath> 19 <PackageOutputPath>$(ArtifactsFolder)</PackageOutputPath>
diff --git a/src/Directory.csproj.targets b/src/Directory.csproj.targets
index 2c6abce3..ed041bb8 100644
--- a/src/Directory.csproj.targets
+++ b/src/Directory.csproj.targets
@@ -7,18 +7,36 @@
7 <DefineConstants Condition=" '$(Configuration)'=='Debug' ">$(DefineConstants);DEBUG</DefineConstants> 7 <DefineConstants Condition=" '$(Configuration)'=='Debug' ">$(DefineConstants);DEBUG</DefineConstants>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <PropertyGroup Condition=" '$(IsWixTestProject)'=='true' "> 10 <PropertyGroup Condition=" '$(IsWixTestProject)'=='true' OR '$(IsWixMSTestProject)'=='true' ">
11 <RollForward>Major</RollForward> 11 <RollForward>Major</RollForward>
12 <IsPackable>false</IsPackable> 12 <IsPackable>false</IsPackable>
13 <SignOutput>false</SignOutput> 13 <SignOutput>false</SignOutput>
14 </PropertyGroup> 14 </PropertyGroup>
15 15
16
17 <PropertyGroup Condition=" '$(IsWixMSTestProject)' == 'true' ">
18 <!-- Force a .NET v6-compatible package. -->
19 <MicrosoftTestingExtensionsCodeCoverageVersion>17.11.5</MicrosoftTestingExtensionsCodeCoverageVersion>
20 <TestingPlatformShowTestsFailure>true</TestingPlatformShowTestsFailure>
21 </PropertyGroup>
22
23 <Target Name="RunWixTests" AfterTargets="Build" Condition=" '$(IsWixMSTestProject)' == 'true' AND '$(SuppressWixTests)' != 'true' ">
24 <Delete Files="$(TestResultsFolder)$(MSBuildProjectName).trx" />
25
26 <Exec
27 Command="$(TargetPath.Replace('.dll', '.exe')) --results-directory $(TestResultsFolder) --report-trx --report-trx-filename $(MSBuildProjectName).trx --no-progress --settings $([MSBuild]::GetPathOfFileAbove('wix.runsettings'))"
28 UseCommandProcessor="false"
29 CustomErrorRegularExpression=" Test method .+ threw exception:" />
30 </Target>
31
32
16 <ItemGroup Condition=" '$(IsWixTestProject)'=='true' "> 33 <ItemGroup Condition=" '$(IsWixTestProject)'=='true' ">
17 <PackageReference Include="Microsoft.NET.Test.Sdk" /> 34 <PackageReference Include="Microsoft.NET.Test.Sdk" />
18 <PackageReference Include="xunit" /> 35 <PackageReference Include="xunit" />
19 <PackageReference Include="xunit.runner.visualstudio" PrivateAssets="All" /> 36 <PackageReference Include="xunit.runner.visualstudio" PrivateAssets="All" />
20 </ItemGroup> 37 </ItemGroup>
21 38
39
22 <ItemGroup Condition=" '$(IsWixTestProject)'!='true' "> 40 <ItemGroup Condition=" '$(IsWixTestProject)'!='true' ">
23 <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" /> 41 <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
24 </ItemGroup> 42 </ItemGroup>
diff --git a/src/clean.cmd b/src/clean.cmd
index 6164a8f9..dc69f855 100644
--- a/src/clean.cmd
+++ b/src/clean.cmd
@@ -19,7 +19,9 @@ if exist ..\global.json (del ..\global.json)
19 19
20if exist "%_NUGET_CACHE%\wixinternal.basebuildtasks.sources" rd /s/q "%_NUGET_CACHE%\wixinternal.basebuildtasks.sources" 20if exist "%_NUGET_CACHE%\wixinternal.basebuildtasks.sources" rd /s/q "%_NUGET_CACHE%\wixinternal.basebuildtasks.sources"
21if exist "%_NUGET_CACHE%\wixinternal.testsupport" rd /s/q "%_NUGET_CACHE%\wixinternal.testsupport" 21if exist "%_NUGET_CACHE%\wixinternal.testsupport" rd /s/q "%_NUGET_CACHE%\wixinternal.testsupport"
22if exist "%_NUGET_CACHE%\wixinternal.mstestsupport" rd /s/q "%_NUGET_CACHE%\wixinternal.mstestsupport"
22if exist "%_NUGET_CACHE%\wixinternal.core.testpackage" rd /s/q "%_NUGET_CACHE%\wixinternal.core.testpackage" 23if exist "%_NUGET_CACHE%\wixinternal.core.testpackage" rd /s/q "%_NUGET_CACHE%\wixinternal.core.testpackage"
24if exist "%_NUGET_CACHE%\wixinternal.core.mstestpackage" rd /s/q "%_NUGET_CACHE%\wixinternal.core.mstestpackage"
23if exist "%_NUGET_CACHE%\wixtoolset.bal.wixext" rd /s/q "%_NUGET_CACHE%\wixtoolset.bal.wixext" 25if exist "%_NUGET_CACHE%\wixtoolset.bal.wixext" rd /s/q "%_NUGET_CACHE%\wixtoolset.bal.wixext"
24if exist "%_NUGET_CACHE%\wixtoolset.bootstrapperapplications.wixext" rd /s/q "%_NUGET_CACHE%\wixtoolset.bootstrapperapplications.wixext" 26if exist "%_NUGET_CACHE%\wixtoolset.bootstrapperapplications.wixext" rd /s/q "%_NUGET_CACHE%\wixtoolset.bootstrapperapplications.wixext"
25if exist "%_NUGET_CACHE%\wixtoolset.bootstrapperextensionapi" rd /s/q "%_NUGET_CACHE%\wixtoolset.bootstrapperextensionapi" 27if exist "%_NUGET_CACHE%\wixtoolset.bootstrapperextensionapi" rd /s/q "%_NUGET_CACHE%\wixtoolset.bootstrapperextensionapi"
diff --git a/src/ext/Bal/bal.cmd b/src/ext/Bal/bal.cmd
deleted file mode 100644
index df9ceca4..00000000
--- a/src/ext/Bal/bal.cmd
+++ /dev/null
@@ -1,55 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5@set _L=%~dp0..\..\..\build\logs
6
7:parse_args
8@if /i "%1"=="release" set _C=Release
9@if /i "%1"=="inc" set _INC=1
10@if /i "%1"=="clean" set _CLEAN=1
11@if not "%1"=="" shift & goto parse_args
12
13@set _B=%~dp0..\..\..\build\Bal.wixext\%_C%
14
15:: Clean
16
17@if "%_INC%"=="" call :clean
18@if NOT "%_CLEAN%"=="" goto :end
19
20@echo Building ext\Bal %_C% using %_N%
21
22:: Restore
23:: Build
24:: Pack
25:: Note: This test project must be restored and built directly to get all its support files laid out correctly.
26:: Everything else is built by the traversal project.
27msbuild -Restore -p:Configuration=%_C% -tl -nologo -m -warnaserror test\WixToolsetTest.BootstrapperApplications\WixToolsetTest.BootstrapperApplications.csproj -bl:%_L%\ext_bal_build.binlog || exit /b
28
29msbuild bal_t.proj -p:Configuration=%_C% -tl -nologo -warnaserror -bl:%_L%\bal_build.binlog || exit /b
30
31:: Test
32dotnet test ^
33 %_B%\x86\WixStdFnUnitTest.dll ^
34 %_B%\net6.0\WixToolsetTest.BootstrapperApplications.dll ^
35 --nologo -l "trx;LogFileName=%_L%\TestResults\bal.wixext.trx" || exit /b
36
37@goto :end
38
39:clean
40@rd /s/q "..\..\..\build\Bal.wixext" 2> nul
41@del "..\..\..\build\artifacts\WixToolset.Bal.wixext.*.nupkg" 2> nul
42@del "..\..\..\build\artifacts\WixToolset.BootstrapperApplications.wixext.*.nupkg" 2> nul
43@del "..\..\..\build\artifacts\WixToolset.WixStandardBootstrapperApplicationFunctionApi.*.nupkg" 2> nul
44@del "%_L%\ext_bal_build.binlog" 2> nul
45@del "%_L%\bal_fnsapi_build.binlog" 2> nul
46@del "%_L%\bal_examples_build.binlog" 2> nul
47@del "%_L%\TestResults\bal.wixext.trx" 2> nul
48@rd /s/q "%USERPROFILE%\.nuget\packages\wixtoolset.bal.wixext" 2> nul
49@rd /s/q "%USERPROFILE%\.nuget\packages\wixtoolset.bootstrapperapplications.wixext" 2> nul
50@rd /s/q "%USERPROFILE%\.nuget\packages\wixtoolset.wixstandardbootstrapperapplicationfunctionapi" 2> nul
51@exit /b
52
53:end
54@popd
55@endlocal
diff --git a/src/ext/Bal/bal_t.proj b/src/ext/Bal/bal_t.proj
index a0e66e97..da83b47f 100644
--- a/src/ext/Bal/bal_t.proj
+++ b/src/ext/Bal/bal_t.proj
@@ -3,13 +3,6 @@
3 3
4<Project Sdk="Microsoft.Build.Traversal"> 4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup> 5 <ItemGroup>
6 <!-- Restore: Explicitly restore the test projects, which need some hand-holding. -->
7 <ProjectReference Include="test\WixStdFnUnitTest\WixStdFnUnitTest.vcxproj" Targets="Restore" BuildInParallel="false" />
8 <ProjectReference Include="test\examples\examples.proj" Targets="Restore" />
9 <ProjectReference Include="wixext-backward-compatible\WixToolset.Bal.wixext.csproj" Targets="Restore" />
10
11 <!-- Build -->
12
13 <!-- C++/CLI projects will try to build their dependent projects in parallel with others, so they must be built first. --> 6 <!-- C++/CLI projects will try to build their dependent projects in parallel with others, so they must be built first. -->
14 <ProjectReference Include="test\WixStdFnUnitTest\WixStdFnUnitTest.vcxproj" Properties="Platform=x86" BuildInParallel="false" /> 7 <ProjectReference Include="test\WixStdFnUnitTest\WixStdFnUnitTest.vcxproj" Properties="Platform=x86" BuildInParallel="false" />
15 8
@@ -17,11 +10,33 @@
17 <ProjectReference Include="wixstdfn\wixstdfn.vcxproj" Properties="Platform=x64" /> 10 <ProjectReference Include="wixstdfn\wixstdfn.vcxproj" Properties="Platform=x64" />
18 <ProjectReference Include="wixstdfn\wixstdfn.vcxproj" Properties="Platform=ARM64" /> 11 <ProjectReference Include="wixstdfn\wixstdfn.vcxproj" Properties="Platform=ARM64" />
19 12
20 <ProjectReference Include="test\examples\examples.proj" /> 13 <ProjectReference Include="test\WixToolsetTest.BootstrapperApplications\WixToolsetTest.BootstrapperApplications.csproj" Properties="Platform=x64" />
21 14
22 <!-- Pack -->
23 <ProjectReference Include="wixstdfn\wixstdfn.vcxproj" Properties="NoBuild=true" Targets="PackNative" /> 15 <ProjectReference Include="wixstdfn\wixstdfn.vcxproj" Properties="NoBuild=true" Targets="PackNative" />
24 <ProjectReference Include="wixext\WixToolset.BootstrapperApplications.wixext.csproj" Properties="NoBuild=true" Targets="Pack" /> 16 <ProjectReference Include="wixext\WixToolset.BootstrapperApplications.wixext.csproj" Properties="NoBuild=true" Targets="Pack" />
25 <ProjectReference Include="wixext-backward-compatible\WixToolset.Bal.wixext.csproj" Targets="Pack" /> 17 <ProjectReference Include="wixext-backward-compatible\WixToolset.Bal.wixext.csproj" Targets="Pack" />
18
19 <ProjectReference Include="test\examples\examples.proj" />
20
21 <!--
22 Currently there are no unskipped unit tests in this project. Should that change,
23 we'll need to update the native test framework or figure out something else.
24
25 <ProjectReference Include="ext\Bal\test\WixStdFnUnitTest\WixStdFnUnitTest.vcxproj" />
26 -->
26 </ItemGroup> 27 </ItemGroup>
28
29 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
30 <RemoveDir Directories="$(RootBuildFolder)Bal.wixext" />
31 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.bal.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
32 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.bal.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
33 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.bootstrapperapplications.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
34 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.bootstrapperapplications.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
35 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.wixstandardbootstrapperapplicationfunctionapi.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
36 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.wixstandardbootstrapperapplicationfunctionapi.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
37
38 <Delete Files="$(ArtifactsFolder)WixToolset.Bal.wixext.*.nupkg" />
39 <Delete Files="$(ArtifactsFolder)WixToolset.BootstrapperApplications.wixext.*.nupkg" />
40 <Delete Files="$(ArtifactsFolder)WixToolset.WixStandardBootstrapperApplicationFunctionApi.wixext.*.nupkg" />
41 </Target>
27</Project> 42</Project>
diff --git a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs
index 2e21ef90..6e24ad72 100644
--- a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs
+++ b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs
@@ -6,13 +6,14 @@ namespace WixToolsetTest.BootstrapperApplications
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.IO; 7 using System.IO;
8 using System.Linq; 8 using System.Linq;
9 using WixInternal.Core.TestPackage; 9 using Microsoft.VisualStudio.TestTools.UnitTesting;
10 using WixInternal.TestSupport; 10 using WixInternal.Core.MSTestPackage;
11 using Xunit; 11 using WixInternal.MSTestSupport;
12 12
13 [TestClass]
13 public class BalExtensionFixture 14 public class BalExtensionFixture
14 { 15 {
15 [Fact] 16 [TestMethod]
16 public void CanBuildUsingDisplayInternalUICondition() 17 public void CanBuildUsingDisplayInternalUICondition()
17 { 18 {
18 using (var fs = new DisposableFileSystem()) 19 using (var fs = new DisposableFileSystem())
@@ -35,7 +36,7 @@ namespace WixToolsetTest.BootstrapperApplications
35 }); 36 });
36 compileResult.AssertSuccess(); 37 compileResult.AssertSuccess();
37 38
38 Assert.True(File.Exists(bundleFile)); 39 Assert.IsTrue(File.Exists(bundleFile));
39 40
40 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); 41 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
41 extractResult.AssertSuccess(); 42 extractResult.AssertSuccess();
@@ -46,11 +47,11 @@ namespace WixToolsetTest.BootstrapperApplications
46 "<WixBalPackageInfo PackageId='test.msi' DisplayInternalUICondition='1' />", 47 "<WixBalPackageInfo PackageId='test.msi' DisplayInternalUICondition='1' />",
47 }, balPackageInfos); 48 }, balPackageInfos);
48 49
49 Assert.True(File.Exists(Path.Combine(baFolderPath, "thm.wxl"))); 50 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "thm.wxl")));
50 } 51 }
51 } 52 }
52 53
53 [Fact] 54 [TestMethod]
54 public void CanBuildUsingBootstrapperApplicationId() 55 public void CanBuildUsingBootstrapperApplicationId()
55 { 56 {
56 using (var fs = new DisposableFileSystem()) 57 using (var fs = new DisposableFileSystem())
@@ -73,7 +74,7 @@ namespace WixToolsetTest.BootstrapperApplications
73 }); 74 });
74 compileResult.AssertSuccess(); 75 compileResult.AssertSuccess();
75 76
76 Assert.True(File.Exists(bundleFile)); 77 Assert.IsTrue(File.Exists(bundleFile));
77 78
78 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); 79 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
79 extractResult.AssertSuccess(); 80 extractResult.AssertSuccess();
@@ -91,7 +92,7 @@ namespace WixToolsetTest.BootstrapperApplications
91 } 92 }
92 } 93 }
93 94
94 [Fact] 95 [TestMethod]
95 public void CanBuildUsingOverridable() 96 public void CanBuildUsingOverridable()
96 { 97 {
97 using (var fs = new DisposableFileSystem()) 98 using (var fs = new DisposableFileSystem())
@@ -113,7 +114,7 @@ namespace WixToolsetTest.BootstrapperApplications
113 }); 114 });
114 compileResult.AssertSuccess(); 115 compileResult.AssertSuccess();
115 116
116 Assert.True(File.Exists(bundleFile)); 117 Assert.IsTrue(File.Exists(bundleFile));
117 118
118 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); 119 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
119 extractResult.AssertSuccess(); 120 extractResult.AssertSuccess();
@@ -132,7 +133,7 @@ namespace WixToolsetTest.BootstrapperApplications
132 } 133 }
133 } 134 }
134 135
135 [Fact] 136 [TestMethod]
136 public void CanBuildUsingWixStdBa() 137 public void CanBuildUsingWixStdBa()
137 { 138 {
138 using (var fs = new DisposableFileSystem()) 139 using (var fs = new DisposableFileSystem())
@@ -152,11 +153,11 @@ namespace WixToolsetTest.BootstrapperApplications
152 }); 153 });
153 compileResult.AssertSuccess(); 154 compileResult.AssertSuccess();
154 155
155 Assert.True(File.Exists(bundleFile)); 156 Assert.IsTrue(File.Exists(bundleFile));
156 } 157 }
157 } 158 }
158 159
159 //[Fact] 160 // [TestMethod]
160 //public void CanBuildUsingMBAWithAlwaysInstallPrereqs() 161 //public void CanBuildUsingMBAWithAlwaysInstallPrereqs()
161 //{ 162 //{
162 // using (var fs = new DisposableFileSystem()) 163 // using (var fs = new DisposableFileSystem())
@@ -179,7 +180,7 @@ namespace WixToolsetTest.BootstrapperApplications
179 180
180 // compileResult.AssertSuccess(); 181 // compileResult.AssertSuccess();
181 182
182 // Assert.True(File.Exists(bundleFile)); 183 // Assert.IsTrue(File.Exists(bundleFile));
183 184
184 // var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); 185 // var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
185 // extractResult.AssertSuccess(); 186 // extractResult.AssertSuccess();
@@ -198,7 +199,7 @@ namespace WixToolsetTest.BootstrapperApplications
198 // } 199 // }
199 //} 200 //}
200 201
201 [Fact] 202 [TestMethod]
202 public void CannotBuildUsingMBAWithNoPrereqs() 203 public void CannotBuildUsingMBAWithNoPrereqs()
203 { 204 {
204 using (var fs = new DisposableFileSystem()) 205 using (var fs = new DisposableFileSystem())
@@ -223,14 +224,14 @@ namespace WixToolsetTest.BootstrapperApplications
223 { 224 {
224 "The WixManagedBootstrapperApplicationHost element has been deprecated.", 225 "The WixManagedBootstrapperApplicationHost element has been deprecated.",
225 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 226 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
226 Assert.Equal(1130, compileResult.ExitCode); 227 Assert.AreEqual(1130, compileResult.ExitCode);
227 228
228 Assert.False(File.Exists(bundleFile)); 229 Assert.IsFalse(File.Exists(bundleFile));
229 Assert.False(File.Exists(Path.Combine(intermediateFolder, "test.exe"))); 230 Assert.IsFalse(File.Exists(Path.Combine(intermediateFolder, "test.exe")));
230 } 231 }
231 } 232 }
232 233
233 [Fact] 234 [TestMethod]
234 public void CannotBuildUsingDncbaMissingBAFactoryPayload() 235 public void CannotBuildUsingDncbaMissingBAFactoryPayload()
235 { 236 {
236 using (var fs = new DisposableFileSystem()) 237 using (var fs = new DisposableFileSystem())
@@ -254,14 +255,14 @@ namespace WixToolsetTest.BootstrapperApplications
254 "The WixDotNetCoreBootstrapperApplicationHost element has been deprecated.", 255 "The WixDotNetCoreBootstrapperApplicationHost element has been deprecated.",
255 "The BootstrapperApplication element's Name or SourceFile attribute was not found; one of these is required." 256 "The BootstrapperApplication element's Name or SourceFile attribute was not found; one of these is required."
256 }, compileResult.Messages.Select(x => x.ToString()).ToArray()); 257 }, compileResult.Messages.Select(x => x.ToString()).ToArray());
257 Assert.Equal(44, compileResult.ExitCode); 258 Assert.AreEqual(44, compileResult.ExitCode);
258 259
259 Assert.False(File.Exists(bundleFile)); 260 Assert.IsFalse(File.Exists(bundleFile));
260 Assert.False(File.Exists(Path.Combine(intermediateFolder, "test.exe"))); 261 Assert.IsFalse(File.Exists(Path.Combine(intermediateFolder, "test.exe")));
261 } 262 }
262 } 263 }
263 264
264 [Fact] 265 [TestMethod]
265 public void CannotBuildUsingOverridableWrongCase() 266 public void CannotBuildUsingOverridableWrongCase()
266 { 267 {
267 using (var fs = new DisposableFileSystem()) 268 using (var fs = new DisposableFileSystem())
@@ -284,7 +285,7 @@ namespace WixToolsetTest.BootstrapperApplications
284 "-o", bundleFile, 285 "-o", bundleFile,
285 }); 286 });
286 287
287 Assert.InRange(result.ExitCode, 2, Int32.MaxValue); 288 Assert.IsTrue(result.ExitCode >= 2 && result.ExitCode <= Int32.MaxValue);
288 289
289 var messages = result.Messages.Select(m => m.ToString()).ToList(); 290 var messages = result.Messages.Select(m => m.ToString()).ToList();
290 messages.Sort(); 291 messages.Sort();
diff --git a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs
index 58d5d551..72e31540 100644
--- a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs
+++ b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs
@@ -5,13 +5,14 @@ namespace WixToolsetTest.BootstrapperApplications
5 using System.IO; 5 using System.IO;
6 using System.Linq; 6 using System.Linq;
7 using System.Xml; 7 using System.Xml;
8 using WixInternal.Core.TestPackage; 8 using Microsoft.VisualStudio.TestTools.UnitTesting;
9 using WixInternal.TestSupport; 9 using WixInternal.Core.MSTestPackage;
10 using Xunit; 10 using WixInternal.MSTestSupport;
11 11
12 [TestClass]
12 public class InternalUIBAFixture 13 public class InternalUIBAFixture
13 { 14 {
14 [Fact] 15 [TestMethod]
15 public void CanBuildUsingWixIuiBa() 16 public void CanBuildUsingWixIuiBa()
16 { 17 {
17 using (var fs = new DisposableFileSystem()) 18 using (var fs = new DisposableFileSystem())
@@ -34,7 +35,7 @@ namespace WixToolsetTest.BootstrapperApplications
34 }); 35 });
35 compileResult.AssertSuccess(); 36 compileResult.AssertSuccess();
36 37
37 Assert.True(File.Exists(bundleFile)); 38 Assert.IsTrue(File.Exists(bundleFile));
38 39
39 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); 40 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
40 extractResult.AssertSuccess(); 41 extractResult.AssertSuccess();
@@ -45,12 +46,12 @@ namespace WixToolsetTest.BootstrapperApplications
45 "<WixBalPackageInfo PackageId='test.msi' PrimaryPackageType='default' />", 46 "<WixBalPackageInfo PackageId='test.msi' PrimaryPackageType='default' />",
46 }, balPackageInfos); 47 }, balPackageInfos);
47 48
48 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm"))); 49 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm")));
49 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl"))); 50 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl")));
50 } 51 }
51 } 52 }
52 53
53 [Fact] 54 [TestMethod]
54 public void CanBuildUsingWixIuiBaWithUrlPrereqPackage() 55 public void CanBuildUsingWixIuiBaWithUrlPrereqPackage()
55 { 56 {
56 using (var fs = new DisposableFileSystem()) 57 using (var fs = new DisposableFileSystem())
@@ -73,7 +74,7 @@ namespace WixToolsetTest.BootstrapperApplications
73 }); 74 });
74 compileResult.AssertSuccess(); 75 compileResult.AssertSuccess();
75 76
76 Assert.True(File.Exists(bundleFile)); 77 Assert.IsTrue(File.Exists(bundleFile));
77 78
78 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); 79 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
79 extractResult.AssertSuccess(); 80 extractResult.AssertSuccess();
@@ -90,12 +91,12 @@ namespace WixToolsetTest.BootstrapperApplications
90 "<WixPrereqInformation PackageId='wixnative.exe' LicenseUrl='https://www.mysite.com/prereqterms' />", 91 "<WixPrereqInformation PackageId='wixnative.exe' LicenseUrl='https://www.mysite.com/prereqterms' />",
91 }, mbaPrereqInfos); 92 }, mbaPrereqInfos);
92 93
93 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm"))); 94 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm")));
94 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl"))); 95 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl")));
95 } 96 }
96 } 97 }
97 98
98 [Fact] 99 [TestMethod]
99 public void CanBuildUsingWixIuiBaWithImplicitPrimaryPackage() 100 public void CanBuildUsingWixIuiBaWithImplicitPrimaryPackage()
100 { 101 {
101 using (var fs = new DisposableFileSystem()) 102 using (var fs = new DisposableFileSystem())
@@ -118,7 +119,7 @@ namespace WixToolsetTest.BootstrapperApplications
118 }); 119 });
119 compileResult.AssertSuccess(); 120 compileResult.AssertSuccess();
120 121
121 Assert.True(File.Exists(bundleFile)); 122 Assert.IsTrue(File.Exists(bundleFile));
122 123
123 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); 124 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
124 extractResult.AssertSuccess(); 125 extractResult.AssertSuccess();
@@ -135,12 +136,12 @@ namespace WixToolsetTest.BootstrapperApplications
135 "<WixPrereqInformation PackageId='wixnative.exe' />", 136 "<WixPrereqInformation PackageId='wixnative.exe' />",
136 }, mbaPrereqInfos); 137 }, mbaPrereqInfos);
137 138
138 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm"))); 139 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm")));
139 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl"))); 140 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl")));
140 } 141 }
141 } 142 }
142 143
143 [Fact] 144 [TestMethod]
144 public void CanBuildUsingWixIuiBaWithWarnings() 145 public void CanBuildUsingWixIuiBaWithWarnings()
145 { 146 {
146 using (var fs = new DisposableFileSystem()) 147 using (var fs = new DisposableFileSystem())
@@ -172,7 +173,7 @@ namespace WixToolsetTest.BootstrapperApplications
172 173
173 compileResult.AssertSuccess(); 174 compileResult.AssertSuccess();
174 175
175 Assert.True(File.Exists(bundleFile)); 176 Assert.IsTrue(File.Exists(bundleFile));
176 177
177 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); 178 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
178 extractResult.AssertSuccess(); 179 extractResult.AssertSuccess();
@@ -189,12 +190,12 @@ namespace WixToolsetTest.BootstrapperApplications
189 "<WixPrereqInformation PackageId='wixnative.exe' />", 190 "<WixPrereqInformation PackageId='wixnative.exe' />",
190 }, mbaPrereqInfos); 191 }, mbaPrereqInfos);
191 192
192 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm"))); 193 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm")));
193 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl"))); 194 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl")));
194 } 195 }
195 } 196 }
196 197
197 [Fact] 198 [TestMethod]
198 public void CanBuildUsingWixIuiBaAndForcedCachePrimaryPackage() 199 public void CanBuildUsingWixIuiBaAndForcedCachePrimaryPackage()
199 { 200 {
200 using (var fs = new DisposableFileSystem()) 201 using (var fs = new DisposableFileSystem())
@@ -218,7 +219,7 @@ namespace WixToolsetTest.BootstrapperApplications
218 219
219 compileResult.AssertSuccess(); 220 compileResult.AssertSuccess();
220 221
221 Assert.True(File.Exists(bundleFile)); 222 Assert.IsTrue(File.Exists(bundleFile));
222 223
223 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); 224 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
224 extractResult.AssertSuccess(); 225 extractResult.AssertSuccess();
@@ -239,8 +240,8 @@ namespace WixToolsetTest.BootstrapperApplications
239 "<WixPrereqInformation PackageId='wixnative.exe' />", 240 "<WixPrereqInformation PackageId='wixnative.exe' />",
240 }, mbaPrereqInfos); 241 }, mbaPrereqInfos);
241 242
242 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm"))); 243 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.thm")));
243 Assert.True(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl"))); 244 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "wixpreq.wxl")));
244 } 245 }
245 246
246 static void AssertCacheType(XmlNode node) 247 static void AssertCacheType(XmlNode node)
@@ -251,16 +252,16 @@ namespace WixToolsetTest.BootstrapperApplications
251 252
252 if (package == "test.msi") 253 if (package == "test.msi")
253 { 254 {
254 Assert.Equal("force", cache); 255 Assert.AreEqual("force", cache);
255 } 256 }
256 else if (package == "wixnative.exe") 257 else if (package == "wixnative.exe")
257 { 258 {
258 Assert.Equal("keep", cache); 259 Assert.AreEqual("keep", cache);
259 } 260 }
260 } 261 }
261 } 262 }
262 263
263 [Fact] 264 [TestMethod]
264 public void CannotBuildUsingWixIuiBaWithAllPrereqPackages() 265 public void CannotBuildUsingWixIuiBaWithAllPrereqPackages()
265 { 266 {
266 using (var fs = new DisposableFileSystem()) 267 using (var fs = new DisposableFileSystem())
@@ -285,11 +286,11 @@ namespace WixToolsetTest.BootstrapperApplications
285 "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".", 286 "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".",
286 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 287 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
287 288
288 Assert.Equal(6808, compileResult.ExitCode); 289 Assert.AreEqual(6808, compileResult.ExitCode);
289 } 290 }
290 } 291 }
291 292
292 [Fact] 293 [TestMethod]
293 public void CannotBuildUsingWixIuiBaWithImplicitNonMsiPrimaryPackage() 294 public void CannotBuildUsingWixIuiBaWithImplicitNonMsiPrimaryPackage()
294 { 295 {
295 using (var fs = new DisposableFileSystem()) 296 using (var fs = new DisposableFileSystem())
@@ -314,11 +315,11 @@ namespace WixToolsetTest.BootstrapperApplications
314 "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.", 315 "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.",
315 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 316 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
316 317
317 Assert.Equal(6811, compileResult.ExitCode); 318 Assert.AreEqual(6811, compileResult.ExitCode);
318 } 319 }
319 } 320 }
320 321
321 [Fact] 322 [TestMethod]
322 public void CannotBuildUsingWixIuiBaWithImplicitPrimaryPackageEnableFeatureSelection() 323 public void CannotBuildUsingWixIuiBaWithImplicitPrimaryPackageEnableFeatureSelection()
323 { 324 {
324 using (var fs = new DisposableFileSystem()) 325 using (var fs = new DisposableFileSystem())
@@ -343,11 +344,11 @@ namespace WixToolsetTest.BootstrapperApplications
343 "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.", 344 "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.",
344 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 345 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
345 346
346 Assert.Equal(6811, compileResult.ExitCode); 347 Assert.AreEqual(6811, compileResult.ExitCode);
347 } 348 }
348 } 349 }
349 350
350 [Fact] 351 [TestMethod]
351 public void CannotBuildUsingWixIuiBaWithMultipleNonPermanentNonPrimaryPackages() 352 public void CannotBuildUsingWixIuiBaWithMultipleNonPermanentNonPrimaryPackages()
352 { 353 {
353 using (var fs = new DisposableFileSystem()) 354 using (var fs = new DisposableFileSystem())
@@ -373,11 +374,11 @@ namespace WixToolsetTest.BootstrapperApplications
373 "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.", 374 "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.",
374 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 375 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
375 376
376 Assert.Equal(6811, compileResult.ExitCode); 377 Assert.AreEqual(6811, compileResult.ExitCode);
377 } 378 }
378 } 379 }
379 380
380 [Fact] 381 [TestMethod]
381 public void CannotBuildUsingWixIuiBaWithMultiplePrimaryPackagesOfSameType() 382 public void CannotBuildUsingWixIuiBaWithMultiplePrimaryPackagesOfSameType()
382 { 383 {
383 using (var fs = new DisposableFileSystem()) 384 using (var fs = new DisposableFileSystem())
@@ -403,11 +404,11 @@ namespace WixToolsetTest.BootstrapperApplications
403 "The location of the package related to the previous error.", 404 "The location of the package related to the previous error.",
404 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 405 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
405 406
406 Assert.Equal(6810, compileResult.ExitCode); 407 Assert.AreEqual(6810, compileResult.ExitCode);
407 } 408 }
408 } 409 }
409 410
410 [Fact] 411 [TestMethod]
411 public void CannotBuildUsingWixIuiBaWithNoDefaultPrimaryPackage() 412 public void CannotBuildUsingWixIuiBaWithNoDefaultPrimaryPackage()
412 { 413 {
413 using (var fs = new DisposableFileSystem()) 414 using (var fs = new DisposableFileSystem())
@@ -432,11 +433,11 @@ namespace WixToolsetTest.BootstrapperApplications
432 "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".", 433 "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".",
433 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 434 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
434 435
435 Assert.Equal(6808, compileResult.ExitCode); 436 Assert.AreEqual(6808, compileResult.ExitCode);
436 } 437 }
437 } 438 }
438 439
439 [Fact] 440 [TestMethod]
440 public void CannotBuildUsingWixIuiBaWithNonMsiPrimaryPackage() 441 public void CannotBuildUsingWixIuiBaWithNonMsiPrimaryPackage()
441 { 442 {
442 using (var fs = new DisposableFileSystem()) 443 using (var fs = new DisposableFileSystem())
@@ -461,11 +462,11 @@ namespace WixToolsetTest.BootstrapperApplications
461 "When using WixInternalUIBootstrapperApplication, each primary package must be an MsiPackage.", 462 "When using WixInternalUIBootstrapperApplication, each primary package must be an MsiPackage.",
462 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 463 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
463 464
464 Assert.Equal(6814, compileResult.ExitCode); 465 Assert.AreEqual(6814, compileResult.ExitCode);
465 } 466 }
466 } 467 }
467 468
468 [Fact] 469 [TestMethod]
469 public void CannotBuildUsingWixIuiBaWithNonPermanentPrereqPackage() 470 public void CannotBuildUsingWixIuiBaWithNonPermanentPrereqPackage()
470 { 471 {
471 using (var fs = new DisposableFileSystem()) 472 using (var fs = new DisposableFileSystem())
@@ -490,11 +491,11 @@ namespace WixToolsetTest.BootstrapperApplications
490 "When using WixInternalUIBootstrapperApplication and bal:PrereqPackage is set to 'yes', the package must be permanent.", 491 "When using WixInternalUIBootstrapperApplication and bal:PrereqPackage is set to 'yes', the package must be permanent.",
491 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 492 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
492 493
493 Assert.Equal(6812, compileResult.ExitCode); 494 Assert.AreEqual(6812, compileResult.ExitCode);
494 } 495 }
495 } 496 }
496 497
497 [Fact] 498 [TestMethod]
498 public void CannotBuildUsingWixIuiBaWithPermanentPrimaryPackage() 499 public void CannotBuildUsingWixIuiBaWithPermanentPrimaryPackage()
499 { 500 {
500 using (var fs = new DisposableFileSystem()) 501 using (var fs = new DisposableFileSystem())
@@ -520,11 +521,11 @@ namespace WixToolsetTest.BootstrapperApplications
520 "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".", 521 "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".",
521 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 522 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
522 523
523 Assert.Equal(6808, compileResult.ExitCode); 524 Assert.AreEqual(6808, compileResult.ExitCode);
524 } 525 }
525 } 526 }
526 527
527 [Fact] 528 [TestMethod]
528 public void CannotBuildUsingWixIuiBaWithPrimaryPackageEnableFeatureSelection() 529 public void CannotBuildUsingWixIuiBaWithPrimaryPackageEnableFeatureSelection()
529 { 530 {
530 using (var fs = new DisposableFileSystem()) 531 using (var fs = new DisposableFileSystem())
@@ -550,11 +551,11 @@ namespace WixToolsetTest.BootstrapperApplications
550 "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".", 551 "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".",
551 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 552 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
552 553
553 Assert.Equal(6808, compileResult.ExitCode); 554 Assert.AreEqual(6808, compileResult.ExitCode);
554 } 555 }
555 } 556 }
556 557
557 [Fact] 558 [TestMethod]
558 public void CannotBuildUsingWixIuiBaWithPrimaryPrereqPackage() 559 public void CannotBuildUsingWixIuiBaWithPrimaryPrereqPackage()
559 { 560 {
560 using (var fs = new DisposableFileSystem()) 561 using (var fs = new DisposableFileSystem())
@@ -578,7 +579,7 @@ namespace WixToolsetTest.BootstrapperApplications
578 "The MsiPackage/@PrereqPackage attribute's value, 'yes', cannot be specified with attribute PrimaryPackageType present.", 579 "The MsiPackage/@PrereqPackage attribute's value, 'yes', cannot be specified with attribute PrimaryPackageType present.",
579 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 580 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
580 581
581 Assert.Equal(193, compileResult.ExitCode); 582 Assert.AreEqual(193, compileResult.ExitCode);
582 } 583 }
583 } 584 }
584 } 585 }
diff --git a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/WixToolsetTest.BootstrapperApplications.csproj b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/WixToolsetTest.BootstrapperApplications.csproj
index 64fc297c..6a9b5856 100644
--- a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/WixToolsetTest.BootstrapperApplications.csproj
+++ b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/WixToolsetTest.BootstrapperApplications.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -20,6 +20,7 @@
20 </ItemGroup> 20 </ItemGroup>
21 21
22 <ItemGroup> 22 <ItemGroup>
23 <PackageReference Include="WixInternal.Core.TestPackage" /> 23 <PackageReference Include="WixInternal.MSTestSupport" />
24 <PackageReference Include="WixInternal.Core.MSTestPackage" />
24 </ItemGroup> 25 </ItemGroup>
25</Project> 26</Project>
diff --git a/src/ext/ComPlus/complus.cmd b/src/ext/ComPlus/complus.cmd
deleted file mode 100644
index 3b3a5772..00000000
--- a/src/ext/ComPlus/complus.cmd
+++ /dev/null
@@ -1,21 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo ComPlus.wixext build %_C%
10
11:: Build
12msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Test
15dotnet test -c %_C% --no-build test\WixToolsetTest.ComPlus || exit /b
16
17:: Pack
18msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.ComPlus.wixext.csproj || exit /b
19
20@popd
21@endlocal \ No newline at end of file
diff --git a/src/ext/ComPlus/complus_t.proj b/src/ext/ComPlus/complus_t.proj
new file mode 100644
index 00000000..439856b6
--- /dev/null
+++ b/src/ext/ComPlus/complus_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.ComPlus\WixToolsetTest.ComPlus.csproj" />
7 <ProjectReference Include="wixext\WixToolset.ComPlus.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)complus.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.complus.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.complus.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.ComPlus.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/ComPlus/test/WixToolsetTest.ComPlus/ComPlusExtensionFixture.cs b/src/ext/ComPlus/test/WixToolsetTest.ComPlus/ComPlusExtensionFixture.cs
index 17c5eb0f..7b38ef54 100644
--- a/src/ext/ComPlus/test/WixToolsetTest.ComPlus/ComPlusExtensionFixture.cs
+++ b/src/ext/ComPlus/test/WixToolsetTest.ComPlus/ComPlusExtensionFixture.cs
@@ -3,14 +3,15 @@
3namespace WixToolsetTest.ComPlus 3namespace WixToolsetTest.ComPlus
4{ 4{
5 using System.Linq; 5 using System.Linq;
6 using WixInternal.TestSupport; 6 using Microsoft.VisualStudio.TestTools.UnitTesting;
7 using WixInternal.Core.TestPackage; 7 using WixInternal.MSTestSupport;
8 using WixInternal.Core.MSTestPackage;
8 using WixToolset.ComPlus; 9 using WixToolset.ComPlus;
9 using Xunit;
10 10
11 [TestClass]
11 public class ComPlusExtensionFixture 12 public class ComPlusExtensionFixture
12 { 13 {
13 [Fact] 14 [TestMethod]
14 public void CanBuildUsingComPlusPartition() 15 public void CanBuildUsingComPlusPartition()
15 { 16 {
16 var folder = TestData.Get(@"TestData\UsingComPlusPartition"); 17 var folder = TestData.Get(@"TestData\UsingComPlusPartition");
diff --git a/src/ext/ComPlus/test/WixToolsetTest.ComPlus/WixToolsetTest.ComPlus.csproj b/src/ext/ComPlus/test/WixToolsetTest.ComPlus/WixToolsetTest.ComPlus.csproj
index a9e9dbef..d0a7081b 100644
--- a/src/ext/ComPlus/test/WixToolsetTest.ComPlus/WixToolsetTest.ComPlus.csproj
+++ b/src/ext/ComPlus/test/WixToolsetTest.ComPlus/WixToolsetTest.ComPlus.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/Dependency/dependency.cmd b/src/ext/Dependency/dependency.cmd
deleted file mode 100644
index 0ebcbfd5..00000000
--- a/src/ext/Dependency/dependency.cmd
+++ /dev/null
@@ -1,21 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo Dependency.wixext build %_C%
10
11:: Build
12msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Test
15dotnet test -c %_C% --no-build test\WixToolsetTest.Dependency || exit /b
16
17:: Pack
18msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.Dependency.wixext.csproj || exit /b
19
20@popd
21@endlocal
diff --git a/src/ext/Dependency/dependency_t.proj b/src/ext/Dependency/dependency_t.proj
new file mode 100644
index 00000000..d05b8de9
--- /dev/null
+++ b/src/ext/Dependency/dependency_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.Dependency\WixToolsetTest.Dependency.csproj" />
7 <ProjectReference Include="wixext\WixToolset.Dependency.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)dependency.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.dependency.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.dependency.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.Dependency.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/Dependency/test/WixToolsetTest.Dependency/DependencyExtensionFixture.cs b/src/ext/Dependency/test/WixToolsetTest.Dependency/DependencyExtensionFixture.cs
index 6190a4e0..ade2a12e 100644
--- a/src/ext/Dependency/test/WixToolsetTest.Dependency/DependencyExtensionFixture.cs
+++ b/src/ext/Dependency/test/WixToolsetTest.Dependency/DependencyExtensionFixture.cs
@@ -4,14 +4,15 @@ namespace WixToolsetTest.Dependency
4{ 4{
5 using System.Linq; 5 using System.Linq;
6 using System.Text.RegularExpressions; 6 using System.Text.RegularExpressions;
7 using WixInternal.TestSupport; 7 using Microsoft.VisualStudio.TestTools.UnitTesting;
8 using WixInternal.Core.TestPackage; 8 using WixInternal.MSTestSupport;
9 using WixInternal.Core.MSTestPackage;
9 using WixToolset.Dependency; 10 using WixToolset.Dependency;
10 using Xunit;
11 11
12 [TestClass]
12 public class DependencyExtensionFixture 13 public class DependencyExtensionFixture
13 { 14 {
14 [Fact] 15 [TestMethod]
15 public void CanBuildUsingProvides() 16 public void CanBuildUsingProvides()
16 { 17 {
17 var folder = TestData.Get(@"TestData\UsingProvides"); 18 var folder = TestData.Get(@"TestData\UsingProvides");
diff --git a/src/ext/Dependency/test/WixToolsetTest.Dependency/WixToolsetTest.Dependency.csproj b/src/ext/Dependency/test/WixToolsetTest.Dependency/WixToolsetTest.Dependency.csproj
index 70b56f45..1fd46c63 100644
--- a/src/ext/Dependency/test/WixToolsetTest.Dependency/WixToolsetTest.Dependency.csproj
+++ b/src/ext/Dependency/test/WixToolsetTest.Dependency/WixToolsetTest.Dependency.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/DirectX/directx.cmd b/src/ext/DirectX/directx.cmd
deleted file mode 100644
index 56889513..00000000
--- a/src/ext/DirectX/directx.cmd
+++ /dev/null
@@ -1,24 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo DirectX.wixext build %_C%
10
11:: Restore
12msbuild -t:Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Build
15msbuild -t:Build -p:Configuration=%_C% -tl -nologo -warnaserror test\WixToolsetTest.DirectX\WixToolsetTest.DirectX.csproj || exit /b
16
17:: Test
18dotnet test -c %_C% --no-build test\WixToolsetTest.DirectX || exit /b
19
20:: Pack
21msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror wixext\WixToolset.DirectX.wixext.csproj || exit /b
22
23@popd
24@endlocal
diff --git a/src/ext/DirectX/directx_t.proj b/src/ext/DirectX/directx_t.proj
new file mode 100644
index 00000000..17b147ef
--- /dev/null
+++ b/src/ext/DirectX/directx_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.DirectX\WixToolsetTest.DirectX.csproj" />
7 <ProjectReference Include="wixext\WixToolset.DirectX.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)directx.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.directx.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.directx.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.DirectX.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/DirectX/test/WixToolsetTest.DirectX/DirectXExtensionFixture.cs b/src/ext/DirectX/test/WixToolsetTest.DirectX/DirectXExtensionFixture.cs
index 64013ca6..dceaaec5 100644
--- a/src/ext/DirectX/test/WixToolsetTest.DirectX/DirectXExtensionFixture.cs
+++ b/src/ext/DirectX/test/WixToolsetTest.DirectX/DirectXExtensionFixture.cs
@@ -3,14 +3,15 @@
3namespace WixToolsetTest.DirectX 3namespace WixToolsetTest.DirectX
4{ 4{
5 using System.Linq; 5 using System.Linq;
6 using WixInternal.TestSupport; 6 using Microsoft.VisualStudio.TestTools.UnitTesting;
7 using WixInternal.Core.TestPackage; 7 using WixInternal.MSTestSupport;
8 using WixInternal.Core.MSTestPackage;
8 using WixToolset.DirectX; 9 using WixToolset.DirectX;
9 using Xunit;
10 10
11 [TestClass]
11 public class DirectXExtensionFixture 12 public class DirectXExtensionFixture
12 { 13 {
13 [Fact] 14 [TestMethod]
14 public void CanBuildUsingPixelShaderVersion() 15 public void CanBuildUsingPixelShaderVersion()
15 { 16 {
16 var folder = TestData.Get(@"TestData\UsingPixelShaderVersion"); 17 var folder = TestData.Get(@"TestData\UsingPixelShaderVersion");
diff --git a/src/ext/DirectX/test/WixToolsetTest.DirectX/WixToolsetTest.DirectX.csproj b/src/ext/DirectX/test/WixToolsetTest.DirectX/WixToolsetTest.DirectX.csproj
index 31a35320..c13f3300 100644
--- a/src/ext/DirectX/test/WixToolsetTest.DirectX/WixToolsetTest.DirectX.csproj
+++ b/src/ext/DirectX/test/WixToolsetTest.DirectX/WixToolsetTest.DirectX.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -19,6 +19,7 @@
19 </ItemGroup> 19 </ItemGroup>
20 20
21 <ItemGroup> 21 <ItemGroup>
22 <PackageReference Include="WixInternal.Core.TestPackage" /> 22 <PackageReference Include="WixInternal.MSTestSupport" />
23 <PackageReference Include="WixInternal.Core.MSTestPackage" />
23 </ItemGroup> 24 </ItemGroup>
24</Project> 25</Project>
diff --git a/src/ext/Firewall/firewall.cmd b/src/ext/Firewall/firewall.cmd
deleted file mode 100644
index 92926a8c..00000000
--- a/src/ext/Firewall/firewall.cmd
+++ /dev/null
@@ -1,21 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo Firewall.wixext build %_C%
10
11:: Build
12msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Test
15dotnet test -c %_C% --no-build test\WixToolsetTest.Firewall || exit /b
16
17:: Pack
18msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.Firewall.wixext.csproj || exit /b
19
20@popd
21@endlocal
diff --git a/src/ext/Firewall/firewall_t.proj b/src/ext/Firewall/firewall_t.proj
new file mode 100644
index 00000000..67229c39
--- /dev/null
+++ b/src/ext/Firewall/firewall_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.Firewall\WixToolsetTest.Firewall.csproj" />
7 <ProjectReference Include="wixext\WixToolset.Firewall.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)firewall.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.firewall.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.firewall.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.Firewall.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
index 65016865..4b9aecd7 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
@@ -6,14 +6,15 @@ namespace WixToolsetTest.Firewall
6 using System.IO; 6 using System.IO;
7 using System.Linq; 7 using System.Linq;
8 using System.Xml.Linq; 8 using System.Xml.Linq;
9 using WixInternal.Core.TestPackage; 9 using Microsoft.VisualStudio.TestTools.UnitTesting;
10 using WixInternal.TestSupport; 10 using WixInternal.Core.MSTestPackage;
11 using WixInternal.MSTestSupport;
11 using WixToolset.Firewall; 12 using WixToolset.Firewall;
12 using Xunit;
13 13
14 [TestClass]
14 public class FirewallExtensionFixture 15 public class FirewallExtensionFixture
15 { 16 {
16 [Fact] 17 [TestMethod]
17 public void CanBuildUsingFirewall() 18 public void CanBuildUsingFirewall()
18 { 19 {
19 var folder = TestData.Get(@"TestData\UsingFirewall"); 20 var folder = TestData.Get(@"TestData\UsingFirewall");
@@ -52,7 +53,7 @@ namespace WixToolsetTest.Firewall
52 }, results); 53 }, results);
53 } 54 }
54 55
55 [Fact] 56 [TestMethod]
56 public void CanBuildUsingFirewallARM64() 57 public void CanBuildUsingFirewallARM64()
57 { 58 {
58 var folder = TestData.Get(@"TestData\UsingFirewall"); 59 var folder = TestData.Get(@"TestData\UsingFirewall");
@@ -91,7 +92,7 @@ namespace WixToolsetTest.Firewall
91 }, results); 92 }, results);
92 } 93 }
93 94
94 [Fact] 95 [TestMethod]
95 public void CanBuildWithProperties() 96 public void CanBuildWithProperties()
96 { 97 {
97 var folder = TestData.Get(@"TestData\UsingProperties"); 98 var folder = TestData.Get(@"TestData\UsingProperties");
@@ -112,7 +113,7 @@ namespace WixToolsetTest.Firewall
112 }, results); 113 }, results);
113 } 114 }
114 115
115 [Fact] 116 [TestMethod]
116 public void CanBuildWithPropertiesUsingFirewallARM64() 117 public void CanBuildWithPropertiesUsingFirewallARM64()
117 { 118 {
118 var folder = TestData.Get(@"TestData\UsingProperties"); 119 var folder = TestData.Get(@"TestData\UsingProperties");
@@ -133,7 +134,7 @@ namespace WixToolsetTest.Firewall
133 }, results); 134 }, results);
134 } 135 }
135 136
136 [Fact] 137 [TestMethod]
137 public void CanRoundtripFirewallExceptions() 138 public void CanRoundtripFirewallExceptions()
138 { 139 {
139 var folder = TestData.Get(@"TestData", "UsingFirewall"); 140 var folder = TestData.Get(@"TestData", "UsingFirewall");
@@ -181,7 +182,7 @@ namespace WixToolsetTest.Firewall
181 }, actual.Select(a => a.Name).ToArray()); 182 }, actual.Select(a => a.Name).ToArray());
182 } 183 }
183 184
184 [Fact] 185 [TestMethod]
185 public void CanRoundtripFirewallExceptionsWithProperties() 186 public void CanRoundtripFirewallExceptionsWithProperties()
186 { 187 {
187 var folder = TestData.Get(@"TestData", "UsingProperties"); 188 var folder = TestData.Get(@"TestData", "UsingProperties");
@@ -212,7 +213,7 @@ namespace WixToolsetTest.Firewall
212 }, actual.Select(a => a.Name).ToArray()); 213 }, actual.Select(a => a.Name).ToArray());
213 } 214 }
214 215
215 [Fact] 216 [TestMethod]
216 public void RoundtripAttributesAreCorrectForApp() 217 public void RoundtripAttributesAreCorrectForApp()
217 { 218 {
218 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleApp"); 219 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleApp");
@@ -230,7 +231,7 @@ namespace WixToolsetTest.Firewall
230 }, actual.Attributes); 231 }, actual.Attributes);
231 } 232 }
232 233
233 [Fact] 234 [TestMethod]
234 public void RoundtripAttributesAreCorrectForPort() 235 public void RoundtripAttributesAreCorrectForPort()
235 { 236 {
236 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExamplePort"); 237 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExamplePort");
@@ -248,7 +249,7 @@ namespace WixToolsetTest.Firewall
248 }, actual.Attributes); 249 }, actual.Attributes);
249 } 250 }
250 251
251 [Fact] 252 [TestMethod]
252 public void RoundtripAttributesAreCorrectForDNSScope() 253 public void RoundtripAttributesAreCorrectForDNSScope()
253 { 254 {
254 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDNSScope"); 255 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDNSScope");
@@ -264,7 +265,7 @@ namespace WixToolsetTest.Firewall
264 }, actual.Attributes); 265 }, actual.Attributes);
265 } 266 }
266 267
267 [Fact] 268 [TestMethod]
268 public void RoundtripAttributesAreCorrectForDHCPScope() 269 public void RoundtripAttributesAreCorrectForDHCPScope()
269 { 270 {
270 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDHCPScope"); 271 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDHCPScope");
@@ -281,7 +282,7 @@ namespace WixToolsetTest.Firewall
281 }, actual.Attributes); 282 }, actual.Attributes);
282 } 283 }
283 284
284 [Fact] 285 [TestMethod]
285 public void RoundtripAttributesAreCorrectForWINSScope() 286 public void RoundtripAttributesAreCorrectForWINSScope()
286 { 287 {
287 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleWINSScope"); 288 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleWINSScope");
@@ -298,7 +299,7 @@ namespace WixToolsetTest.Firewall
298 }, actual.Attributes); 299 }, actual.Attributes);
299 } 300 }
300 301
301 [Fact] 302 [TestMethod]
302 public void RoundtripAttributesAreCorrectForDefaultGatewayScope() 303 public void RoundtripAttributesAreCorrectForDefaultGatewayScope()
303 { 304 {
304 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDefaultGatewayScope"); 305 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDefaultGatewayScope");
@@ -315,7 +316,7 @@ namespace WixToolsetTest.Firewall
315 }, actual.Attributes); 316 }, actual.Attributes);
316 } 317 }
317 318
318 [Fact] 319 [TestMethod]
319 public void RoundtripAttributesAreCorrectForINetFwRule3Values() 320 public void RoundtripAttributesAreCorrectForINetFwRule3Values()
320 { 321 {
321 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "INetFwRule3 values"); 322 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "INetFwRule3 values");
@@ -335,7 +336,7 @@ namespace WixToolsetTest.Firewall
335 }, actual.Attributes); 336 }, actual.Attributes);
336 } 337 }
337 338
338 [Fact] 339 [TestMethod]
339 public void RoundtripAttributesAreCorrectForINetFwRule3Properties() 340 public void RoundtripAttributesAreCorrectForINetFwRule3Properties()
340 { 341 {
341 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "INetFwRule3 properties"); 342 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "INetFwRule3 properties");
@@ -355,7 +356,7 @@ namespace WixToolsetTest.Firewall
355 }, actual.Attributes); 356 }, actual.Attributes);
356 } 357 }
357 358
358 [Fact] 359 [TestMethod]
359 public void RoundtripAttributesAreCorrectForGroupingValue() 360 public void RoundtripAttributesAreCorrectForGroupingValue()
360 { 361 {
361 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "GroupingExample1"); 362 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "GroupingExample1");
@@ -370,7 +371,7 @@ namespace WixToolsetTest.Firewall
370 }, actual.Attributes); 371 }, actual.Attributes);
371 } 372 }
372 373
373 [Fact] 374 [TestMethod]
374 public void RoundtripAttributesAreCorrectForGroupingProperty() 375 public void RoundtripAttributesAreCorrectForGroupingProperty()
375 { 376 {
376 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "GroupingExample2"); 377 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "GroupingExample2");
@@ -386,7 +387,7 @@ namespace WixToolsetTest.Firewall
386 }, actual.Attributes); 387 }, actual.Attributes);
387 } 388 }
388 389
389 [Fact] 390 [TestMethod]
390 public void RoundtripAttributesAreCorrectForIcmpValue() 391 public void RoundtripAttributesAreCorrectForIcmpValue()
391 { 392 {
392 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ICMPExample1"); 393 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ICMPExample1");
@@ -401,7 +402,7 @@ namespace WixToolsetTest.Firewall
401 }, actual.Attributes); 402 }, actual.Attributes);
402 } 403 }
403 404
404 [Fact] 405 [TestMethod]
405 public void RoundtripAttributesAreCorrectForIcmpProperty() 406 public void RoundtripAttributesAreCorrectForIcmpProperty()
406 { 407 {
407 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ICMPExample2"); 408 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ICMPExample2");
@@ -416,7 +417,7 @@ namespace WixToolsetTest.Firewall
416 }, actual.Attributes); 417 }, actual.Attributes);
417 } 418 }
418 419
419 [Fact] 420 [TestMethod]
420 public void RoundtripAttributesAreCorrectForLocalScopeValue() 421 public void RoundtripAttributesAreCorrectForLocalScopeValue()
421 { 422 {
422 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "LocalScopeExample1"); 423 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "LocalScopeExample1");
@@ -431,7 +432,7 @@ namespace WixToolsetTest.Firewall
431 }, actual.Attributes); 432 }, actual.Attributes);
432 } 433 }
433 434
434 [Fact] 435 [TestMethod]
435 public void RoundtripAttributesAreCorrectForLocalScopeProperty() 436 public void RoundtripAttributesAreCorrectForLocalScopeProperty()
436 { 437 {
437 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "LocalScopeExample2"); 438 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "LocalScopeExample2");
@@ -446,7 +447,7 @@ namespace WixToolsetTest.Firewall
446 }, actual.Attributes); 447 }, actual.Attributes);
447 } 448 }
448 449
449 [Fact] 450 [TestMethod]
450 public void RoundtripAttributesAreCorrectForRemotePorts() 451 public void RoundtripAttributesAreCorrectForRemotePorts()
451 { 452 {
452 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "RemotePortExample1"); 453 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "RemotePortExample1");
@@ -462,7 +463,7 @@ namespace WixToolsetTest.Firewall
462 }, actual.Attributes); 463 }, actual.Attributes);
463 } 464 }
464 465
465 [Fact] 466 [TestMethod]
466 public void RoundtripAttributesAreCorrectForRemotePortsProperty() 467 public void RoundtripAttributesAreCorrectForRemotePortsProperty()
467 { 468 {
468 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "RemotePortExample2"); 469 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "RemotePortExample2");
@@ -478,7 +479,7 @@ namespace WixToolsetTest.Firewall
478 }, actual.Attributes); 479 }, actual.Attributes);
479 } 480 }
480 481
481 [Fact] 482 [TestMethod]
482 public void RoundtripAttributesAreCorrectWhenPropertiesAreUsed() 483 public void RoundtripAttributesAreCorrectWhenPropertiesAreUsed()
483 { 484 {
484 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "[NAME]", "UsingProperties"); 485 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "[NAME]", "UsingProperties");
@@ -526,10 +527,10 @@ namespace WixToolsetTest.Firewall
526 }); 527 });
527 528
528 var nested = related.Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value); 529 var nested = related.Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value);
529 Assert.False(nested.Any()); 530 Assert.IsFalse(nested.Any());
530 } 531 }
531 532
532 [Fact] 533 [TestMethod]
533 public void RoundtripAttributesAreCorrectWhenNestedPropertiesAreUsed() 534 public void RoundtripAttributesAreCorrectWhenNestedPropertiesAreUsed()
534 { 535 {
535 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "Single Nested properties", "UsingProperties"); 536 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "Single Nested properties", "UsingProperties");
@@ -559,10 +560,10 @@ namespace WixToolsetTest.Firewall
559 }); 560 });
560 561
561 var nested = related.Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value); 562 var nested = related.Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value);
562 Assert.False(nested.Any()); 563 Assert.IsFalse(nested.Any());
563 } 564 }
564 565
565 [Fact] 566 [TestMethod]
566 public void RoundtripAttributesAreCorrectWhenMultipleNestedPropertiesAreUsed() 567 public void RoundtripAttributesAreCorrectWhenMultipleNestedPropertiesAreUsed()
567 { 568 {
568 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "Multiple Nested properties", "UsingProperties"); 569 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "Multiple Nested properties", "UsingProperties");
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj b/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
index e46020a6..5de88c8b 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/Http/http.cmd b/src/ext/Http/http.cmd
deleted file mode 100644
index afcffb24..00000000
--- a/src/ext/Http/http.cmd
+++ /dev/null
@@ -1,21 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo Http.wixext build %_C%
10
11:: Build
12msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Test
15dotnet test -c %_C% --no-build test\WixToolsetTest.Http || exit /b
16
17:: Pack
18msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.Http.wixext.csproj || exit /b
19
20@popd
21@endlocal
diff --git a/src/ext/Http/http_t.proj b/src/ext/Http/http_t.proj
new file mode 100644
index 00000000..8cd9c7d4
--- /dev/null
+++ b/src/ext/Http/http_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.Http\WixToolsetTest.Http.csproj" />
7 <ProjectReference Include="wixext\WixToolset.Http.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)http.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.http.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.http.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.Http.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/Http/test/WixToolsetTest.Http/HttpExtensionFixture.cs b/src/ext/Http/test/WixToolsetTest.Http/HttpExtensionFixture.cs
index ffd698f5..c91ce937 100644
--- a/src/ext/Http/test/WixToolsetTest.Http/HttpExtensionFixture.cs
+++ b/src/ext/Http/test/WixToolsetTest.Http/HttpExtensionFixture.cs
@@ -2,14 +2,15 @@
2 2
3namespace WixToolsetTest.Http 3namespace WixToolsetTest.Http
4{ 4{
5 using WixInternal.TestSupport; 5 using Microsoft.VisualStudio.TestTools.UnitTesting;
6 using WixInternal.Core.TestPackage; 6 using WixInternal.MSTestSupport;
7 using WixInternal.Core.MSTestPackage;
7 using WixToolset.Http; 8 using WixToolset.Http;
8 using Xunit;
9 9
10 [TestClass]
10 public class HttpExtensionFixture 11 public class HttpExtensionFixture
11 { 12 {
12 [Fact] 13 [TestMethod]
13 public void CanBuildUsingSsl() 14 public void CanBuildUsingSsl()
14 { 15 {
15 var folder = TestData.Get("TestData", "Ssl"); 16 var folder = TestData.Get("TestData", "Ssl");
@@ -29,7 +30,7 @@ namespace WixToolsetTest.Http
29 }, results); 30 }, results);
30 } 31 }
31 32
32 [Fact] 33 [TestMethod]
33 public void CanBuildUsingUrlReservation() 34 public void CanBuildUsingUrlReservation()
34 { 35 {
35 var folder = TestData.Get(@"TestData\UsingUrlReservation"); 36 var folder = TestData.Get(@"TestData\UsingUrlReservation");
diff --git a/src/ext/Http/test/WixToolsetTest.Http/WixToolsetTest.Http.csproj b/src/ext/Http/test/WixToolsetTest.Http/WixToolsetTest.Http.csproj
index b23ef481..d5e6c929 100644
--- a/src/ext/Http/test/WixToolsetTest.Http/WixToolsetTest.Http.csproj
+++ b/src/ext/Http/test/WixToolsetTest.Http/WixToolsetTest.Http.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/Iis/iis.cmd b/src/ext/Iis/iis.cmd
deleted file mode 100644
index 0ae87a77..00000000
--- a/src/ext/Iis/iis.cmd
+++ /dev/null
@@ -1,21 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo Iis.wixext build %_C%
10
11:: Build
12msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Test
15dotnet test test\WixToolsetTest.Iis -c %_C% --no-build --nologo || exit /b
16
17:: Pack
18dotnet pack wixext\WixToolset.Iis.wixext.csproj -c %_C% --no-build --nologo || exit /b
19
20@popd
21@endlocal
diff --git a/src/ext/Iis/iis_t.proj b/src/ext/Iis/iis_t.proj
new file mode 100644
index 00000000..84473475
--- /dev/null
+++ b/src/ext/Iis/iis_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.Iis\WixToolsetTest.Iis.csproj" />
7 <ProjectReference Include="wixext\WixToolset.Iis.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)iis.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.iis.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.iis.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.Iis.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/Iis/test/WixToolsetTest.Iis/IisExtensionFixture.cs b/src/ext/Iis/test/WixToolsetTest.Iis/IisExtensionFixture.cs
index ab3f35d9..01a89dc0 100644
--- a/src/ext/Iis/test/WixToolsetTest.Iis/IisExtensionFixture.cs
+++ b/src/ext/Iis/test/WixToolsetTest.Iis/IisExtensionFixture.cs
@@ -3,14 +3,15 @@
3namespace WixToolsetTest.Iis 3namespace WixToolsetTest.Iis
4{ 4{
5 using System.Linq; 5 using System.Linq;
6 using WixInternal.TestSupport; 6 using Microsoft.VisualStudio.TestTools.UnitTesting;
7 using WixInternal.Core.TestPackage; 7 using WixInternal.MSTestSupport;
8 using WixInternal.Core.MSTestPackage;
8 using WixToolset.Iis; 9 using WixToolset.Iis;
9 using Xunit;
10 10
11 [TestClass]
11 public class IisExtensionFixture 12 public class IisExtensionFixture
12 { 13 {
13 [Fact] 14 [TestMethod]
14 public void CanBuildUsingIIs() 15 public void CanBuildUsingIIs()
15 { 16 {
16 var folder = TestData.Get(@"TestData\UsingIis"); 17 var folder = TestData.Get(@"TestData\UsingIis");
diff --git a/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj b/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj
index a39e5b0b..a0a6e043 100644
--- a/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj
+++ b/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -19,6 +19,7 @@
19 </ItemGroup> 19 </ItemGroup>
20 20
21 <ItemGroup> 21 <ItemGroup>
22 <PackageReference Include="WixInternal.Core.TestPackage" /> 22 <PackageReference Include="WixInternal.MSTestSupport" />
23 <PackageReference Include="WixInternal.Core.MSTestPackage" />
23 </ItemGroup> 24 </ItemGroup>
24</Project> 25</Project>
diff --git a/src/ext/Msmq/msmq.cmd b/src/ext/Msmq/msmq.cmd
deleted file mode 100644
index 3ebceab4..00000000
--- a/src/ext/Msmq/msmq.cmd
+++ /dev/null
@@ -1,21 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo Msmq.wixext build %_C%
10
11:: Build
12msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Test
15dotnet test test\WixToolsetTest.Msmq -c %_C% --no-build --nologo || exit /b
16
17:: Pack
18dotnet pack wixext\WixToolset.Msmq.wixext.csproj -c %_C% --no-build --nologo || exit /b
19
20@popd
21@endlocal
diff --git a/src/ext/Msmq/msmq_t.proj b/src/ext/Msmq/msmq_t.proj
new file mode 100644
index 00000000..73424370
--- /dev/null
+++ b/src/ext/Msmq/msmq_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.Msmq\WixToolsetTest.Msmq.csproj" />
7 <ProjectReference Include="wixext\WixToolset.Msmq.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)Msmq.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.Msmq.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.Msmq.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.Msmq.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/Msmq/test/WixToolsetTest.Msmq/MsmqExtensionFixture.cs b/src/ext/Msmq/test/WixToolsetTest.Msmq/MsmqExtensionFixture.cs
index 970bc2e9..60335b8a 100644
--- a/src/ext/Msmq/test/WixToolsetTest.Msmq/MsmqExtensionFixture.cs
+++ b/src/ext/Msmq/test/WixToolsetTest.Msmq/MsmqExtensionFixture.cs
@@ -6,14 +6,15 @@ namespace WixToolsetTest.Msmq
6 using System.IO; 6 using System.IO;
7 using System.Linq; 7 using System.Linq;
8 using System.Xml.Linq; 8 using System.Xml.Linq;
9 using WixInternal.TestSupport; 9 using Microsoft.VisualStudio.TestTools.UnitTesting;
10 using WixInternal.Core.TestPackage; 10 using WixInternal.MSTestSupport;
11 using WixInternal.Core.MSTestPackage;
11 using WixToolset.Msmq; 12 using WixToolset.Msmq;
12 using Xunit;
13 13
14 [TestClass]
14 public class MsmqExtensionFixture 15 public class MsmqExtensionFixture
15 { 16 {
16 [Fact] 17 [TestMethod]
17 public void CanBuildUsingMessageQueue() 18 public void CanBuildUsingMessageQueue()
18 { 19 {
19 var folder = TestData.Get(@"TestData\UsingMessageQueue"); 20 var folder = TestData.Get(@"TestData\UsingMessageQueue");
@@ -36,7 +37,8 @@ namespace WixToolsetTest.Msmq
36 }, results); 37 }, results);
37 } 38 }
38 39
39 [Fact(Skip = "Util:Wix4Group and Util:Wix6Group decompilation issues prevent this usage currently")] 40 [TestMethod]
41 [Ignore("Util:Wix4Group and Util:Wix6Group decompilation issues prevent this usage currently")]
40 public void CanRoundtripMessageQueue() 42 public void CanRoundtripMessageQueue()
41 { 43 {
42 var folder = TestData.Get(@"TestData\UsingMessageQueue"); 44 var folder = TestData.Get(@"TestData\UsingMessageQueue");
diff --git a/src/ext/Msmq/test/WixToolsetTest.Msmq/WixToolsetTest.Msmq.csproj b/src/ext/Msmq/test/WixToolsetTest.Msmq/WixToolsetTest.Msmq.csproj
index e7b6f21e..a8991c2e 100644
--- a/src/ext/Msmq/test/WixToolsetTest.Msmq/WixToolsetTest.Msmq.csproj
+++ b/src/ext/Msmq/test/WixToolsetTest.Msmq/WixToolsetTest.Msmq.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -19,6 +19,7 @@
19 </ItemGroup> 19 </ItemGroup>
20 20
21 <ItemGroup> 21 <ItemGroup>
22 <PackageReference Include="WixInternal.Core.TestPackage" /> 22 <PackageReference Include="WixInternal.MSTestSupport" />
23 <PackageReference Include="WixInternal.Core.MSTestPackage" />
23 </ItemGroup> 24 </ItemGroup>
24</Project> 25</Project>
diff --git a/src/ext/NetFx/netfx.cmd b/src/ext/NetFx/netfx.cmd
deleted file mode 100644
index d81959cc..00000000
--- a/src/ext/NetFx/netfx.cmd
+++ /dev/null
@@ -1,48 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5@set _L=%~dp0..\..\..\build\logs
6
7:parse_args
8@if /i "%1"=="release" set _C=Release
9@if /i "%1"=="inc" set _INC=1
10@if /i "%1"=="clean" set _CLEAN=1
11@if not "%1"=="" shift & goto parse_args
12
13@set _B=%~dp0..\..\..\build\NetFx.wixext\%_C%
14
15:: Clean
16
17@if "%_INC%"=="" call :clean
18@if NOT "%_CLEAN%"=="" goto :end
19
20@echo NetFx.wixext build %_C%
21
22:: Restore
23nuget restore netcoresearch\packages.config || exit /b
24
25:: Build
26msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror -bl:%_L%\ext_netfx_build.binlog || exit /b
27
28:: Test
29dotnet test ^
30 %_B%\net6.0\WixToolsetTest.NetFx.dll ^
31 --nologo -l "trx;LogFileName=%_L%\TestResults\netfx.wixext.trx" || exit /b
32
33:: Pack
34msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.Netfx.wixext.csproj || exit /b
35
36@goto :end
37
38:clean
39@rd /s/q "..\..\build\NetFx.wixext" 2> nul
40@del "..\..\build\artifacts\WixToolset.NetFx.wixext.*.nupkg" 2> nul
41@del "%_L%\ext_netfx_build.binlog" 2> nul
42@del "%_L%\TestResults\netfx.wixext.trx" 2> nul
43@rd /s/q "%USERPROFILE%\.nuget\packages\wixtoolset.netfx.wixext" 2> nul
44@exit /b
45
46:end
47@popd
48@endlocal
diff --git a/src/ext/NetFx/netfx_t.proj b/src/ext/NetFx/netfx_t.proj
new file mode 100644
index 00000000..3301dc8a
--- /dev/null
+++ b/src/ext/NetFx/netfx_t.proj
@@ -0,0 +1,26 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="wixlib\netfx.wixproj" />
7 <ProjectReference Include="test\WixToolsetTest.Netfx\WixToolsetTest.Netfx.csproj" />
8 <ProjectReference Include="wixext\WixToolset.Netfx.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
9 </ItemGroup>
10
11 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
12 <!--
13 This should work but at first glance, the .vcxproj doesn't get detected as a "package.config-style project."
14 Worth finding out if we could trigger it artificially. It would let us stop needing nuget.exe.
15
16 <ProjectReference Include="netcoresearch\netcoresearch.vcxproj" Targets="Restore" Properties="RestorePackagesConfig=true" />
17 -->
18 <Exec Command="nuget restore netcoresearch\packages.config" />
19
20 <RemoveDir Directories="$(RootBuildFolder)NetFx.wixext" />
21 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.netfx.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
22 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.netfx.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
23
24 <Delete Files="$(ArtifactsFolder)WixToolset.NetFx.wixext.*.nupkg" />
25 </Target>
26</Project>
diff --git a/src/ext/NetFx/test/WixToolsetTest.Netfx/NetfxExtensionFixture.cs b/src/ext/NetFx/test/WixToolsetTest.Netfx/NetfxExtensionFixture.cs
index a78a5617..37f715bf 100644
--- a/src/ext/NetFx/test/WixToolsetTest.Netfx/NetfxExtensionFixture.cs
+++ b/src/ext/NetFx/test/WixToolsetTest.Netfx/NetfxExtensionFixture.cs
@@ -4,14 +4,15 @@ namespace WixToolsetTest.Netfx
4{ 4{
5 using System.IO; 5 using System.IO;
6 using System.Linq; 6 using System.Linq;
7 using WixInternal.TestSupport; 7 using Microsoft.VisualStudio.TestTools.UnitTesting;
8 using WixInternal.Core.TestPackage; 8 using WixInternal.MSTestSupport;
9 using WixInternal.Core.MSTestPackage;
9 using WixToolset.Netfx; 10 using WixToolset.Netfx;
10 using Xunit;
11 11
12 [TestClass]
12 public class NetfxExtensionFixture 13 public class NetfxExtensionFixture
13 { 14 {
14 [Fact] 15 [TestMethod]
15 public void CanBuildUsingLatestDotNetCorePackages() 16 public void CanBuildUsingLatestDotNetCorePackages()
16 { 17 {
17 using (var fs = new DisposableFileSystem()) 18 using (var fs = new DisposableFileSystem())
@@ -21,30 +22,24 @@ namespace WixToolsetTest.Netfx
21 var bundleSourceFolder = TestData.Get(@"TestData\UsingDotNetCorePackages"); 22 var bundleSourceFolder = TestData.Get(@"TestData\UsingDotNetCorePackages");
22 var intermediateFolder = Path.Combine(baseFolder, "obj"); 23 var intermediateFolder = Path.Combine(baseFolder, "obj");
23 24
24 var extensionResult = WixRunner.Execute(new[]
25 {
26 "extension", "add",
27 "WixToolset.BootstrapperApplications.wixext"
28 });
29
30 var compileResult = WixRunner.Execute(new[] 25 var compileResult = WixRunner.Execute(new[]
31 { 26 {
32 "build", 27 "build",
33 Path.Combine(bundleSourceFolder, "BundleLatest.wxs"), 28 Path.Combine(bundleSourceFolder, "BundleLatest.wxs"),
34 Path.Combine(bundleSourceFolder, "NetCore3.1.12_x86.wxs"), 29 Path.Combine(bundleSourceFolder, "NetCore3.1.12_x86.wxs"),
35 Path.Combine(bundleSourceFolder, "NetCore3.1.12_x64.wxs"), 30 Path.Combine(bundleSourceFolder, "NetCore3.1.12_x64.wxs"),
36 "-ext", "WixToolset.BootstrapperApplications.wixext", 31 "-ext", TestData.Get(@"WixToolset.BootstrapperApplications.wixext.dll").Replace("NetFx.wixext", "Bal.wixext"),
37 "-ext", TestData.Get(@"WixToolset.Netfx.wixext.dll"), 32 "-ext", TestData.Get(@"WixToolset.Netfx.wixext.dll"),
38 "-intermediateFolder", intermediateFolder, 33 "-intermediateFolder", intermediateFolder,
39 "-o", bundleFile, 34 "-o", bundleFile,
40 }); 35 });
41 compileResult.AssertSuccess(); 36 compileResult.AssertSuccess();
42 37
43 Assert.True(File.Exists(bundleFile)); 38 Assert.IsTrue(File.Exists(bundleFile));
44 } 39 }
45 } 40 }
46 41
47 [Fact] 42 [TestMethod]
48 public void CanBuildUsingLatestDotNetCorePackages_X64() 43 public void CanBuildUsingLatestDotNetCorePackages_X64()
49 { 44 {
50 using (var fs = new DisposableFileSystem()) 45 using (var fs = new DisposableFileSystem())
@@ -54,29 +49,23 @@ namespace WixToolsetTest.Netfx
54 var bundleSourceFolder = TestData.Get(@"TestData\UsingDotNetCorePackages"); 49 var bundleSourceFolder = TestData.Get(@"TestData\UsingDotNetCorePackages");
55 var intermediateFolder = Path.Combine(baseFolder, "obj"); 50 var intermediateFolder = Path.Combine(baseFolder, "obj");
56 51
57 var extensionResult = WixRunner.Execute(new[]
58 {
59 "extension", "add",
60 "WixToolset.BootstrapperApplications.wixext"
61 });
62
63 var compileResult = WixRunner.Execute(new[] 52 var compileResult = WixRunner.Execute(new[]
64 { 53 {
65 "build", 54 "build",
66 Path.Combine(bundleSourceFolder, "BundleLatest_x64.wxs"), 55 Path.Combine(bundleSourceFolder, "BundleLatest_x64.wxs"),
67 Path.Combine(bundleSourceFolder, "NetCore3.1.12_x64.wxs"), 56 Path.Combine(bundleSourceFolder, "NetCore3.1.12_x64.wxs"),
68 "-ext", "WixToolset.BootstrapperApplications.wixext", 57 "-ext", TestData.Get(@"WixToolset.BootstrapperApplications.wixext.dll").Replace("NetFx.wixext", "Bal.wixext"),
69 "-ext", TestData.Get(@"WixToolset.Netfx.wixext.dll"), 58 "-ext", TestData.Get(@"WixToolset.Netfx.wixext.dll"),
70 "-intermediateFolder", intermediateFolder, 59 "-intermediateFolder", intermediateFolder,
71 "-o", bundleFile, 60 "-o", bundleFile,
72 }); 61 });
73 compileResult.AssertSuccess(); 62 compileResult.AssertSuccess();
74 63
75 Assert.True(File.Exists(bundleFile)); 64 Assert.IsTrue(File.Exists(bundleFile));
76 } 65 }
77 } 66 }
78 67
79 [Fact] 68 [TestMethod]
80 public void CanBuildUsingNetFx481Packages() 69 public void CanBuildUsingNetFx481Packages()
81 { 70 {
82 using (var fs = new DisposableFileSystem()) 71 using (var fs = new DisposableFileSystem())
@@ -86,17 +75,11 @@ namespace WixToolsetTest.Netfx
86 var bundleSourceFolder = TestData.Get(@"TestData\UsingNetFxPackages"); 75 var bundleSourceFolder = TestData.Get(@"TestData\UsingNetFxPackages");
87 var intermediateFolder = Path.Combine(baseFolder, "obj"); 76 var intermediateFolder = Path.Combine(baseFolder, "obj");
88 77
89 var extensionResult = WixRunner.Execute(new[]
90 {
91 "extension", "add",
92 "WixToolset.BootstrapperApplications.wixext"
93 });
94
95 var compileResult = WixRunner.Execute(new[] 78 var compileResult = WixRunner.Execute(new[]
96 { 79 {
97 "build", 80 "build",
98 Path.Combine(bundleSourceFolder, "BundleLatest.wxs"), 81 Path.Combine(bundleSourceFolder, "BundleLatest.wxs"),
99 "-ext", "WixToolset.BootstrapperApplications.wixext", 82 "-ext", TestData.Get(@"WixToolset.BootstrapperApplications.wixext.dll").Replace("NetFx.wixext", "Bal.wixext"),
100 "-ext", TestData.Get(@"WixToolset.Netfx.wixext.dll"), 83 "-ext", TestData.Get(@"WixToolset.Netfx.wixext.dll"),
101 "-intermediateFolder", intermediateFolder, 84 "-intermediateFolder", intermediateFolder,
102 "-o", bundleFile, 85 "-o", bundleFile,
@@ -104,11 +87,11 @@ namespace WixToolsetTest.Netfx
104 }); 87 });
105 compileResult.AssertSuccess(); 88 compileResult.AssertSuccess();
106 89
107 Assert.True(File.Exists(bundleFile)); 90 Assert.IsTrue(File.Exists(bundleFile));
108 } 91 }
109 } 92 }
110 93
111 [Fact] 94 [TestMethod]
112 public void CanBuildUsingNetFxSearches() 95 public void CanBuildUsingNetFxSearches()
113 { 96 {
114 using (var fs = new DisposableFileSystem()) 97 using (var fs = new DisposableFileSystem())
@@ -118,20 +101,12 @@ namespace WixToolsetTest.Netfx
118 var bundleSourceFolder = TestData.Get(@"TestData\UsingNetFxSearches"); 101 var bundleSourceFolder = TestData.Get(@"TestData\UsingNetFxSearches");
119 var intermediateFolder = Path.Combine(baseFolder, "obj"); 102 var intermediateFolder = Path.Combine(baseFolder, "obj");
120 103
121 var extensionResult = WixRunner.Execute(warningsAsErrors: true, new[]
122 {
123 "extension", "add",
124 "WixToolset.BootstrapperApplications.wixext",
125 "extension", "add",
126 "WixToolset.Util.wixext",
127 });
128
129 var compileResult = WixRunner.Execute(new[] 104 var compileResult = WixRunner.Execute(new[]
130 { 105 {
131 "build", 106 "build",
132 Path.Combine(bundleSourceFolder, "BundleLatest.wxs"), 107 Path.Combine(bundleSourceFolder, "BundleLatest.wxs"),
133 "-ext", "WixToolset.BootstrapperApplications.wixext", 108 "-ext", TestData.Get(@"WixToolset.BootstrapperApplications.wixext.dll").Replace("NetFx.wixext", "Bal.wixext"),
134 "-ext", "WixToolset.Util.wixext", 109 "-ext", TestData.Get(@"WixToolset.Util.wixext.dll").Replace("NetFx.wixext", "Util.wixext"),
135 "-ext", TestData.Get(@"WixToolset.Netfx.wixext.dll"), 110 "-ext", TestData.Get(@"WixToolset.Netfx.wixext.dll"),
136 "-intermediateFolder", intermediateFolder, 111 "-intermediateFolder", intermediateFolder,
137 "-o", bundleFile, 112 "-o", bundleFile,
@@ -139,11 +114,11 @@ namespace WixToolsetTest.Netfx
139 }); 114 });
140 compileResult.AssertSuccess(); 115 compileResult.AssertSuccess();
141 116
142 Assert.True(File.Exists(bundleFile)); 117 Assert.IsTrue(File.Exists(bundleFile));
143 } 118 }
144 } 119 }
145 120
146 [Fact] 121 [TestMethod]
147 public void CanBuildUsingNativeImage() 122 public void CanBuildUsingNativeImage()
148 { 123 {
149 var folder = TestData.Get(@"TestData\UsingNativeImage"); 124 var folder = TestData.Get(@"TestData\UsingNativeImage");
@@ -162,7 +137,7 @@ namespace WixToolsetTest.Netfx
162 }, results.OrderBy(s => s).ToArray()); 137 }, results.OrderBy(s => s).ToArray());
163 } 138 }
164 139
165 [Fact] 140 [TestMethod]
166 public void CanBuildUsingNativeImageX64() 141 public void CanBuildUsingNativeImageX64()
167 { 142 {
168 var folder = TestData.Get(@"TestData\UsingNativeImage"); 143 var folder = TestData.Get(@"TestData\UsingNativeImage");
@@ -181,7 +156,7 @@ namespace WixToolsetTest.Netfx
181 }, results.OrderBy(s => s).ToArray()); 156 }, results.OrderBy(s => s).ToArray());
182 } 157 }
183 158
184 [Fact] 159 [TestMethod]
185 public void CanBuildUsingNativeImageARM64() 160 public void CanBuildUsingNativeImageARM64()
186 { 161 {
187 var folder = TestData.Get(@"TestData\UsingNativeImage"); 162 var folder = TestData.Get(@"TestData\UsingNativeImage");
@@ -200,7 +175,7 @@ namespace WixToolsetTest.Netfx
200 }, results.OrderBy(s => s).ToArray()); 175 }, results.OrderBy(s => s).ToArray());
201 } 176 }
202 177
203 [Fact] 178 [TestMethod]
204 public void CanBuildUsingDotNetCompatibilityCheck() 179 public void CanBuildUsingDotNetCompatibilityCheck()
205 { 180 {
206 var folder = TestData.Get(@"TestData\UsingDotNetCompatibilityCheck"); 181 var folder = TestData.Get(@"TestData\UsingDotNetCompatibilityCheck");
diff --git a/src/ext/NetFx/test/WixToolsetTest.Netfx/WixToolsetTest.Netfx.csproj b/src/ext/NetFx/test/WixToolsetTest.Netfx/WixToolsetTest.Netfx.csproj
index 4e509cce..bdca49e6 100644
--- a/src/ext/NetFx/test/WixToolsetTest.Netfx/WixToolsetTest.Netfx.csproj
+++ b/src/ext/NetFx/test/WixToolsetTest.Netfx/WixToolsetTest.Netfx.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/PowerShell/powershell_t.proj b/src/ext/PowerShell/powershell_t.proj
new file mode 100644
index 00000000..da54d629
--- /dev/null
+++ b/src/ext/PowerShell/powershell_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.PowerShell\WixToolsetTest.Powershell.csproj" />
7 <ProjectReference Include="wixext\WixToolset.PowerShell.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)PowerShell.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.PowerShell.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.PowerShell.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.PowerShell.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/PowerShell/ps.cmd b/src/ext/PowerShell/ps.cmd
deleted file mode 100644
index 4a8aa61e..00000000
--- a/src/ext/PowerShell/ps.cmd
+++ /dev/null
@@ -1,21 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo PowerShell.wixext build %_C%
10
11:: Build
12msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Test
15dotnet test -c %_C% --no-build test\WixToolsetTest.PowerShell || exit /b
16
17:: Pack
18msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.PowerShell.wixext.csproj || exit /b
19
20@popd
21@endlocal
diff --git a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs
index eafda99f..a1dc3282 100644
--- a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs
+++ b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/PowerShellExtensionFixture.cs
@@ -2,14 +2,15 @@
2 2
3namespace WixToolsetTest.PowerShell 3namespace WixToolsetTest.PowerShell
4{ 4{
5 using WixInternal.TestSupport; 5 using Microsoft.VisualStudio.TestTools.UnitTesting;
6 using WixInternal.Core.TestPackage; 6 using WixInternal.MSTestSupport;
7 using WixInternal.Core.MSTestPackage;
7 using WixToolset.PowerShell; 8 using WixToolset.PowerShell;
8 using Xunit;
9 9
10 [TestClass]
10 public class PowerShellExtensionFixture 11 public class PowerShellExtensionFixture
11 { 12 {
12 [Fact] 13 [TestMethod]
13 public void CantBuildUsingTypesFileWithoutSnapIn() 14 public void CantBuildUsingTypesFileWithoutSnapIn()
14 { 15 {
15 var folder = TestData.Get(@"TestData\TypesFile"); 16 var folder = TestData.Get(@"TestData\TypesFile");
@@ -19,8 +20,8 @@ namespace WixToolsetTest.PowerShell
19 var results = build.BuildAndQuery(args => { 20 var results = build.BuildAndQuery(args => {
20 wixRunnerResult = WixRunner.Execute(args); 21 wixRunnerResult = WixRunner.Execute(args);
21 }); 22 });
22 Assert.NotNull(wixRunnerResult); 23 Assert.IsNotNull(wixRunnerResult);
23 Assert.Equal((int)PSErrors.Ids.NeitherIdSpecified, wixRunnerResult.ExitCode); 24 Assert.AreEqual((int)PSErrors.Ids.NeitherIdSpecified, wixRunnerResult.ExitCode);
24 } 25 }
25 } 26 }
26} 27}
diff --git a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj
index 347ca1ed..cff13cb7 100644
--- a/src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj
+++ b/src/ext/PowerShell/test/WixToolsetTest.PowerShell/WixToolsetTest.Powershell.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/Sql/sql.cmd b/src/ext/Sql/sql.cmd
deleted file mode 100644
index 41af0223..00000000
--- a/src/ext/Sql/sql.cmd
+++ /dev/null
@@ -1,21 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo Sql.wixext build %_C%
10
11:: Build
12msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Test
15dotnet test -c %_C% --no-build test\WixToolsetTest.Sql || exit /b
16
17:: Pack
18msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.Sql.wixext.csproj || exit /b
19
20@popd
21@endlocal
diff --git a/src/ext/Sql/sql_t.proj b/src/ext/Sql/sql_t.proj
new file mode 100644
index 00000000..97b2c8fd
--- /dev/null
+++ b/src/ext/Sql/sql_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.Sql\WixToolsetTest.Sql.csproj" />
7 <ProjectReference Include="wixext\WixToolset.Sql.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)Sql.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.Sql.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.Sql.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.Sql.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/Sql/test/WixToolsetTest.Sql/SqlExtensionFixture.cs b/src/ext/Sql/test/WixToolsetTest.Sql/SqlExtensionFixture.cs
index 5576576d..14ca14c3 100644
--- a/src/ext/Sql/test/WixToolsetTest.Sql/SqlExtensionFixture.cs
+++ b/src/ext/Sql/test/WixToolsetTest.Sql/SqlExtensionFixture.cs
@@ -3,14 +3,15 @@
3namespace WixToolsetTest.Sql 3namespace WixToolsetTest.Sql
4{ 4{
5 using System.Linq; 5 using System.Linq;
6 using WixInternal.TestSupport; 6 using Microsoft.VisualStudio.TestTools.UnitTesting;
7 using WixInternal.Core.TestPackage; 7 using WixInternal.MSTestSupport;
8 using WixInternal.Core.MSTestPackage;
8 using WixToolset.Sql; 9 using WixToolset.Sql;
9 using Xunit;
10 10
11 [TestClass]
11 public class SqlExtensionFixture 12 public class SqlExtensionFixture
12 { 13 {
13 [Fact] 14 [TestMethod]
14 public void CanBuildUsingSqlStuff() 15 public void CanBuildUsingSqlStuff()
15 { 16 {
16 var folder = TestData.Get(@"TestData\UsingSql"); 17 var folder = TestData.Get(@"TestData\UsingSql");
diff --git a/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.csproj b/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.csproj
index 6c848683..62345258 100644
--- a/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.csproj
+++ b/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/UI/test/WixToolsetTest.UI/UIExtensionFixture.cs b/src/ext/UI/test/WixToolsetTest.UI/UIExtensionFixture.cs
index bb20f087..e06feac7 100644
--- a/src/ext/UI/test/WixToolsetTest.UI/UIExtensionFixture.cs
+++ b/src/ext/UI/test/WixToolsetTest.UI/UIExtensionFixture.cs
@@ -4,15 +4,16 @@ namespace WixToolsetTest.UI
4{ 4{
5 using System.IO; 5 using System.IO;
6 using System.Linq; 6 using System.Linq;
7 using WixInternal.Core.TestPackage; 7 using Microsoft.VisualStudio.TestTools.UnitTesting;
8 using WixInternal.TestSupport; 8 using WixInternal.Core.MSTestPackage;
9 using WixInternal.MSTestSupport;
9 using WixToolset.Data.WindowsInstaller; 10 using WixToolset.Data.WindowsInstaller;
10 using WixToolset.UI; 11 using WixToolset.UI;
11 using Xunit;
12 12
13 [TestClass]
13 public class UIExtensionFixture 14 public class UIExtensionFixture
14 { 15 {
15 [Fact] 16 [TestMethod]
16 public void CanBuildUsingWixUIAdvanced() 17 public void CanBuildUsingWixUIAdvanced()
17 { 18 {
18 var folder = TestData.Get(@"TestData", "WixUI_Advanced"); 19 var folder = TestData.Get(@"TestData", "WixUI_Advanced");
@@ -20,7 +21,7 @@ namespace WixToolsetTest.UI
20 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); 21 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder });
21 22
22 var results = build.BuildAndQuery(Build, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence"); 23 var results = build.BuildAndQuery(Build, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence");
23 Assert.Single(results, result => result.StartsWith("Dialog:AdvancedWelcomeEulaDlg\t")); 24 WixAssert.Single(results, result => result.StartsWith("Dialog:AdvancedWelcomeEulaDlg\t"));
24 WixAssert.CompareLineByLine(new[] 25 WixAssert.CompareLineByLine(new[]
25 { 26 {
26 "Binary:WixUI_Bmp_Banner\t[Binary data]", 27 "Binary:WixUI_Bmp_Banner\t[Binary data]",
@@ -37,7 +38,7 @@ namespace WixToolsetTest.UI
37 "CustomAction:WixSetPerMachineFolder\t51\tAPPLICATIONFOLDER\t[WixPerMachineFolder]\t", 38 "CustomAction:WixSetPerMachineFolder\t51\tAPPLICATIONFOLDER\t[WixPerMachineFolder]\t",
38 "CustomAction:WixSetPerUserFolder\t51\tAPPLICATIONFOLDER\t[WixPerUserFolder]\t", 39 "CustomAction:WixSetPerUserFolder\t51\tAPPLICATIONFOLDER\t[WixPerUserFolder]\t",
39 }, results.Where(r => r.StartsWith("CustomAction:")).ToArray()); 40 }, results.Where(r => r.StartsWith("CustomAction:")).ToArray());
40 Assert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).ToArray()); 41 WixAssert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).ToArray());
41 WixAssert.CompareLineByLine(new[] 42 WixAssert.CompareLineByLine(new[]
42 { 43 {
43 "InstallUISequence:AdvancedWelcomeEulaDlg\tNOT Installed\t1297", 44 "InstallUISequence:AdvancedWelcomeEulaDlg\tNOT Installed\t1297",
@@ -45,7 +46,7 @@ namespace WixToolsetTest.UI
45 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray()); 46 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray());
46 } 47 }
47 48
48 [Fact] 49 [TestMethod]
49 public void CanBuildUsingWixUIAdvancedX64() 50 public void CanBuildUsingWixUIAdvancedX64()
50 { 51 {
51 var folder = TestData.Get(@"TestData", "WixUI_Advanced"); 52 var folder = TestData.Get(@"TestData", "WixUI_Advanced");
@@ -53,7 +54,7 @@ namespace WixToolsetTest.UI
53 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); 54 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder });
54 55
55 var results = build.BuildAndQuery(BuildX64, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence"); 56 var results = build.BuildAndQuery(BuildX64, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence");
56 Assert.Single(results, result => result.StartsWith("Dialog:AdvancedWelcomeEulaDlg\t")); 57 WixAssert.Single(results, result => result.StartsWith("Dialog:AdvancedWelcomeEulaDlg\t"));
57 WixAssert.CompareLineByLine(new[] 58 WixAssert.CompareLineByLine(new[]
58 { 59 {
59 "Binary:WixUI_Bmp_Banner\t[Binary data]", 60 "Binary:WixUI_Bmp_Banner\t[Binary data]",
@@ -70,10 +71,10 @@ namespace WixToolsetTest.UI
70 "CustomAction:WixSetPerMachineFolder\t51\tAPPLICATIONFOLDER\t[WixPerMachineFolder]\t", 71 "CustomAction:WixSetPerMachineFolder\t51\tAPPLICATIONFOLDER\t[WixPerMachineFolder]\t",
71 "CustomAction:WixSetPerUserFolder\t51\tAPPLICATIONFOLDER\t[WixPerUserFolder]\t", 72 "CustomAction:WixSetPerUserFolder\t51\tAPPLICATIONFOLDER\t[WixPerUserFolder]\t",
72 }, results.Where(r => r.StartsWith("CustomAction:")).ToArray()); 73 }, results.Where(r => r.StartsWith("CustomAction:")).ToArray());
73 Assert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).ToArray()); 74 WixAssert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).ToArray());
74 } 75 }
75 76
76 [Fact] 77 [TestMethod]
77 public void CanBuildUsingWixUIAdvancedARM64() 78 public void CanBuildUsingWixUIAdvancedARM64()
78 { 79 {
79 var folder = TestData.Get(@"TestData", "WixUI_Advanced"); 80 var folder = TestData.Get(@"TestData", "WixUI_Advanced");
@@ -81,7 +82,7 @@ namespace WixToolsetTest.UI
81 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); 82 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder });
82 83
83 var results = build.BuildAndQuery(BuildARM64, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence"); 84 var results = build.BuildAndQuery(BuildARM64, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence");
84 Assert.Single(results, result => result.StartsWith("Dialog:AdvancedWelcomeEulaDlg\t")); 85 WixAssert.Single(results, result => result.StartsWith("Dialog:AdvancedWelcomeEulaDlg\t"));
85 WixAssert.CompareLineByLine(new[] 86 WixAssert.CompareLineByLine(new[]
86 { 87 {
87 "Binary:WixUI_Bmp_Banner\t[Binary data]", 88 "Binary:WixUI_Bmp_Banner\t[Binary data]",
@@ -98,10 +99,10 @@ namespace WixToolsetTest.UI
98 "CustomAction:WixSetPerMachineFolder\t51\tAPPLICATIONFOLDER\t[WixPerMachineFolder]\t", 99 "CustomAction:WixSetPerMachineFolder\t51\tAPPLICATIONFOLDER\t[WixPerMachineFolder]\t",
99 "CustomAction:WixSetPerUserFolder\t51\tAPPLICATIONFOLDER\t[WixPerUserFolder]\t", 100 "CustomAction:WixSetPerUserFolder\t51\tAPPLICATIONFOLDER\t[WixPerUserFolder]\t",
100 }, results.Where(r => r.StartsWith("CustomAction:")).ToArray()); 101 }, results.Where(r => r.StartsWith("CustomAction:")).ToArray());
101 Assert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).ToArray()); 102 WixAssert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).ToArray());
102 } 103 }
103 104
104 [Fact] 105 [TestMethod]
105 public void CanBuildUsingWixUIFeatureTree() 106 public void CanBuildUsingWixUIFeatureTree()
106 { 107 {
107 var folder = TestData.Get(@"TestData", "WixUI_FeatureTree"); 108 var folder = TestData.Get(@"TestData", "WixUI_FeatureTree");
@@ -109,9 +110,9 @@ namespace WixToolsetTest.UI
109 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); 110 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder });
110 111
111 var results = build.BuildAndQuery(BuildX64, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence"); 112 var results = build.BuildAndQuery(BuildX64, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence");
112 Assert.Single(results, result => result.StartsWith("Dialog:WelcomeDlg\t")); 113 WixAssert.Single(results, result => result.StartsWith("Dialog:WelcomeDlg\t"));
113 Assert.Single(results, result => result.StartsWith("Dialog:CustomizeDlg\t")); 114 WixAssert.Single(results, result => result.StartsWith("Dialog:CustomizeDlg\t"));
114 Assert.Empty(results.Where(result => result.StartsWith("Dialog:SetupTypeDlg\t"))); 115 WixAssert.Empty(results.Where(result => result.StartsWith("Dialog:SetupTypeDlg\t")));
115 WixAssert.CompareLineByLine(new[] 116 WixAssert.CompareLineByLine(new[]
116 { 117 {
117 "Binary:WixUI_Bmp_Banner\t[Binary data]", 118 "Binary:WixUI_Bmp_Banner\t[Binary data]",
@@ -125,14 +126,14 @@ namespace WixToolsetTest.UI
125 { 126 {
126 "CustomAction:SetWIXUI_EXITDIALOGOPTIONALTEXT\t51\tWIXUI_EXITDIALOGOPTIONALTEXT\tThank you for installing [ProductName].\t", 127 "CustomAction:SetWIXUI_EXITDIALOGOPTIONALTEXT\t51\tWIXUI_EXITDIALOGOPTIONALTEXT\tThank you for installing [ProductName].\t",
127 }, results.Where(r => r.StartsWith("CustomAction:")).ToArray()); 128 }, results.Where(r => r.StartsWith("CustomAction:")).ToArray());
128 Assert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction"))); 129 WixAssert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")));
129 WixAssert.CompareLineByLine(new[] 130 WixAssert.CompareLineByLine(new[]
130 { 131 {
131 "InstallUISequence:WelcomeDlg\tNOT Installed OR PATCH\t1297", 132 "InstallUISequence:WelcomeDlg\tNOT Installed OR PATCH\t1297",
132 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray()); 133 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray());
133 } 134 }
134 135
135 [Fact] 136 [TestMethod]
136 public void CanBuildWithWixUIInstallDirWithCustomizedEula() 137 public void CanBuildWithWixUIInstallDirWithCustomizedEula()
137 { 138 {
138 var folder = TestData.Get(@"TestData", "WixUI_InstallDir"); 139 var folder = TestData.Get(@"TestData", "WixUI_InstallDir");
@@ -140,8 +141,8 @@ namespace WixToolsetTest.UI
140 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); 141 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder });
141 142
142 var results = build.BuildAndQuery(BuildEula, "Binary", "Dialog", "CustomAction", "Property", "ControlEvent", "InstallUISequence"); 143 var results = build.BuildAndQuery(BuildEula, "Binary", "Dialog", "CustomAction", "Property", "ControlEvent", "InstallUISequence");
143 Assert.Single(results, result => result.StartsWith("Dialog:InstallDirDlg\t")); 144 WixAssert.Single(results, result => result.StartsWith("Dialog:InstallDirDlg\t"));
144 Assert.Single(results, result => result.StartsWith("Dialog:WelcomeDlg\t")); 145 WixAssert.Single(results, result => result.StartsWith("Dialog:WelcomeDlg\t"));
145 WixAssert.CompareLineByLine(new[] 146 WixAssert.CompareLineByLine(new[]
146 { 147 {
147 "Binary:WixUI_Bmp_Banner\t[Binary data]", 148 "Binary:WixUI_Bmp_Banner\t[Binary data]",
@@ -171,7 +172,7 @@ namespace WixToolsetTest.UI
171 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray()); 172 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray());
172 } 173 }
173 174
174 [Fact] 175 [TestMethod]
175 public void CanBuildUsingWixUIMinimal() 176 public void CanBuildUsingWixUIMinimal()
176 { 177 {
177 var folder = TestData.Get(@"TestData", "WixUI_Minimal"); 178 var folder = TestData.Get(@"TestData", "WixUI_Minimal");
@@ -179,7 +180,7 @@ namespace WixToolsetTest.UI
179 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); 180 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder });
180 181
181 var results = build.BuildAndQuery(Build, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence"); 182 var results = build.BuildAndQuery(Build, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence");
182 Assert.Single(results, result => result.StartsWith("Dialog:WelcomeEulaDlg\t")); 183 WixAssert.Single(results, result => result.StartsWith("Dialog:WelcomeEulaDlg\t"));
183 WixAssert.CompareLineByLine(new[] 184 WixAssert.CompareLineByLine(new[]
184 { 185 {
185 "Binary:WixUI_Bmp_Banner\t[Binary data]", 186 "Binary:WixUI_Bmp_Banner\t[Binary data]",
@@ -189,8 +190,8 @@ namespace WixToolsetTest.UI
189 "Binary:WixUI_Ico_Exclam\t[Binary data]", 190 "Binary:WixUI_Ico_Exclam\t[Binary data]",
190 "Binary:WixUI_Ico_Info\t[Binary data]", 191 "Binary:WixUI_Ico_Info\t[Binary data]",
191 }, results.Where(r => r.StartsWith("Binary:")).ToArray()); 192 }, results.Where(r => r.StartsWith("Binary:")).ToArray());
192 Assert.Empty(results.Where(r => r.StartsWith("CustomAction:"))); 193 WixAssert.Empty(results.Where(r => r.StartsWith("CustomAction:")));
193 Assert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction"))); 194 WixAssert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")));
194 WixAssert.CompareLineByLine(new[] 195 WixAssert.CompareLineByLine(new[]
195 { 196 {
196 "InstallUISequence:WelcomeDlg\tInstalled AND PATCH\t1296", 197 "InstallUISequence:WelcomeDlg\tInstalled AND PATCH\t1296",
@@ -198,7 +199,7 @@ namespace WixToolsetTest.UI
198 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray()); 199 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray());
199 } 200 }
200 201
201 [Fact] 202 [TestMethod]
202 public void CanBuildUsingWixUIMinimalInKazakh() 203 public void CanBuildUsingWixUIMinimalInKazakh()
203 { 204 {
204 var folder = TestData.Get(@"TestData", "WixUI_Minimal"); 205 var folder = TestData.Get(@"TestData", "WixUI_Minimal");
@@ -207,10 +208,10 @@ namespace WixToolsetTest.UI
207 208
208 var results = build.BuildAndQuery(BuildInKazakh, "Dialog"); 209 var results = build.BuildAndQuery(BuildInKazakh, "Dialog");
209 var welcomeDlg = results.Where(r => r.StartsWith("Dialog:WelcomeDlg\t")).Select(r => r.Split('\t')).Single(); 210 var welcomeDlg = results.Where(r => r.StartsWith("Dialog:WelcomeDlg\t")).Select(r => r.Split('\t')).Single();
210 Assert.Equal("[ProductName] бағдарламасын орнату", welcomeDlg[6]); 211 Assert.AreEqual("[ProductName] бағдарламасын орнату", welcomeDlg[6]);
211 } 212 }
212 213
213 [Fact] 214 [TestMethod]
214 public void CanBuildUsingWixUIMinimalAndReadPdb() 215 public void CanBuildUsingWixUIMinimalAndReadPdb()
215 { 216 {
216 var folder = TestData.Get(@"TestData", "WixUI_Minimal"); 217 var folder = TestData.Get(@"TestData", "WixUI_Minimal");
@@ -236,7 +237,7 @@ namespace WixToolsetTest.UI
236 } 237 }
237 } 238 }
238 239
239 [Fact] 240 [TestMethod]
240 public void CanBuildUsingWixUIMondo() 241 public void CanBuildUsingWixUIMondo()
241 { 242 {
242 var folder = TestData.Get(@"TestData", "WixUI_Mondo"); 243 var folder = TestData.Get(@"TestData", "WixUI_Mondo");
@@ -244,9 +245,9 @@ namespace WixToolsetTest.UI
244 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); 245 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder });
245 246
246 var results = build.BuildAndQuery(Build, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence"); 247 var results = build.BuildAndQuery(Build, "Binary", "Dialog", "CustomAction", "ControlEvent", "InstallUISequence");
247 Assert.Single(results, result => result.StartsWith("Dialog:WelcomeDlg\t")); 248 WixAssert.Single(results, result => result.StartsWith("Dialog:WelcomeDlg\t"));
248 Assert.Single(results, result => result.StartsWith("Dialog:CustomizeDlg\t")); 249 WixAssert.Single(results, result => result.StartsWith("Dialog:CustomizeDlg\t"));
249 Assert.Single(results, result => result.StartsWith("Dialog:SetupTypeDlg\t")); 250 WixAssert.Single(results, result => result.StartsWith("Dialog:SetupTypeDlg\t"));
250 WixAssert.CompareLineByLine(new[] 251 WixAssert.CompareLineByLine(new[]
251 { 252 {
252 "Binary:WixUI_Bmp_Banner\t[Binary data]", 253 "Binary:WixUI_Bmp_Banner\t[Binary data]",
@@ -271,7 +272,7 @@ namespace WixToolsetTest.UI
271 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray()); 272 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray());
272 } 273 }
273 274
274 [Fact] 275 [TestMethod]
275 public void CanBuildUsingWixUIMondoLocalized() 276 public void CanBuildUsingWixUIMondoLocalized()
276 { 277 {
277 var folder = TestData.Get(@"TestData", "WixUI_Mondo"); 278 var folder = TestData.Get(@"TestData", "WixUI_Mondo");
@@ -285,7 +286,7 @@ namespace WixToolsetTest.UI
285 }, results.Where(s => s.StartsWith("Control:ErrorDlg\tY")).Select(s => s.Split('\t')[9]).ToArray()); 286 }, results.Where(s => s.StartsWith("Control:ErrorDlg\tY")).Select(s => s.Split('\t')[9]).ToArray());
286 } 287 }
287 288
288 [Fact] 289 [TestMethod]
289 public void CanBuildWithInstallDirAndRemovedDialog() 290 public void CanBuildWithInstallDirAndRemovedDialog()
290 { 291 {
291 var folder = TestData.Get(@"TestData", "InstallDir_NoLicense"); 292 var folder = TestData.Get(@"TestData", "InstallDir_NoLicense");
@@ -293,7 +294,7 @@ namespace WixToolsetTest.UI
293 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); 294 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder });
294 295
295 var results = build.BuildAndQuery(Build, "Binary", "Dialog", "CustomAction", "Property", "ControlEvent", "InstallUISequence"); 296 var results = build.BuildAndQuery(Build, "Binary", "Dialog", "CustomAction", "Property", "ControlEvent", "InstallUISequence");
296 Assert.Single(results, result => result.StartsWith("Dialog:InstallDirDlg\t")); 297 WixAssert.Single(results, result => result.StartsWith("Dialog:InstallDirDlg\t"));
297 WixAssert.CompareLineByLine(new[] 298 WixAssert.CompareLineByLine(new[]
298 { 299 {
299 "Binary:WixUI_Bmp_Banner\t[Binary data]", 300 "Binary:WixUI_Bmp_Banner\t[Binary data]",
@@ -318,7 +319,7 @@ namespace WixToolsetTest.UI
318 "ControlEvent:InstallDirDlg\tNext\tDoAction\tWixUIValidatePath_X86\t1\t2", 319 "ControlEvent:InstallDirDlg\tNext\tDoAction\tWixUIValidatePath_X86\t1\t2",
319 }, results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).OrderBy(s => s).ToArray()); 320 }, results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).OrderBy(s => s).ToArray());
320 321
321 Assert.Empty(results.Where(result => result.Contains("LicenseAgreementDlg")).ToArray()); 322 WixAssert.Empty(results.Where(result => result.Contains("LicenseAgreementDlg")).ToArray());
322 323
323 WixAssert.CompareLineByLine(new[] 324 WixAssert.CompareLineByLine(new[]
324 { 325 {
@@ -326,7 +327,7 @@ namespace WixToolsetTest.UI
326 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray()); 327 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray());
327 } 328 }
328 329
329 [Fact] 330 [TestMethod]
330 public void CanBuildWithInstallDirAndAddedDialog() 331 public void CanBuildWithInstallDirAndAddedDialog()
331 { 332 {
332 var folder = TestData.Get(@"TestData", "InstallDir_SpecialDlg"); 333 var folder = TestData.Get(@"TestData", "InstallDir_SpecialDlg");
@@ -334,7 +335,7 @@ namespace WixToolsetTest.UI
334 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); 335 var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder });
335 336
336 var results = build.BuildAndQuery(BuildX64, "Binary", "Control", "Dialog", "CustomAction", "Property", "ControlEvent", "InstallUISequence"); 337 var results = build.BuildAndQuery(BuildX64, "Binary", "Control", "Dialog", "CustomAction", "Property", "ControlEvent", "InstallUISequence");
337 Assert.Single(results, result => result.StartsWith("Dialog:InstallDirDlg\t")); 338 WixAssert.Single(results, result => result.StartsWith("Dialog:InstallDirDlg\t"));
338 WixAssert.CompareLineByLine(new[] 339 WixAssert.CompareLineByLine(new[]
339 { 340 {
340 "Binary:WixUI_Bmp_Banner\t[Binary data]", 341 "Binary:WixUI_Bmp_Banner\t[Binary data]",
@@ -344,23 +345,23 @@ namespace WixToolsetTest.UI
344 "Binary:WixUI_Ico_Exclam\t[Binary data]", 345 "Binary:WixUI_Ico_Exclam\t[Binary data]",
345 "Binary:WixUI_Ico_Info\t[Binary data]", 346 "Binary:WixUI_Ico_Info\t[Binary data]",
346 }, results.Where(r => r.StartsWith("Binary:")).ToArray()); 347 }, results.Where(r => r.StartsWith("Binary:")).ToArray());
347 Assert.Empty(results.Where(r => r.StartsWith("CustomAction:")).ToArray()); 348 WixAssert.Empty(results.Where(r => r.StartsWith("CustomAction:")).ToArray());
348 WixAssert.CompareLineByLine(new[] 349 WixAssert.CompareLineByLine(new[]
349 { 350 {
350 "Property:WIXUI_INSTALLDIR\tINSTALLFOLDER", 351 "Property:WIXUI_INSTALLDIR\tINSTALLFOLDER",
351 }, results.Where(r => r.StartsWith("Property:WIXUI")).ToArray()); 352 }, results.Where(r => r.StartsWith("Property:WIXUI")).ToArray());
352 Assert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).OrderBy(s => s).ToArray()); 353 WixAssert.Empty(results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("DoAction")).OrderBy(s => s).ToArray());
353 WixAssert.CompareLineByLine(new[] 354 WixAssert.CompareLineByLine(new[]
354 { 355 {
355 "InstallUISequence:WelcomeDlg\tNOT Installed OR PATCH\t1297", 356 "InstallUISequence:WelcomeDlg\tNOT Installed OR PATCH\t1297",
356 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray()); 357 }, results.Where(r => r.StartsWith("InstallUISequence:AdvancedWelcome") || r.StartsWith("InstallUISequence:Welcome")).ToArray());
357 358
358 Assert.Equal(10, results.Where(result => result.StartsWith("Control:") && result.Contains("SpecialDlg")).Count()); 359 Assert.AreEqual(10, results.Where(result => result.StartsWith("Control:") && result.Contains("SpecialDlg")).Count());
359 Assert.Equal(5, results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("SpecialDlg")).Count()); 360 Assert.AreEqual(5, results.Where(result => result.StartsWith("ControlEvent:") && result.Contains("SpecialDlg")).Count());
360 Assert.Single(results.Where(result => result.StartsWith("Dialog:") && result.Contains("SpecialDlg"))); 361 WixAssert.Single(results.Where(result => result.StartsWith("Dialog:") && result.Contains("SpecialDlg")));
361 } 362 }
362 363
363 [Fact] 364 [TestMethod]
364 public void CannotBuildWithV3LikeUIRef() 365 public void CannotBuildWithV3LikeUIRef()
365 { 366 {
366 var folder = TestData.Get(@"TestData", "InvalidUIRef"); 367 var folder = TestData.Get(@"TestData", "InvalidUIRef");
@@ -381,7 +382,7 @@ namespace WixToolsetTest.UI
381 382
382 var results = WixRunner.Execute(args); 383 var results = WixRunner.Execute(args);
383 var message = results.Messages.Single(); 384 var message = results.Messages.Single();
384 Assert.Equal("The identifier 'WixUI:WixUI_Mondo' is inaccessible due to its protection level.", message.ToString()); 385 Assert.AreEqual("The identifier 'WixUI:WixUI_Mondo' is inaccessible due to its protection level.", message.ToString());
385 } 386 }
386 } 387 }
387 388
diff --git a/src/ext/UI/test/WixToolsetTest.UI/WixToolsetTest.UI.csproj b/src/ext/UI/test/WixToolsetTest.UI/WixToolsetTest.UI.csproj
index 675f14f8..132920c5 100644
--- a/src/ext/UI/test/WixToolsetTest.UI/WixToolsetTest.UI.csproj
+++ b/src/ext/UI/test/WixToolsetTest.UI/WixToolsetTest.UI.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/UI/ui.cmd b/src/ext/UI/ui.cmd
deleted file mode 100644
index a990db91..00000000
--- a/src/ext/UI/ui.cmd
+++ /dev/null
@@ -1,42 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5@set _L=%~dp0..\..\..\build\logs
6
7:parse_args
8@if /i "%1"=="release" set _C=Release
9@if /i "%1"=="inc" set _INC=1
10@if /i "%1"=="clean" set _CLEAN=1
11@if not "%1"=="" shift & goto parse_args
12
13@set _B=%~dp0..\..\..\build\UI.wixext\%_C%
14
15:: Clean
16
17@if "%_INC%"=="" call :clean
18@if NOT "%_CLEAN%"=="" goto :end
19
20@echo UI.wixext build %_C%
21
22:: Build
23msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror -bl:%_L%\ext_ui_build.binlog || exit /b
24
25:: Test
26dotnet test -c %_C% --no-build test\WixToolsetTest.UI || exit /b
27
28:: Pack
29msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.UI.wixext.csproj || exit /b
30
31@goto :end
32
33:clean
34@rd /s/q "..\..\..\build\UI.wixext" 2> nul
35@del "..\..\..\build\artifacts\WixToolset.UI.wixext.*.nupkg" 2> nul
36@del "%_L%\ext_ui_build.binlog" 2> nul
37@rd /s/q "%USERPROFILE%\.nuget\packages\wixtoolset.ui.wixext" 2> nul
38@exit /b
39
40:end
41@popd
42@endlocal
diff --git a/src/ext/UI/ui_t.proj b/src/ext/UI/ui_t.proj
new file mode 100644
index 00000000..0a989b6f
--- /dev/null
+++ b/src/ext/UI/ui_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.UI\WixToolsetTest.UI.csproj" />
7 <ProjectReference Include="wixext\WixToolset.UI.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)UI.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.UI.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.UI.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.UI.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
index 13c39091..03d87e4e 100644
--- a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
+++ b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
@@ -2,19 +2,20 @@
2 2
3namespace WixToolsetTest.Util 3namespace WixToolsetTest.Util
4{ 4{
5 using System;
5 using System.IO; 6 using System.IO;
6 using System.Linq; 7 using System.Linq;
7 using System.Xml; 8 using System.Xml;
8 using WixInternal.TestSupport;
9 using WixInternal.Core.TestPackage;
10 using WixToolset.Util;
11 using Xunit;
12 using System.Xml.Linq; 9 using System.Xml.Linq;
13 using System; 10 using Microsoft.VisualStudio.TestTools.UnitTesting;
11 using WixInternal.MSTestSupport;
12 using WixInternal.Core.MSTestPackage;
13 using WixToolset.Util;
14 14
15 [TestClass]
15 public class UtilExtensionFixture 16 public class UtilExtensionFixture
16 { 17 {
17 [Fact] 18 [TestMethod]
18 public void CanBuildUsingFileShare() 19 public void CanBuildUsingFileShare()
19 { 20 {
20 var folder = TestData.Get(@"TestData\UsingFileShare"); 21 var folder = TestData.Get(@"TestData\UsingFileShare");
@@ -35,7 +36,7 @@ namespace WixToolsetTest.Util
35 }, results.OrderBy(s => s).ToArray()); 36 }, results.OrderBy(s => s).ToArray());
36 } 37 }
37 38
38 [Fact] 39 [TestMethod]
39 public void CanBuildUsingFileShareX64() 40 public void CanBuildUsingFileShareX64()
40 { 41 {
41 var folder = TestData.Get(@"TestData\UsingFileShare"); 42 var folder = TestData.Get(@"TestData\UsingFileShare");
@@ -56,7 +57,7 @@ namespace WixToolsetTest.Util
56 }, results.OrderBy(s => s).ToArray()); 57 }, results.OrderBy(s => s).ToArray());
57 } 58 }
58 59
59 [Fact] 60 [TestMethod]
60 public void CanRoundtripFileShare() 61 public void CanRoundtripFileShare()
61 { 62 {
62 var folder = TestData.Get(@"TestData", "UsingFileShare"); 63 var folder = TestData.Get(@"TestData", "UsingFileShare");
@@ -79,7 +80,7 @@ namespace WixToolsetTest.Util
79 }, utilElementNames); 80 }, utilElementNames);
80 } 81 }
81 82
82 [Fact] 83 [TestMethod]
83 public void CanBuildCloseApplication() 84 public void CanBuildCloseApplication()
84 { 85 {
85 var folder = TestData.Get(@"TestData\CloseApplication"); 86 var folder = TestData.Get(@"TestData\CloseApplication");
@@ -96,7 +97,7 @@ namespace WixToolsetTest.Util
96 }, results.OrderBy(s => s).ToArray()); 97 }, results.OrderBy(s => s).ToArray());
97 } 98 }
98 99
99 [Fact] 100 [TestMethod]
100 public void CanBuildInternetShortcutInProduct() 101 public void CanBuildInternetShortcutInProduct()
101 { 102 {
102 var folder = TestData.Get(@"TestData\InternetShortcut"); 103 var folder = TestData.Get(@"TestData\InternetShortcut");
@@ -116,7 +117,7 @@ namespace WixToolsetTest.Util
116 }, results.OrderBy(s => s).ToArray()); 117 }, results.OrderBy(s => s).ToArray());
117 } 118 }
118 119
119 [Fact] 120 [TestMethod]
120 public void CanBuildInternetShortcutInMergeModule() 121 public void CanBuildInternetShortcutInMergeModule()
121 { 122 {
122 var folder = TestData.Get(@"TestData\InternetShortcutModule"); 123 var folder = TestData.Get(@"TestData\InternetShortcutModule");
@@ -136,7 +137,7 @@ namespace WixToolsetTest.Util
136 }, results.OrderBy(s => s).ToArray()); 137 }, results.OrderBy(s => s).ToArray());
137 } 138 }
138 139
139 [Fact] 140 [TestMethod]
140 public void CanBuildWithPermissionEx() 141 public void CanBuildWithPermissionEx()
141 { 142 {
142 var folder = TestData.Get(@"TestData\PermissionEx"); 143 var folder = TestData.Get(@"TestData\PermissionEx");
@@ -153,7 +154,7 @@ namespace WixToolsetTest.Util
153 }, results.OrderBy(s => s).ToArray()); 154 }, results.OrderBy(s => s).ToArray());
154 } 155 }
155 156
156 [Fact] 157 [TestMethod]
157 public void CanBuildRemoveRegistryKeyExInMergeModule() 158 public void CanBuildRemoveRegistryKeyExInMergeModule()
158 { 159 {
159 var folder = TestData.Get(@"TestData", "RemoveRegistryKeyEx"); 160 var folder = TestData.Get(@"TestData", "RemoveRegistryKeyEx");
@@ -168,7 +169,7 @@ namespace WixToolsetTest.Util
168 }, results.OrderBy(s => s).ToArray()); 169 }, results.OrderBy(s => s).ToArray());
169 } 170 }
170 171
171 [Fact] 172 [TestMethod]
172 public void CanBuildRemoveFolderExInMergeModule() 173 public void CanBuildRemoveFolderExInMergeModule()
173 { 174 {
174 var folder = TestData.Get(@"TestData\RemoveFolderEx"); 175 var folder = TestData.Get(@"TestData\RemoveFolderEx");
@@ -183,7 +184,7 @@ namespace WixToolsetTest.Util
183 }, results.OrderBy(s => s).ToArray()); 184 }, results.OrderBy(s => s).ToArray());
184 } 185 }
185 186
186 [Fact] 187 [TestMethod]
187 public void CanBuildRemoveFolderExInPackage() 188 public void CanBuildRemoveFolderExInPackage()
188 { 189 {
189 var folder = TestData.Get(@"TestData\RemoveFolderExPackage"); 190 var folder = TestData.Get(@"TestData\RemoveFolderExPackage");
@@ -198,7 +199,7 @@ namespace WixToolsetTest.Util
198 }, results.OrderBy(s => s).ToArray()); 199 }, results.OrderBy(s => s).ToArray());
199 } 200 }
200 201
201 [Fact] 202 [TestMethod]
202 public void CanBuildServiceConfig() 203 public void CanBuildServiceConfig()
203 { 204 {
204 var folder = TestData.Get(@"TestData", "ServiceConfig"); 205 var folder = TestData.Get(@"TestData", "ServiceConfig");
@@ -215,7 +216,7 @@ namespace WixToolsetTest.Util
215 }, results.OrderBy(s => s).ToArray()); 216 }, results.OrderBy(s => s).ToArray());
216 } 217 }
217 218
218 [Fact] 219 [TestMethod]
219 public void CanBuildWithEventManifest() 220 public void CanBuildWithEventManifest()
220 { 221 {
221 var folder = TestData.Get(@"TestData\EventManifest"); 222 var folder = TestData.Get(@"TestData\EventManifest");
@@ -240,7 +241,7 @@ namespace WixToolsetTest.Util
240 }, results.OrderBy(s => s).ToArray()); 241 }, results.OrderBy(s => s).ToArray());
241 } 242 }
242 243
243 [Fact] 244 [TestMethod]
244 public void CanBuildWithQueries() 245 public void CanBuildWithQueries()
245 { 246 {
246 var folder = TestData.Get(@"TestData\Queries"); 247 var folder = TestData.Get(@"TestData\Queries");
@@ -259,7 +260,7 @@ namespace WixToolsetTest.Util
259 }, results.OrderBy(s => s).ToArray()); 260 }, results.OrderBy(s => s).ToArray());
260 } 261 }
261 262
262 [Fact] 263 [TestMethod]
263 public void CanBuildAndDecompiileQueries() 264 public void CanBuildAndDecompiileQueries()
264 { 265 {
265 var folder = TestData.Get(@"TestData\Queries"); 266 var folder = TestData.Get(@"TestData\Queries");
@@ -285,7 +286,7 @@ namespace WixToolsetTest.Util
285 }, utilElementNames); 286 }, utilElementNames);
286 } 287 }
287 288
288 [Fact] 289 [TestMethod]
289 public void CanBuildWithXmlConfig() 290 public void CanBuildWithXmlConfig()
290 { 291 {
291 var folder = TestData.Get(@"TestData", "XmlConfig"); 292 var folder = TestData.Get(@"TestData", "XmlConfig");
@@ -301,7 +302,7 @@ namespace WixToolsetTest.Util
301 }, results.OrderBy(s => s).ToArray()); 302 }, results.OrderBy(s => s).ToArray());
302 } 303 }
303 304
304 [Fact] 305 [TestMethod]
305 public void CanRoundtripXmlConfig() 306 public void CanRoundtripXmlConfig()
306 { 307 {
307 var folder = TestData.Get(@"TestData", "XmlConfig"); 308 var folder = TestData.Get(@"TestData", "XmlConfig");
@@ -324,7 +325,7 @@ namespace WixToolsetTest.Util
324 }, utilElementNames); 325 }, utilElementNames);
325 } 326 }
326 327
327 [Fact] 328 [TestMethod]
328 public void CanBuildModuleWithXmlConfig() 329 public void CanBuildModuleWithXmlConfig()
329 { 330 {
330 var folder = TestData.Get(@"TestData", "XmlConfigModule"); 331 var folder = TestData.Get(@"TestData", "XmlConfigModule");
@@ -338,7 +339,7 @@ namespace WixToolsetTest.Util
338 }, results.OrderBy(s => s).ToArray()); 339 }, results.OrderBy(s => s).ToArray());
339 } 340 }
340 341
341 [Fact] 342 [TestMethod]
342 public void CanBuildBundleWithSearches() 343 public void CanBuildBundleWithSearches()
343 { 344 {
344 var folder = TestData.Get(@"TestData\BundleWithSearches"); 345 var folder = TestData.Get(@"TestData\BundleWithSearches");
@@ -366,15 +367,15 @@ namespace WixToolsetTest.Util
366 367
367 result.AssertSuccess(); 368 result.AssertSuccess();
368 369
369 Assert.True(File.Exists(bundlePath)); 370 Assert.IsTrue(File.Exists(bundlePath));
370 Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb"))); 371 Assert.IsTrue(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb")));
371 372
372 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); 373 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
373 extractResult.AssertSuccess(); 374 extractResult.AssertSuccess();
374 375
375 var bootstrapperExtensionDatas = extractResult.SelectBootstrapperExtensionDataNodes("/be:BootstrapperExtensionData/be:BootstrapperExtension[@Id='Wix4UtilBootstrapperExtension_X86']"); 376 var bootstrapperExtensionDatas = extractResult.SelectBootstrapperExtensionDataNodes("/be:BootstrapperExtensionData/be:BootstrapperExtension[@Id='Wix4UtilBootstrapperExtension_X86']");
376 Assert.Equal(1, bootstrapperExtensionDatas.Count); 377 Assert.AreEqual(1, bootstrapperExtensionDatas.Count);
377 Assert.Equal("<BootstrapperExtension Id='Wix4UtilBootstrapperExtension_X86'>" + 378 Assert.AreEqual("<BootstrapperExtension Id='Wix4UtilBootstrapperExtension_X86'>" +
378 "<WixWindowsFeatureSearch Id='DetectSHA2SupportId' Type='sha2CodeSigning' />" + 379 "<WixWindowsFeatureSearch Id='DetectSHA2SupportId' Type='sha2CodeSigning' />" +
379 "</BootstrapperExtension>", bootstrapperExtensionDatas[0].GetTestXml()); 380 "</BootstrapperExtension>", bootstrapperExtensionDatas[0].GetTestXml());
380 381
@@ -394,7 +395,7 @@ namespace WixToolsetTest.Util
394 } 395 }
395 } 396 }
396 397
397 [Fact] 398 [TestMethod]
398 public void CanCreateUserGroupWithComment() 399 public void CanCreateUserGroupWithComment()
399 { 400 {
400 var folder = TestData.Get(@"TestData\CreateGroup"); 401 var folder = TestData.Get(@"TestData\CreateGroup");
@@ -550,7 +551,7 @@ namespace WixToolsetTest.Util
550 }, results.OrderBy(s => s).ToArray()); 551 }, results.OrderBy(s => s).ToArray());
551 } 552 }
552 553
553 [Fact] 554 [TestMethod]
554 public void CanCreateUserAccountWithComment() 555 public void CanCreateUserAccountWithComment()
555 { 556 {
556 var folder = TestData.Get(@"TestData\CreateUser"); 557 var folder = TestData.Get(@"TestData\CreateUser");
@@ -626,7 +627,7 @@ namespace WixToolsetTest.Util
626 }, results.OrderBy(s => s).ToArray()); 627 }, results.OrderBy(s => s).ToArray());
627 } 628 }
628 629
629 [Fact] 630 [TestMethod]
630 public void CannotBuildBundleWithSearchesUsingBuiltinVariableNames() 631 public void CannotBuildBundleWithSearchesUsingBuiltinVariableNames()
631 { 632 {
632 var folder = TestData.Get("TestData", "BundleWithSearches"); 633 var folder = TestData.Get("TestData", "BundleWithSearches");
diff --git a/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj b/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj
index 16d0e138..4036c3ab 100644
--- a/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj
+++ b/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/Util/util.cmd b/src/ext/Util/util.cmd
deleted file mode 100644
index 3c66e7d8..00000000
--- a/src/ext/Util/util.cmd
+++ /dev/null
@@ -1,45 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5@set _L=%~dp0..\..\..\build\logs
6
7:parse_args
8@if /i "%1"=="release" set _C=Release
9@if /i "%1"=="inc" set _INC=1
10@if /i "%1"=="clean" set _CLEAN=1
11@if not "%1"=="" shift & goto parse_args
12
13@set _B=%~dp0..\..\..\build\Util.wixext\%_C%
14
15:: Clean
16
17@if "%_INC%"=="" call :clean
18@if NOT "%_CLEAN%"=="" goto :end
19
20@echo Building ext\Util %_C% using %_N%
21
22:: Build
23msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror -bl:%_L%\ext_util_build.binlog || exit /b
24
25:: Test
26dotnet test ^
27 %_B%\net6.0\WixToolsetTest.Util.dll ^
28 --nologo -l "trx;LogFileName=%_L%\TestResults\util.wixext.trx" || exit /b
29
30:: Pack
31msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.Util.wixext.csproj || exit /b
32
33@goto :end
34
35:clean
36@rd /s/q "..\..\build\Util.wixext" 2> nul
37@del "..\..\build\artifacts\WixToolset.Util.wixext.*.nupkg" 2> nul
38@del "%_L%\ext_util_build.binlog" 2> nul
39@del "%_L%\TestResults\util.wixext.trx" 2> nul
40@rd /s/q "%USERPROFILE%\.nuget\packages\wixtoolset.util.wixext" 2> nul
41@exit /b
42
43:end
44@popd
45@endlocal
diff --git a/src/ext/Util/util_t.proj b/src/ext/Util/util_t.proj
new file mode 100644
index 00000000..e1da6adf
--- /dev/null
+++ b/src/ext/Util/util_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.Util\WixToolsetTest.Util.csproj" />
7 <ProjectReference Include="wixext\WixToolset.Util.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)Util.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.util.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.util.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.Util.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/VisualStudioExtensionFixture.cs b/src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/VisualStudioExtensionFixture.cs
index f3e81e2d..992ac953 100644
--- a/src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/VisualStudioExtensionFixture.cs
+++ b/src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/VisualStudioExtensionFixture.cs
@@ -2,15 +2,16 @@
2 2
3namespace WixToolsetTest.VisualStudio 3namespace WixToolsetTest.VisualStudio
4{ 4{
5 using WixInternal.TestSupport; 5 using Microsoft.VisualStudio.TestTools.UnitTesting;
6 using WixInternal.Core.TestPackage; 6 using WixInternal.MSTestSupport;
7 using WixInternal.Core.MSTestPackage;
7 using WixToolset.VisualStudio; 8 using WixToolset.VisualStudio;
8 using Xunit;
9 using System.Linq; 9 using System.Linq;
10 10
11 [TestClass]
11 public class VisualStudioExtensionFixture 12 public class VisualStudioExtensionFixture
12 { 13 {
13 [Fact] 14 [TestMethod]
14 public void CanBuildUsingVsixPackage() 15 public void CanBuildUsingVsixPackage()
15 { 16 {
16 var folder = TestData.Get(@"TestData\UsingVsixPackage"); 17 var folder = TestData.Get(@"TestData\UsingVsixPackage");
@@ -36,7 +37,7 @@ namespace WixToolsetTest.VisualStudio
36 }, results); 37 }, results);
37 } 38 }
38 39
39 [Fact] 40 [TestMethod]
40 public void CanBuildUsingVsixPackageOnArm64() 41 public void CanBuildUsingVsixPackageOnArm64()
41 { 42 {
42 var folder = TestData.Get(@"TestData\UsingVsixPackage"); 43 var folder = TestData.Get(@"TestData\UsingVsixPackage");
diff --git a/src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/WixToolsetTest.VisualStudio.csproj b/src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/WixToolsetTest.VisualStudio.csproj
index 2b0a7c1c..9cfb6867 100644
--- a/src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/WixToolsetTest.VisualStudio.csproj
+++ b/src/ext/VisualStudio/test/WixToolsetTest.VisualStudio/WixToolsetTest.VisualStudio.csproj
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project Sdk="Microsoft.NET.Sdk"> 4<Project Sdk="MSTest.Sdk">
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixMSTestProject>true</IsWixMSTestProject>
8 </PropertyGroup> 8 </PropertyGroup>
9 9
10 <ItemGroup> 10 <ItemGroup>
@@ -16,6 +16,7 @@
16 </ItemGroup> 16 </ItemGroup>
17 17
18 <ItemGroup> 18 <ItemGroup>
19 <PackageReference Include="WixInternal.Core.TestPackage" /> 19 <PackageReference Include="WixInternal.MSTestSupport" />
20 <PackageReference Include="WixInternal.Core.MSTestPackage" />
20 </ItemGroup> 21 </ItemGroup>
21</Project> 22</Project>
diff --git a/src/ext/VisualStudio/visualstudio_t.proj b/src/ext/VisualStudio/visualstudio_t.proj
new file mode 100644
index 00000000..52de8019
--- /dev/null
+++ b/src/ext/VisualStudio/visualstudio_t.proj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <ProjectReference Include="test\WixToolsetTest.VisualStudio\WixToolsetTest.VisualStudio.csproj" />
7 <ProjectReference Include="wixext\WixToolset.VisualStudio.wixext.csproj" Targets="Pack" Properties="NoBuild=true" />
8 </ItemGroup>
9
10 <Target Name="WixClean" BeforeTargets="Restore" Condition="'$(SuppressWixClean)' != 'true'">
11 <RemoveDir Directories="$(RootBuildFolder)VisualStudio.wixext" />
12 <RemoveDir Directories="$(USERPROFILE)\.nuget\packages\wixtoolset.VisualStudio.wixext" Condition="'$(NUGET_PACKAGES)' == ''" />
13 <RemoveDir Directories="$(NUGET_PACKAGES)\wixtoolset.VisualStudio.wixext" Condition="'$(NUGET_PACKAGES)' != ''" />
14
15 <Delete Files="$(ArtifactsFolder)WixToolset.VisualStudio.wixext.*.nupkg" />
16 </Target>
17</Project>
diff --git a/src/ext/VisualStudio/vs.cmd b/src/ext/VisualStudio/vs.cmd
deleted file mode 100644
index f0873f1d..00000000
--- a/src/ext/VisualStudio/vs.cmd
+++ /dev/null
@@ -1,21 +0,0 @@
1@setlocal
2@pushd %~dp0
3
4@set _C=Debug
5:parse_args
6@if /i "%1"=="release" set _C=Release
7@if not "%1"=="" shift & goto parse_args
8
9@echo VisualStudio.wixext build %_C%
10
11:: Build
12msbuild -Restore -p:Configuration=%_C% -tl -nologo -warnaserror || exit /b
13
14:: Test
15dotnet test -c %_C% --no-build test\WixToolsetTest.VisualStudio || exit /b
16
17:: Pack
18msbuild -t:Pack -p:Configuration=%_C% -tl -nologo -warnaserror -p:NoBuild=true wixext\WixToolset.VisualStudio.wixext.csproj || exit /b
19
20@popd
21@endlocal
diff --git a/src/ext/ext.cmd b/src/ext/ext.cmd
index 8575b81e..86aac47b 100644
--- a/src/ext/ext.cmd
+++ b/src/ext/ext.cmd
@@ -2,58 +2,15 @@
2@pushd %~dp0 2@pushd %~dp0
3 3
4@set _C=Debug 4@set _C=Debug
5@set _L=%~dp0..\..\build\logs
6@set _SuppressWixClean=false
7
5:parse_args 8:parse_args
6@if /i "%1"=="release" set _C=Release 9@if /i "%1"=="release" set _C=Release
10@if /i "%1"=="inc" set _SuppressWixClean=true
7@if not "%1"=="" shift & goto parse_args 11@if not "%1"=="" shift & goto parse_args
8 12
9@echo ext build %_C% 13msbuild ext_t.proj -p:Configuration=%_C% -p:SuppressWixClean=%_SuppressWixClean% -m -tl -nologo -warnaserror -bl:%_L%\ext_build.binlog || exit /b
10
11:: These extensions must be built in this order.
12
13:: Util
14call Util\util.cmd %_C% || exit /b
15
16:: Bal
17call Bal\bal.cmd %_C% || exit /b
18
19:: NetFx
20call NetFx\netfx.cmd %_C% || exit /b
21
22
23:: The rest of the extensions are in alphabetical order.
24
25:: ComPlus
26call ComPlus\complus.cmd %_C% || exit /b
27
28:: Dependency
29call Dependency\dependency.cmd %_C% || exit /b
30
31:: DirectX
32call DirectX\directx.cmd %_C% || exit /b
33
34:: Firewall
35call Firewall\firewall.cmd %_C% || exit /b
36
37:: Http
38call Http\http.cmd %_C% || exit /b
39
40:: Iis
41call Iis\iis.cmd %_C% || exit /b
42
43:: Msmq
44call Msmq\msmq.cmd %_C% || exit /b
45
46:: PowerShell
47call PowerShell\ps.cmd %_C% || exit /b
48
49:: Sql
50call Sql\sql.cmd %_C% || exit /b
51
52:: UI
53call UI\ui.cmd %_C% || exit /b
54
55:: VisualStudio
56call VisualStudio\vs.cmd %_C% || exit /b
57 14
58@popd 15@popd
59@endlocal 16@endlocal
diff --git a/src/ext/ext_t.proj b/src/ext/ext_t.proj
new file mode 100644
index 00000000..e3301172
--- /dev/null
+++ b/src/ext/ext_t.proj
@@ -0,0 +1,30 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.Build.Traversal">
5 <ItemGroup>
6 <!-- These projects are "special." -->
7 <ProjectReference Include="Util\util_t.proj" BuildInParallel="false" Targets="Restore;Build" Properties="SuppressWixTests=true" />
8 <ProjectReference Include="Bal\bal_t.proj" BuildInParallel="false" Targets="Restore;Build" Properties="SuppressWixTests=true" />
9 <!-- <ProjectReference Include="NetFx\netfx_t.proj" BuildInParallel="false" Targets="Restore;Build" Properties="SuppressWixTests=true" /> -->
10
11 <!-- Now run tests we skipped earlier along with everything in parallel. -->
12 <ProjectReference Include="Util\util_t.proj" Targets="Build" />
13 <ProjectReference Include="Bal\bal_t.proj" Targets="Build" />
14 <!-- <ProjectReference Include="NetFx\netfx_t.proj" Targets="Build" /> -->
15
16 <ProjectReference Include="NetFx\netfx_t.proj" BuildInParallel="false" Targets="Restore;Build" />
17 <ProjectReference Include="ComPlus\complus_t.proj" Targets="Restore;Build" />
18 <ProjectReference Include="Dependency\dependency_t.proj" Targets="Restore;Build" />
19 <ProjectReference Include="DirectX\directx_t.proj" Targets="Restore;Build" />
20 <ProjectReference Include="Firewall\firewall_t.proj" Targets="Restore;Build" />
21 <ProjectReference Include="Http\http_t.proj" Targets="Restore;Build" />
22 <ProjectReference Include="Iis\iis_t.proj" Targets="Restore;Build" />
23 <ProjectReference Include="Msmq\msmq_t.proj" Targets="Restore;Build" />
24 <ProjectReference Include="NetFx\netfx_t.proj" Targets="Restore;Build" />
25 <ProjectReference Include="PowerShell\powershell_t.proj" Targets="Restore;Build" />
26 <ProjectReference Include="Sql\sql_t.proj" Targets="Restore;Build" />
27 <ProjectReference Include="UI\ui_t.proj" Targets="Restore;Build" />
28 <ProjectReference Include="VisualStudio\visualstudio_t.proj" Targets="Restore;Build" />
29 </ItemGroup>
30</Project>
diff --git a/src/internal/SetBuildNumber/Directory.Packages.props.pp b/src/internal/SetBuildNumber/Directory.Packages.props.pp
index 8cf271d7..18a9b5eb 100644
--- a/src/internal/SetBuildNumber/Directory.Packages.props.pp
+++ b/src/internal/SetBuildNumber/Directory.Packages.props.pp
@@ -17,6 +17,7 @@
17 <PackageVersion Include="WixToolset.Dtf.WindowsInstaller.Package" Version="{packageversion}" /> 17 <PackageVersion Include="WixToolset.Dtf.WindowsInstaller.Package" Version="{packageversion}" />
18 18
19 <PackageVersion Include="WixInternal.TestSupport" Version="{packageversion}" /> 19 <PackageVersion Include="WixInternal.TestSupport" Version="{packageversion}" />
20 <PackageVersion Include="WixInternal.MSTestSupport" Version="{packageversion}" />
20 <PackageVersion Include="WixInternal.TestSupport.Native" Version="{packageversion}" /> 21 <PackageVersion Include="WixInternal.TestSupport.Native" Version="{packageversion}" />
21 <PackageVersion Include="WixInternal.BaseBuildTasks.Sources" Version="{packageversion}" /> 22 <PackageVersion Include="WixInternal.BaseBuildTasks.Sources" Version="{packageversion}" />
22 23
@@ -37,6 +38,7 @@
37 <PackageVersion Include="WixToolset.Core.Burn" Version="{packageversion}" /> 38 <PackageVersion Include="WixToolset.Core.Burn" Version="{packageversion}" />
38 <PackageVersion Include="WixToolset.Core.WindowsInstaller" Version="{packageversion}" /> 39 <PackageVersion Include="WixToolset.Core.WindowsInstaller" Version="{packageversion}" />
39 <PackageVersion Include="WixInternal.Core.TestPackage" Version="{packageversion}" /> 40 <PackageVersion Include="WixInternal.Core.TestPackage" Version="{packageversion}" />
41 <PackageVersion Include="WixInternal.Core.MSTestPackage" Version="{packageversion}" />
40 42
41 <PackageVersion Include="WixToolset.Heat" Version="{packageversion}" /> 43 <PackageVersion Include="WixToolset.Heat" Version="{packageversion}" />
42 44
@@ -98,6 +100,10 @@
98 </ItemGroup> 100 </ItemGroup>
99 101
100 <ItemGroup> 102 <ItemGroup>
103 <PackageVersion Include="MSTest.TestFramework" Version="3.7.3" />
104 </ItemGroup>
105
106 <ItemGroup>
101 <PackageVersion Include="Microsoft.NET.Tools.NETCoreCheck.x86" Version="6.0.0" /> 107 <PackageVersion Include="Microsoft.NET.Tools.NETCoreCheck.x86" Version="6.0.0" />
102 <PackageVersion Include="Microsoft.NET.Tools.NETCoreCheck.x64" Version="6.0.0" /> 108 <PackageVersion Include="Microsoft.NET.Tools.NETCoreCheck.x64" Version="6.0.0" />
103 <PackageVersion Include="Microsoft.NET.Tools.NETCoreCheck.arm64" Version="6.0.0" /> 109 <PackageVersion Include="Microsoft.NET.Tools.NETCoreCheck.arm64" Version="6.0.0" />
diff --git a/src/internal/SetBuildNumber/global.json.pp b/src/internal/SetBuildNumber/global.json.pp
index bad3c0bd..fe48e6cc 100644
--- a/src/internal/SetBuildNumber/global.json.pp
+++ b/src/internal/SetBuildNumber/global.json.pp
@@ -1,6 +1,7 @@
1{ 1{
2 "msbuild-sdks": { 2 "msbuild-sdks": {
3 "Microsoft.Build.Traversal": "3.2.0", 3 "MSTest.Sdk": "3.8.0",
4 "Microsoft.Build.Traversal": "4.1.82",
4 "Microsoft.Build.NoTargets": "3.5.6", 5 "Microsoft.Build.NoTargets": "3.5.6",
5 "WixToolset.Sdk": "{packageversion}" 6 "WixToolset.Sdk": "{packageversion}"
6 }, 7 },
diff --git a/src/internal/WixInternal.MSTestSupport/Builder.cs b/src/internal/WixInternal.MSTestSupport/Builder.cs
new file mode 100644
index 00000000..62f2891b
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/Builder.cs
@@ -0,0 +1,204 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8
9 public class Builder
10 {
11 public Builder(string sourceFolder, Type extensionType = null, string[] bindPaths = null, string outputFile = null)
12 {
13 this.SourceFolder = sourceFolder;
14 if (extensionType != null)
15 {
16 this.ExtensionTypes = new Type[] { extensionType };
17 }
18 else
19 {
20 this.ExtensionTypes = new Type[] { };
21 }
22 this.BindPaths = bindPaths;
23 this.OutputFile = outputFile ?? "test.msi";
24 }
25
26 public Builder(string sourceFolder, Type[] extensionTypes, string[] bindPaths = null, string outputFile = null)
27 {
28 this.SourceFolder = sourceFolder;
29 this.ExtensionTypes = extensionTypes;
30 this.BindPaths = bindPaths;
31 this.OutputFile = outputFile ?? "test.msi";
32 }
33
34 public string[] BindPaths { get; set; }
35
36 public Type[] ExtensionTypes { get; set; }
37
38 public string OutputFile { get; set; }
39
40 public string SourceFolder { get; }
41
42 public string[] BuildAndQuery(Action<string[]> buildFunc, params string[] tables)
43 {
44 return this.BuildAndQuery(buildFunc, validate: false, tables);
45 }
46
47 public string[] BuildAndQuery(Action<string[]> buildFunc, bool validate, params string[] tables)
48 {
49 var sourceFiles = Directory.GetFiles(this.SourceFolder, "*.wxs");
50 var wxlFiles = Directory.GetFiles(this.SourceFolder, "*.wxl");
51
52 using (var fs = new DisposableFileSystem())
53 {
54 var intermediateFolder = fs.GetFolder();
55 var outputPath = Path.Combine(intermediateFolder, "bin", this.OutputFile);
56
57 var args = new List<string>
58 {
59 "build",
60 "-o", outputPath,
61 "-intermediateFolder", intermediateFolder,
62 };
63
64 foreach (var ext in this.ExtensionTypes)
65 {
66 args.Add("-ext");
67 args.Add(Path.GetFullPath(ext.Assembly.Location));
68 }
69
70 args.AddRange(sourceFiles);
71
72 foreach (var wxlFile in wxlFiles)
73 {
74 args.Add("-loc");
75 args.Add(wxlFile);
76 }
77
78 foreach (var bindPath in this.BindPaths)
79 {
80 args.Add("-bindpath");
81 args.Add(bindPath);
82 }
83
84 buildFunc(args.ToArray());
85
86 if (validate)
87 {
88 args = new List<string>
89 {
90 "msi",
91 "validate",
92 "-intermediateFolder", intermediateFolder,
93 outputPath,
94 };
95
96 buildFunc(args.ToArray());
97 }
98
99 return Query.QueryDatabase(outputPath, tables);
100 }
101 }
102
103 public void BuildAndDecompileAndBuild(Action<string[]> buildFunc, Action<string[]> decompileFunc, string decompilePath, bool validate = false)
104 {
105 var sourceFiles = Directory.GetFiles(this.SourceFolder, "*.wxs");
106 var wxlFiles = Directory.GetFiles(this.SourceFolder, "*.wxl");
107
108 using (var fs = new DisposableFileSystem())
109 {
110 var intermediateFolder = fs.GetFolder();
111 var outputFolder = Path.Combine(intermediateFolder, "bin");
112 var decompileExtractFolder = Path.Combine(intermediateFolder, "decompiled", "extract");
113 var decompileIntermediateFolder = Path.Combine(intermediateFolder, "decompiled", "obj");
114 var decompileBuildFolder = Path.Combine(intermediateFolder, "decompiled", "bin");
115 var outputPath = Path.Combine(outputFolder, this.OutputFile);
116 var decompileBuildPath = Path.Combine(decompileBuildFolder, this.OutputFile);
117
118 // First build.
119 var firstBuildArgs = new List<string>
120 {
121 "build",
122 "-o", outputPath,
123 "-intermediateFolder", intermediateFolder,
124 };
125
126 foreach (var ext in this.ExtensionTypes)
127 {
128 firstBuildArgs.Add("-ext");
129 firstBuildArgs.Add(Path.GetFullPath(ext.Assembly.Location));
130 }
131
132 firstBuildArgs.AddRange(sourceFiles);
133
134 foreach (var wxlFile in wxlFiles)
135 {
136 firstBuildArgs.Add("-loc");
137 firstBuildArgs.Add(wxlFile);
138 }
139
140 foreach (var bindPath in this.BindPaths)
141 {
142 firstBuildArgs.Add("-bindpath");
143 firstBuildArgs.Add(bindPath);
144 }
145
146 buildFunc(firstBuildArgs.ToArray());
147
148 if (validate)
149 {
150 firstBuildArgs = new List<string>
151 {
152 "msi",
153 "validate",
154 "-intermediateFolder", intermediateFolder,
155 outputPath,
156 };
157
158 buildFunc(firstBuildArgs.ToArray());
159 }
160
161 // Decompile built output.
162 var decompileArgs = new List<string>
163 {
164 "msi", "decompile",
165 outputPath,
166 "-intermediateFolder", decompileIntermediateFolder,
167 "-x", decompileExtractFolder,
168 "-o", decompilePath
169 };
170
171 foreach (var ext in this.ExtensionTypes)
172 {
173 decompileArgs.Add("-ext");
174 decompileArgs.Add(Path.GetFullPath(ext.Assembly.Location));
175 }
176
177 decompileFunc(decompileArgs.ToArray());
178
179 // Build decompiled output.
180 var secondBuildArgs = new List<string>
181 {
182 "build",
183 decompilePath,
184 "-o", decompileBuildPath,
185 "-intermediateFolder", decompileIntermediateFolder
186 };
187
188 foreach (var ext in this.ExtensionTypes)
189 {
190 secondBuildArgs.Add("-ext");
191 secondBuildArgs.Add(Path.GetFullPath(ext.Assembly.Location));
192 }
193
194 secondBuildArgs.Add("-bindpath");
195 secondBuildArgs.Add(outputFolder);
196
197 secondBuildArgs.Add("-bindpath");
198 secondBuildArgs.Add(decompileExtractFolder);
199
200 buildFunc(secondBuildArgs.ToArray());
201 }
202 }
203 }
204}
diff --git a/src/internal/WixInternal.MSTestSupport/DisposableFileSystem.cs b/src/internal/WixInternal.MSTestSupport/DisposableFileSystem.cs
new file mode 100644
index 00000000..5e4bb23f
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/DisposableFileSystem.cs
@@ -0,0 +1,94 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8
9 public class DisposableFileSystem : IDisposable
10 {
11 protected bool Disposed { get; private set; }
12
13 private List<string> CleanupPaths { get; } = new List<string>();
14
15 public bool Keep { get; }
16
17 public DisposableFileSystem(bool keep = false)
18 {
19 this.Keep = keep;
20 }
21
22 protected string GetFile(bool create = false)
23 {
24 var path = Path.GetTempFileName();
25
26 if (!create)
27 {
28 File.Delete(path);
29 }
30
31 this.CleanupPaths.Add(path);
32
33 return path;
34 }
35
36 public string GetFolder(bool create = false)
37 {
38 // Always return a path with a space in it.
39 var path = Path.Combine(Path.GetTempPath(), ".WIXTEST " + Path.GetRandomFileName());
40
41 if (create)
42 {
43 Directory.CreateDirectory(path);
44 }
45
46 this.CleanupPaths.Add(path);
47
48 return path;
49 }
50
51
52 #region // IDisposable
53
54 public void Dispose()
55 {
56 this.Dispose(true);
57 GC.SuppressFinalize(this);
58 }
59
60 protected virtual void Dispose(bool disposing)
61 {
62 if (this.Disposed)
63 {
64 return;
65 }
66
67 if (disposing && !this.Keep)
68 {
69 foreach (var path in this.CleanupPaths)
70 {
71 try
72 {
73 if (File.Exists(path))
74 {
75 File.Delete(path);
76 }
77 else if (Directory.Exists(path))
78 {
79 Directory.Delete(path, true);
80 }
81 }
82 catch
83 {
84 // Best effort delete, so ignore any failures.
85 }
86 }
87 }
88
89 this.Disposed = true;
90 }
91
92 #endregion
93 }
94}
diff --git a/src/internal/WixInternal.MSTestSupport/DotnetRunner.cs b/src/internal/WixInternal.MSTestSupport/DotnetRunner.cs
new file mode 100644
index 00000000..8fa3a739
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/DotnetRunner.cs
@@ -0,0 +1,57 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8
9 public class DotnetRunner : ExternalExecutable
10 {
11 private static readonly object InitLock = new object();
12 private static bool Initialized;
13 private static DotnetRunner Instance;
14
15 public static ExternalExecutableResult Execute(string command, string[] arguments = null) =>
16 InitAndExecute(command, arguments);
17
18 private static ExternalExecutableResult InitAndExecute(string command, string[] arguments)
19 {
20 lock (InitLock)
21 {
22 if (!Initialized)
23 {
24 Initialized = true;
25 var dotnetPath = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH");
26 if (String.IsNullOrEmpty(dotnetPath) || !File.Exists(dotnetPath))
27 {
28 dotnetPath = "dotnet";
29 }
30
31 Instance = new DotnetRunner(dotnetPath);
32 }
33 }
34
35 return Instance.ExecuteCore(command, arguments);
36 }
37
38 private DotnetRunner(string exePath) : base(exePath) { }
39
40 private ExternalExecutableResult ExecuteCore(string command, string[] arguments)
41 {
42 var total = new List<string>
43 {
44 command,
45 };
46
47 if (arguments != null)
48 {
49 total.AddRange(arguments);
50 }
51
52 var args = CombineArguments(total);
53 var mergeErrorIntoOutput = true;
54 return this.Run(args, mergeErrorIntoOutput);
55 }
56 }
57}
diff --git a/src/internal/WixInternal.MSTestSupport/ExternalExecutable.cs b/src/internal/WixInternal.MSTestSupport/ExternalExecutable.cs
new file mode 100644
index 00000000..927240ec
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/ExternalExecutable.cs
@@ -0,0 +1,374 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.Collections.Concurrent;
7 using System.Collections.Generic;
8 using System.ComponentModel;
9 using System.Diagnostics;
10 using System.IO;
11 using System.Runtime.InteropServices;
12 using System.Text;
13 using System.Threading.Tasks;
14 using Microsoft.Win32.SafeHandles;
15
16 public abstract class ExternalExecutable
17 {
18 private readonly string exePath;
19
20 protected ExternalExecutable(string exePath)
21 {
22 this.exePath = exePath;
23 }
24
25 protected ExternalExecutableResult Run(string args, bool mergeErrorIntoOutput = false, string workingDirectory = null)
26 {
27 // https://github.com/dotnet/runtime/issues/58492
28 // Process.Start doesn't currently support starting a process with a long path,
29 // but the way to support long paths doesn't support searching for the executable if it was a relative path.
30 // Avoid the managed way of doing this even if the target isn't a long path to help verify that the native way works.
31 if (!Path.IsPathRooted(this.exePath))
32 {
33 return this.RunManaged(args, mergeErrorIntoOutput, workingDirectory);
34 }
35
36 // https://web.archive.org/web/20150331190801/https://support.microsoft.com/en-us/kb/190351
37 var commandLine = $"\"{this.exePath}\" {args}";
38 var currentDirectory = workingDirectory ?? Path.GetDirectoryName(this.exePath);
39 if (String.IsNullOrEmpty(currentDirectory))
40 {
41 currentDirectory = null;
42 }
43 var processInfo = new PROCESS_INFORMATION();
44 var startInfo = new STARTUPINFOW
45 {
46 cb = Marshal.SizeOf(typeof(STARTUPINFOW)),
47 dwFlags = StartupInfoFlags.STARTF_FORCEOFFFEEDBACK | StartupInfoFlags.STARTF_USESTDHANDLES,
48 hStdInput = GetStdHandle(StdHandleType.STD_INPUT_HANDLE),
49 };
50 SafeFileHandle hStdOutputParent = null;
51 SafeFileHandle hStdErrorParent = null;
52
53 try
54 {
55 CreatePipeForProcess(out hStdOutputParent, out startInfo.hStdOutput);
56
57 if (!mergeErrorIntoOutput)
58 {
59 CreatePipeForProcess(out hStdErrorParent, out startInfo.hStdError);
60 }
61 else
62 {
63 if (!DuplicateHandle(GetCurrentProcess(), startInfo.hStdOutput, GetCurrentProcess(), out startInfo.hStdError, 0, true, DuplicateHandleOptions.DUPLICATE_SAME_ACCESS))
64 {
65 throw new Win32Exception();
66 }
67 }
68
69 if (!CreateProcessW(this.exePath, commandLine, IntPtr.Zero, IntPtr.Zero, true, CreateProcessFlags.CREATE_NO_WINDOW, IntPtr.Zero,
70 currentDirectory, ref startInfo, ref processInfo))
71 {
72 throw new Win32Exception();
73 }
74
75 startInfo.Dispose();
76
77 return GetResultFromNative(mergeErrorIntoOutput, hStdOutputParent, hStdErrorParent, processInfo.hProcess, this.exePath, args);
78 }
79 finally
80 {
81 hStdErrorParent?.Dispose();
82 hStdOutputParent?.Dispose();
83
84 startInfo.Dispose();
85 processInfo.Dispose();
86 }
87 }
88
89 private static ExternalExecutableResult GetResultFromNative(bool mergeErrorIntoOutput, SafeFileHandle hStdOutputParent, SafeFileHandle hStdErrorParent, IntPtr hProcess, string fileName, string args)
90 {
91 using (var outputStream = new StreamReader(new FileStream(hStdOutputParent, FileAccess.Read)))
92 using (var errorStream = mergeErrorIntoOutput ? null : new StreamReader(new FileStream(hStdErrorParent, FileAccess.Read)))
93 {
94 var outputTask = Task.Run(() => ReadProcessStreamLines(outputStream));
95 var errorTask = Task.Run(() => ReadProcessStreamLines(errorStream));
96
97 while (!outputTask.Wait(100) || !errorTask.Wait(100)) { Task.Yield(); }
98 var standardOutput = outputTask.Result;
99 var standardError = errorTask.Result;
100
101 if (WaitForSingleObject(hProcess, -1) != 0)
102 {
103 throw new Win32Exception();
104 }
105
106 if (!GetExitCodeProcess(hProcess, out var exitCode))
107 {
108 throw new Win32Exception();
109 }
110
111 return new ExternalExecutableResult
112 {
113 ExitCode = exitCode,
114 StandardError = standardError,
115 StandardOutput = standardOutput,
116 FileName = fileName,
117 Arguments = args,
118 };
119 }
120 }
121
122 private static string[] ReadProcessStreamLines(StreamReader streamReader)
123 {
124 if (streamReader == null)
125 {
126 return null;
127 }
128
129 var lines = new List<string>();
130 while (true)
131 {
132 var line = streamReader.ReadLine();
133 if (line == null)
134 {
135 break;
136 }
137
138 lines.Add(line);
139 }
140
141 return lines.ToArray();
142 }
143
144 protected ExternalExecutableResult RunManaged(string args, bool mergeErrorIntoOutput = false, string workingDirectory = null)
145 {
146 var startInfo = new ProcessStartInfo(this.exePath, args)
147 {
148 CreateNoWindow = true,
149 RedirectStandardError = true,
150 RedirectStandardOutput = true,
151 UseShellExecute = false,
152 WorkingDirectory = workingDirectory ?? Path.GetDirectoryName(this.exePath),
153 };
154
155 using (var process = Process.Start(startInfo))
156 {
157 // This implementation of merging the streams does not guarantee that lines are retrieved in the same order that they were written.
158 // If the process is simultaneously writing to both streams, this is impossible to do anyway.
159 var standardOutput = new ConcurrentQueue<string>();
160 var standardError = mergeErrorIntoOutput ? standardOutput : new ConcurrentQueue<string>();
161
162 process.ErrorDataReceived += (s, e) => { if (e.Data != null) { standardError.Enqueue(e.Data); } };
163 process.OutputDataReceived += (s, e) => { if (e.Data != null) { standardOutput.Enqueue(e.Data); } };
164
165 process.BeginErrorReadLine();
166 process.BeginOutputReadLine();
167
168 process.WaitForExit();
169
170 return new ExternalExecutableResult
171 {
172 ExitCode = process.ExitCode,
173 StandardError = mergeErrorIntoOutput ? null : standardError.ToArray(),
174 StandardOutput = standardOutput.ToArray(),
175 FileName = this.exePath,
176 Arguments = args,
177 };
178 }
179 }
180
181 // This is internal because it assumes backslashes aren't used as escape characters and there aren't any double quotes.
182 internal static string CombineArguments(IEnumerable<string> arguments)
183 {
184 if (arguments == null)
185 {
186 return null;
187 }
188
189 var sb = new StringBuilder();
190
191 foreach (var arg in arguments)
192 {
193 if (sb.Length > 0)
194 {
195 sb.Append(' ');
196 }
197
198 if (arg.IndexOf(' ') > -1 && !arg.EndsWith("\""))
199 {
200 sb.Append("\"");
201 sb.Append(arg);
202 sb.Append("\"");
203 }
204 else
205 {
206 sb.Append(arg);
207 }
208 }
209
210 return sb.ToString();
211 }
212
213 private static void CreatePipeForProcess(out SafeFileHandle hReadPipe, out IntPtr hWritePipe)
214 {
215 var securityAttributes = new SECURITY_ATTRIBUTES
216 {
217 nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)),
218 bInheritHandle = true,
219 };
220
221 if (!CreatePipe(out var hReadTemp, out hWritePipe, ref securityAttributes, 0))
222 {
223 throw new Win32Exception();
224 }
225
226 // Only the handle passed to the process should be inheritable, so have to duplicate the other handle to get an uninheritable one.
227 if (!DuplicateHandle(GetCurrentProcess(), hReadTemp, GetCurrentProcess(), out var hReadPipePtr, 0, false, DuplicateHandleOptions.DUPLICATE_CLOSE_SOURCE | DuplicateHandleOptions.DUPLICATE_SAME_ACCESS))
228 {
229 throw new Win32Exception();
230 }
231
232 hReadPipe = new SafeFileHandle(hReadPipePtr, true);
233 }
234
235 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
236 private extern static IntPtr GetStdHandle(StdHandleType nStdHandle);
237
238 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
239 [return: MarshalAs(UnmanagedType.Bool)]
240 private extern static bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize);
241
242 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
243 [return: MarshalAs(UnmanagedType.Bool)]
244 private extern static bool CreateProcessW(
245 string lpApplicationName,
246 string lpCommandLine,
247 IntPtr lpProcessAttributes,
248 IntPtr lpThreadAttributes,
249 [MarshalAs(UnmanagedType.Bool)] bool bInheritHandles,
250 CreateProcessFlags dwCreationFlags,
251 IntPtr lpEnvironment,
252 string lpCurrentDirectory,
253 ref STARTUPINFOW lpStartupInfo,
254 ref PROCESS_INFORMATION lpProcessInformation);
255
256 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
257 private extern static IntPtr GetCurrentProcess();
258
259 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
260 [return: MarshalAs(UnmanagedType.Bool)]
261 private extern static bool GetExitCodeProcess(IntPtr hHandle, out int lpExitCode);
262
263 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
264 private extern static int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
265
266 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
267 [return: MarshalAs(UnmanagedType.Bool)]
268 private extern static bool CloseHandle(IntPtr hObject);
269
270 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
271 [return: MarshalAs(UnmanagedType.Bool)]
272 private extern static bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, DuplicateHandleOptions dwOptions);
273
274 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
275 private struct SECURITY_ATTRIBUTES
276 {
277 public int nLength;
278 public IntPtr lpSecurityDescriptor;
279 [MarshalAs(UnmanagedType.Bool)]
280 public bool bInheritHandle;
281 }
282
283 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
284 private struct STARTUPINFOW
285 {
286 public int cb;
287 public string lpReserved;
288 public string lpDesktop;
289 public string lpTitle;
290 public int dwX;
291 public int dwY;
292 public int dwXSize;
293 public int dwYSize;
294 public int dwXCountChars;
295 public int dwYCountChars;
296 public int dwFillAttribute;
297 public StartupInfoFlags dwFlags;
298 public short wShowWindow;
299 public short cbReserved2;
300 public IntPtr lpReserved2;
301 public IntPtr hStdInput;
302 public IntPtr hStdOutput;
303 public IntPtr hStdError;
304
305 public void Dispose()
306 {
307 // This makes assumptions based on how it's used above.
308 if (this.hStdError != IntPtr.Zero)
309 {
310 CloseHandle(this.hStdError);
311 this.hStdError = IntPtr.Zero;
312 }
313
314 if (this.hStdOutput != IntPtr.Zero)
315 {
316 CloseHandle(this.hStdOutput);
317 this.hStdOutput = IntPtr.Zero;
318 }
319 }
320 }
321
322 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
323 private struct PROCESS_INFORMATION
324 {
325 public IntPtr hProcess;
326 public IntPtr hThread;
327 public int dwProcessId;
328 public int dwThreadId;
329
330 public void Dispose()
331 {
332 if (this.hProcess != IntPtr.Zero)
333 {
334 CloseHandle(this.hProcess);
335 this.hProcess = IntPtr.Zero;
336 }
337
338 if (this.hThread != IntPtr.Zero)
339 {
340 CloseHandle(this.hThread);
341 this.hThread = IntPtr.Zero;
342 }
343 }
344 }
345
346 private enum StdHandleType
347 {
348 STD_INPUT_HANDLE = -10,
349 STD_OUTPUT_HANDLE = -11,
350 STD_ERROR_HANDLE = -12,
351 }
352
353 [Flags]
354 private enum CreateProcessFlags
355 {
356 None = 0x0,
357 CREATE_NO_WINDOW = 0x08000000,
358 }
359
360 [Flags]
361 private enum StartupInfoFlags
362 {
363 None = 0x0,
364 STARTF_FORCEOFFFEEDBACK = 0x80,
365 STARTF_USESTDHANDLES = 0x100,
366 }
367
368 private enum DuplicateHandleOptions
369 {
370 DUPLICATE_CLOSE_SOURCE = 1,
371 DUPLICATE_SAME_ACCESS = 2,
372 }
373 }
374}
diff --git a/src/internal/WixInternal.MSTestSupport/ExternalExecutableResult.cs b/src/internal/WixInternal.MSTestSupport/ExternalExecutableResult.cs
new file mode 100644
index 00000000..57bf0d11
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/ExternalExecutableResult.cs
@@ -0,0 +1,19 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System.Diagnostics;
6
7 public class ExternalExecutableResult
8 {
9 public int ExitCode { get; set; }
10
11 public string[] StandardError { get; set; }
12
13 public string[] StandardOutput { get; set; }
14
15 public string FileName { get; set; }
16
17 public string Arguments { get; set; }
18 }
19}
diff --git a/src/internal/WixInternal.MSTestSupport/FakeBuildEngine.cs b/src/internal/WixInternal.MSTestSupport/FakeBuildEngine.cs
new file mode 100644
index 00000000..951d1bc8
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/FakeBuildEngine.cs
@@ -0,0 +1,33 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System.Collections;
6 using System.Text;
7 using Microsoft.Build.Framework;
8
9 public class FakeBuildEngine : IBuildEngine
10 {
11 private readonly StringBuilder output = new StringBuilder();
12
13 public int ColumnNumberOfTaskNode => 0;
14
15 public bool ContinueOnError => false;
16
17 public int LineNumberOfTaskNode => 0;
18
19 public string ProjectFileOfTaskNode => "fake_wix.targets";
20
21 public string Output => this.output.ToString();
22
23 public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs) => throw new System.NotImplementedException();
24
25 public void LogCustomEvent(CustomBuildEventArgs e) => this.output.AppendLine(e.Message);
26
27 public void LogErrorEvent(BuildErrorEventArgs e) => this.output.AppendLine(e.Message);
28
29 public void LogMessageEvent(BuildMessageEventArgs e) => this.output.AppendLine(e.Message);
30
31 public void LogWarningEvent(BuildWarningEventArgs e) => this.output.AppendLine(e.Message);
32 }
33}
diff --git a/src/internal/WixInternal.MSTestSupport/MsbuildRunner.cs b/src/internal/WixInternal.MSTestSupport/MsbuildRunner.cs
new file mode 100644
index 00000000..69fc7292
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/MsbuildRunner.cs
@@ -0,0 +1,112 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8
9 public class MsbuildRunner : ExternalExecutable
10 {
11 private static readonly string VswhereFindArguments = "-property installationPath -version [17.0,18.0)";
12 private static readonly string MsbuildCurrentRelativePath = @"MSBuild\Current\Bin\MSBuild.exe";
13 private static readonly string MsbuildCurrentRelativePath64 = @"MSBuild\Current\Bin\amd64\MSBuild.exe";
14
15 private static readonly object InitLock = new object();
16
17 private static bool Initialized;
18 private static MsbuildRunner MsbuildCurrentRunner;
19 private static MsbuildRunner MsbuildCurrentRunner64;
20
21 public static MsbuildRunnerResult Execute(string projectPath, string[] arguments = null, bool x64 = false) =>
22 InitAndExecute(String.Empty, projectPath, arguments, x64);
23
24 public static MsbuildRunnerResult ExecuteWithMsbuildCurrent(string projectPath, string[] arguments = null, bool x64 = false) =>
25 InitAndExecute("Current", projectPath, arguments, x64);
26
27 private static MsbuildRunnerResult InitAndExecute(string msbuildVersion, string projectPath, string[] arguments, bool x64)
28 {
29 lock (InitLock)
30 {
31 if (!Initialized)
32 {
33 Initialized = true;
34 var vswhereResult = VswhereRunner.Execute(VswhereFindArguments, true);
35 if (vswhereResult.ExitCode != 0)
36 {
37 throw new InvalidOperationException($"Failed to execute vswhere.exe, exit code: {vswhereResult.ExitCode}. Output:\r\n{String.Join("\r\n", vswhereResult.StandardOutput)}");
38 }
39
40 string msbuildCurrentPath = null;
41 string msbuildCurrentPath64 = null;
42
43 foreach (var installPath in vswhereResult.StandardOutput)
44 {
45 if (msbuildCurrentPath == null)
46 {
47 var path = Path.Combine(installPath, MsbuildCurrentRelativePath);
48 if (File.Exists(path))
49 {
50 msbuildCurrentPath = path;
51 }
52 }
53
54 if (msbuildCurrentPath64 == null)
55 {
56 var path = Path.Combine(installPath, MsbuildCurrentRelativePath64);
57 if (File.Exists(path))
58 {
59 msbuildCurrentPath64 = path;
60 }
61 }
62 }
63
64 if (msbuildCurrentPath != null)
65 {
66 MsbuildCurrentRunner = new MsbuildRunner(msbuildCurrentPath);
67 }
68
69 if (msbuildCurrentPath64 != null)
70 {
71 MsbuildCurrentRunner64 = new MsbuildRunner(msbuildCurrentPath64);
72 }
73 }
74 }
75
76 MsbuildRunner runner = x64 ? MsbuildCurrentRunner64 : MsbuildCurrentRunner;
77
78 if (runner == null)
79 {
80 throw new InvalidOperationException($"Failed to find an installed{(x64 ? " 64-bit" : String.Empty)} MSBuild{msbuildVersion}");
81 }
82
83 return runner.ExecuteCore(projectPath, arguments);
84 }
85
86 private MsbuildRunner(string exePath) : base(exePath) { }
87
88 private MsbuildRunnerResult ExecuteCore(string projectPath, string[] arguments)
89 {
90 var total = new List<string>
91 {
92 projectPath,
93 };
94
95 if (arguments != null)
96 {
97 total.AddRange(arguments);
98 }
99
100 var args = CombineArguments(total);
101 var mergeErrorIntoOutput = true;
102 var workingFolder = Path.GetDirectoryName(projectPath);
103 var result = this.Run(args, mergeErrorIntoOutput, workingFolder);
104
105 return new MsbuildRunnerResult
106 {
107 ExitCode = result.ExitCode,
108 Output = result.StandardOutput,
109 };
110 }
111 }
112}
diff --git a/src/internal/WixInternal.MSTestSupport/MsbuildRunnerResult.cs b/src/internal/WixInternal.MSTestSupport/MsbuildRunnerResult.cs
new file mode 100644
index 00000000..02e25ebb
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/MsbuildRunnerResult.cs
@@ -0,0 +1,19 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using Microsoft.VisualStudio.TestTools.UnitTesting;
7
8 public class MsbuildRunnerResult
9 {
10 public int ExitCode { get; set; }
11
12 public string[] Output { get; set; }
13
14 public void AssertSuccess()
15 {
16 Assert.IsTrue(0 == this.ExitCode, $"MSBuild failed unexpectedly. Output:{Environment.NewLine}{String.Join(Environment.NewLine, this.Output)}");
17 }
18 }
19}
diff --git a/src/internal/WixInternal.MSTestSupport/MsbuildUtilities.cs b/src/internal/WixInternal.MSTestSupport/MsbuildUtilities.cs
new file mode 100644
index 00000000..4776e6f1
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/MsbuildUtilities.cs
@@ -0,0 +1,99 @@
1// Copyright(c) .NET Foundation and contributors.All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Linq;
9
10 public enum BuildSystem
11 {
12 DotNetCoreSdk,
13 MSBuild,
14 MSBuild64,
15 }
16
17 public static class MsbuildUtilities
18 {
19 public static MsbuildRunnerResult BuildProject(BuildSystem buildSystem, string projectPath, string[] arguments = null, string configuration = "Release", string verbosityLevel = "normal", bool suppressValidation = true)
20 {
21 var allArgs = new List<string>
22 {
23 $"-verbosity:{verbosityLevel}",
24 $"-p:Configuration={configuration}",
25 $"-p:SuppressValidation={suppressValidation}",
26 // Node reuse means that child msbuild processes can stay around after the build completes.
27 // Under that scenario, the root msbuild does not reliably close its streams which causes us to hang.
28 "-nr:false",
29 MsbuildUtilities.GetQuotedSwitch(buildSystem, "bl", Path.ChangeExtension(projectPath, ".binlog"))
30 };
31
32 if (arguments != null)
33 {
34 allArgs.AddRange(arguments);
35 }
36
37 switch (buildSystem)
38 {
39 case BuildSystem.DotNetCoreSdk:
40 {
41 allArgs.Add(projectPath);
42 var result = DotnetRunner.Execute("msbuild", allArgs.ToArray());
43 return new MsbuildRunnerResult
44 {
45 ExitCode = result.ExitCode,
46 Output = result.StandardOutput,
47 };
48 }
49 case BuildSystem.MSBuild:
50 case BuildSystem.MSBuild64:
51 {
52 return MsbuildRunner.Execute(projectPath, allArgs.ToArray(), buildSystem == BuildSystem.MSBuild64);
53 }
54 default:
55 {
56 throw new NotImplementedException();
57 }
58 }
59 }
60
61 public static string GetQuotedSwitch(BuildSystem _, string switchName, string switchValue)
62 {
63 // If the value ends with a backslash, escape it.
64 if (switchValue?.EndsWith("\\") == true)
65 {
66 switchValue += @"\";
67 }
68
69 return $"-{switchName}:\"{switchValue}\"";
70 }
71
72 public static string GetQuotedPropertySwitch(BuildSystem buildSystem, string propertyName, string propertyValue)
73 {
74 // If the value ends with a backslash, escape it.
75 if (propertyValue?.EndsWith("\\") == true)
76 {
77 propertyValue += @"\";
78 }
79
80 var quotedValue = "\"" + propertyValue + "\"";
81
82 // If the value contains a semicolon then escape-quote it (wrap with the characters: \") to wrap the value
83 // instead of just quoting the value, otherwise dotnet.exe will not pass the value to MSBuild correctly.
84 if (buildSystem == BuildSystem.DotNetCoreSdk && propertyValue?.IndexOf(';') > -1)
85 {
86 quotedValue = "\\\"" + propertyValue + "\\\"";
87 }
88
89 return $"-p:{propertyName}={quotedValue}";
90 }
91
92 public static IEnumerable<string> GetToolCommandLines(MsbuildRunnerResult result, string toolName, string operation, BuildSystem buildSystem)
93 {
94 var expectedToolExe = buildSystem == BuildSystem.DotNetCoreSdk ? $"{toolName}.dll\"" : $"{toolName}.exe";
95 var expectedToolCommand = $"{expectedToolExe} {operation}";
96 return result.Output.Where(line => line.Contains(expectedToolCommand));
97 }
98 }
99}
diff --git a/src/internal/WixInternal.MSTestSupport/Pushd.cs b/src/internal/WixInternal.MSTestSupport/Pushd.cs
new file mode 100644
index 00000000..7086ffd0
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/Pushd.cs
@@ -0,0 +1,46 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.IO;
7
8 public class Pushd : IDisposable
9 {
10 protected bool Disposed { get; private set; }
11
12 public Pushd(string path)
13 {
14 this.PreviousDirectory = Directory.GetCurrentDirectory();
15
16 Directory.SetCurrentDirectory(path);
17 }
18
19 public string PreviousDirectory { get; }
20
21 #region // IDisposable
22
23 public void Dispose()
24 {
25 this.Dispose(true);
26 GC.SuppressFinalize(this);
27 }
28
29 protected virtual void Dispose(bool disposing)
30 {
31 if (this.Disposed)
32 {
33 return;
34 }
35
36 if (disposing)
37 {
38 Directory.SetCurrentDirectory(this.PreviousDirectory);
39 }
40
41 this.Disposed = true;
42 }
43
44 #endregion
45 }
46}
diff --git a/src/internal/WixInternal.MSTestSupport/Query.cs b/src/internal/WixInternal.MSTestSupport/Query.cs
new file mode 100644
index 00000000..5a8868b3
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/Query.cs
@@ -0,0 +1,207 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Linq;
9 using System.Text;
10 using WixToolset.Dtf.Compression.Cab;
11 using WixToolset.Dtf.WindowsInstaller;
12
13 public class Query
14 {
15 public static string[] QueryDatabase(string path, string[] tables)
16 {
17 var results = new List<string>();
18 var resultsByTable = QueryDatabaseByTable(path, tables);
19 var sortedTables = tables.ToList();
20 sortedTables.Sort();
21 foreach (var tableName in sortedTables)
22 {
23 var rows = resultsByTable[tableName];
24 rows?.ForEach(r => results.Add($"{tableName}:{r}"));
25 }
26 return results.ToArray();
27 }
28
29 public static string[] QueryDatabase(Database db, string[] tables)
30 {
31 var results = new List<string>();
32 var resultsByTable = QueryDatabaseByTable(db, tables);
33 var sortedTables = tables.ToList();
34 sortedTables.Sort();
35 foreach (var tableName in sortedTables)
36 {
37 var rows = resultsByTable[tableName];
38 rows?.ForEach(r => results.Add($"{tableName}:{r}"));
39 }
40 return results.ToArray();
41 }
42
43 /// <summary>
44 /// Returns rows from requested tables formatted to facilitate testing.
45 /// If the table did not exist in the database, its list will be null.
46 /// </summary>
47 /// <param name="path"></param>
48 /// <param name="tables"></param>
49 /// <returns></returns>
50 public static Dictionary<string, List<string>> QueryDatabaseByTable(string path, string[] tables)
51 {
52 var results = new Dictionary<string, List<string>>();
53
54 if (tables?.Length > 0)
55 {
56 using (var db = new Database(path))
57 {
58 results = QueryDatabaseByTable(db, tables);
59 }
60 }
61
62 return results;
63 }
64
65 /// <summary>
66 /// Returns rows from requested tables formatted to facilitate testing.
67 /// If the table did not exist in the database, its list will be null.
68 /// </summary>
69 /// <param name="db"></param>
70 /// <param name="tables"></param>
71 /// <returns></returns>
72 public static Dictionary<string, List<string>> QueryDatabaseByTable(Database db, string[] tables)
73 {
74 var results = new Dictionary<string, List<string>>();
75
76 if (tables?.Length > 0)
77 {
78 var sb = new StringBuilder();
79
80 foreach (var table in tables)
81 {
82 if (table == "_SummaryInformation")
83 {
84 var entries = new List<string>();
85 results.Add(table, entries);
86
87 entries.Add($"Title\t{db.SummaryInfo.Title}");
88 entries.Add($"Subject\t{db.SummaryInfo.Subject}");
89 entries.Add($"Author\t{db.SummaryInfo.Author}");
90 entries.Add($"Keywords\t{db.SummaryInfo.Keywords}");
91 entries.Add($"Comments\t{db.SummaryInfo.Comments}");
92 entries.Add($"Template\t{db.SummaryInfo.Template}");
93 entries.Add($"CodePage\t{db.SummaryInfo.CodePage}");
94 entries.Add($"PageCount\t{db.SummaryInfo.PageCount}");
95 entries.Add($"WordCount\t{db.SummaryInfo.WordCount}");
96 entries.Add($"CharacterCount\t{db.SummaryInfo.CharacterCount}");
97 entries.Add($"Security\t{db.SummaryInfo.Security}");
98
99 continue;
100 }
101
102 if (!db.IsTablePersistent(table))
103 {
104 results.Add(table, null);
105 continue;
106 }
107
108 var rows = new List<string>();
109 results.Add(table, rows);
110
111 using (var view = db.OpenView("SELECT * FROM `{0}`", table))
112 {
113 view.Execute();
114
115 Record record;
116 while ((record = view.Fetch()) != null)
117 {
118 sb.Clear();
119
120 using (record)
121 {
122 for (var i = 0; i < record.FieldCount; ++i)
123 {
124 if (i > 0)
125 {
126 sb.Append("\t");
127 }
128
129 sb.Append(record[i + 1]?.ToString());
130 }
131 }
132
133 rows.Add(sb.ToString());
134 }
135 }
136
137 rows.Sort();
138 }
139 }
140
141 return results;
142 }
143
144 public static CabFileInfo[] GetCabinetFiles(string path)
145 {
146 var cab = new CabInfo(path);
147
148 var result = cab.GetFiles();
149
150 return result.Select(c => c).ToArray();
151 }
152
153 public static void ExtractStream(string path, string streamName, string outputPath)
154 {
155 Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
156
157 using (var db = new Database(path))
158 using (var view = db.OpenView("SELECT `Data` FROM `_Streams` WHERE `Name` = '{0}'", streamName))
159 {
160 view.Execute();
161
162 using (var record = view.Fetch())
163 {
164 record.GetStream(1, outputPath);
165 }
166 }
167 }
168
169 public static void ExtractSubStorage(string path, string subStorageName, string outputPath)
170 {
171 Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
172
173 using (var db = new Database(path))
174 using (var view = db.OpenView("SELECT `Name`, `Data` FROM `_Storages` WHERE `Name` = '{0}'", subStorageName))
175 {
176 view.Execute();
177
178 using (var record = view.Fetch())
179 {
180 var name = record.GetString(1);
181 record.GetStream(2, outputPath);
182 }
183 }
184 }
185
186 public static string[] GetSubStorageNames(string path)
187 {
188 var result = new List<string>();
189
190 using (var db = new Database(path))
191 using (var view = db.OpenView("SELECT `Name` FROM `_Storages`"))
192 {
193 view.Execute();
194
195 Record record;
196 while ((record = view.Fetch()) != null)
197 {
198 var name = record.GetString(1);
199 result.Add(name);
200 }
201 }
202
203 result.Sort();
204 return result.ToArray();
205 }
206 }
207}
diff --git a/src/internal/WixInternal.MSTestSupport/RobocopyRunner.cs b/src/internal/WixInternal.MSTestSupport/RobocopyRunner.cs
new file mode 100644
index 00000000..7ad8f6fe
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/RobocopyRunner.cs
@@ -0,0 +1,16 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 public class RobocopyRunner : ExternalExecutable
6 {
7 private static readonly RobocopyRunner Instance = new RobocopyRunner();
8
9 private RobocopyRunner() : base("robocopy") { }
10
11 public static ExternalExecutableResult Execute(string args)
12 {
13 return Instance.Run(args);
14 }
15 }
16}
diff --git a/src/internal/WixInternal.MSTestSupport/TestData.cs b/src/internal/WixInternal.MSTestSupport/TestData.cs
new file mode 100644
index 00000000..5f167a87
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/TestData.cs
@@ -0,0 +1,78 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.IO;
7 using System.Reflection;
8 using System.Runtime.CompilerServices;
9
10 public class TestData
11 {
12 public static void CreateFile(string path, long size, bool fill = false)
13 {
14 // Ensure the directory exists.
15 path = Path.GetFullPath(path);
16 Directory.CreateDirectory(Path.GetDirectoryName(path));
17
18 using (var file = File.OpenWrite(path))
19 {
20 if (fill)
21 {
22 var random = new Random();
23 var bytes = new byte[4096];
24 var generated = 0L;
25
26 // Put fill bytes in the file so it doesn't compress trivially.
27 while (generated < size)
28 {
29 var generate = (int)Math.Min(size - generated, bytes.Length);
30
31 random.NextBytes(bytes);
32
33 file.Write(bytes, 0, generate);
34
35 generated += generate;
36 }
37 }
38 else
39 {
40 file.SetLength(size);
41 }
42 }
43 }
44
45 public static string Get(params string[] paths)
46 {
47 var localPath = AppDomain.CurrentDomain.BaseDirectory;
48 return Path.Combine(localPath, Path.Combine(paths));
49 }
50
51 public static string GetUnitTestLogsFolder([CallerFilePath] string path = "", [CallerMemberName] string method = "")
52 {
53 var startingPath = AppDomain.CurrentDomain.BaseDirectory;
54 var buildPath = startingPath;
55
56 while (!String.IsNullOrEmpty(buildPath))
57 {
58 var folderName = Path.GetFileName(buildPath);
59 if (String.Equals("build", folderName, StringComparison.OrdinalIgnoreCase))
60 {
61 break;
62 }
63
64 buildPath = Path.GetDirectoryName(buildPath);
65 }
66
67 if (String.IsNullOrEmpty(buildPath))
68 {
69 throw new InvalidOperationException($"Could not find the 'build' folder in the test path: {startingPath}. Cannot get test logs folder without being able to find the build folder.");
70 }
71
72 var testLogsFolder = Path.Combine(buildPath, "logs", "UnitTests", $"{Path.GetFileNameWithoutExtension(path)}_{method}");
73 Directory.CreateDirectory(testLogsFolder);
74
75 return testLogsFolder;
76 }
77 }
78}
diff --git a/src/internal/WixInternal.MSTestSupport/TestDataFolderFileSystem.cs b/src/internal/WixInternal.MSTestSupport/TestDataFolderFileSystem.cs
new file mode 100644
index 00000000..1fea9665
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/TestDataFolderFileSystem.cs
@@ -0,0 +1,42 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6
7 /// <summary>
8 /// This class builds on top of DisposableFileSystem
9 /// to make it easy to write a test that needs a whole folder of test data copied to a temp location
10 /// that will automatically be cleaned up at the end of the test.
11 /// </summary>
12 public class TestDataFolderFileSystem : IDisposable
13 {
14 private DisposableFileSystem fileSystem;
15
16 public string BaseFolder { get; private set; }
17
18 public void Dispose()
19 {
20 this.fileSystem?.Dispose();
21 }
22
23 public void Initialize(string sourceDirectoryPath)
24 {
25 if (this.fileSystem != null)
26 {
27 throw new InvalidOperationException();
28 }
29 this.fileSystem = new DisposableFileSystem();
30
31 this.BaseFolder = this.fileSystem.GetFolder();
32
33 RobocopyFolder(sourceDirectoryPath, this.BaseFolder);
34 }
35
36 public static ExternalExecutableResult RobocopyFolder(string sourceFolderPath, string destinationFolderPath)
37 {
38 var args = $"\"{sourceFolderPath}\" \"{destinationFolderPath}\" /E /R:1 /W:1";
39 return RobocopyRunner.Execute(args);
40 }
41 }
42}
diff --git a/src/internal/WixInternal.MSTestSupport/VswhereRunner.cs b/src/internal/WixInternal.MSTestSupport/VswhereRunner.cs
new file mode 100644
index 00000000..f6ff2116
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/VswhereRunner.cs
@@ -0,0 +1,41 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.IO;
7
8 public class VswhereRunner : ExternalExecutable
9 {
10 private static readonly string VswhereRelativePath = @"Microsoft Visual Studio\Installer\vswhere.exe";
11
12 private static readonly object InitLock = new object();
13 private static bool Initialized;
14 private static VswhereRunner Instance;
15
16 public static ExternalExecutableResult Execute(string args, bool mergeErrorIntoOutput = false) =>
17 InitAndExecute(args, mergeErrorIntoOutput);
18
19 private static ExternalExecutableResult InitAndExecute(string args, bool mergeErrorIntoOutput)
20 {
21 lock (InitLock)
22 {
23 if (!Initialized)
24 {
25 Initialized = true;
26 var vswherePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), VswhereRelativePath);
27 if (!File.Exists(vswherePath))
28 {
29 throw new InvalidOperationException($"Failed to find vswhere at: {vswherePath}");
30 }
31
32 Instance = new VswhereRunner(vswherePath);
33 }
34 }
35
36 return Instance.Run(args, mergeErrorIntoOutput);
37 }
38
39 private VswhereRunner(string exePath) : base(exePath) { }
40 }
41}
diff --git a/src/internal/WixInternal.MSTestSupport/WixAssert.cs b/src/internal/WixInternal.MSTestSupport/WixAssert.cs
new file mode 100644
index 00000000..927ebee6
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/WixAssert.cs
@@ -0,0 +1,164 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using Microsoft.VisualStudio.TestTools.UnitTesting;
6 using System;
7 using System.Collections.Generic;
8 using System.Linq;
9 using System.Text;
10 using System.Xml.Linq;
11
12 public class WixAssert
13 {
14 public static void CompareLineByLine(string[] expectedLines, string[] actualLines)
15 {
16 var lineNumber = 0;
17
18 for (; lineNumber < expectedLines.Length && lineNumber < actualLines.Length; ++lineNumber)
19 {
20 StringEqual($"{lineNumber}: {expectedLines[lineNumber]}", $"{lineNumber}: {actualLines[lineNumber]}");
21 }
22
23 var additionalExpectedLines = expectedLines.Length > lineNumber ? String.Join(Environment.NewLine, expectedLines.Skip(lineNumber).Select((s, i) => $"{lineNumber + i}: {s}")) : $"Missing {actualLines.Length - lineNumber} lines";
24 var additionalActualLines = actualLines.Length > lineNumber ? String.Join(Environment.NewLine, actualLines.Skip(lineNumber).Select((s, i) => $"{lineNumber + i}: {s}")) : $"Missing {expectedLines.Length - lineNumber} lines";
25
26 Assert.AreEqual<object>(additionalExpectedLines, additionalActualLines, StringObjectEqualityComparer.InvariantCulture);
27 }
28
29 public static void CompareXml(XContainer xExpected, XContainer xActual)
30 {
31 var expecteds = ComparableElements(xExpected);
32 var actuals = ComparableElements(xActual);
33
34 CompareLineByLine(expecteds.OrderBy(s => s).ToArray(), actuals.OrderBy(s => s).ToArray());
35 }
36
37 public static void CompareXml(string expectedPath, string actualPath)
38 {
39 var expectedDoc = XDocument.Load(expectedPath, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
40 var actualDoc = XDocument.Load(actualPath, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
41
42 CompareXml(expectedDoc, actualDoc);
43 }
44
45 private static IEnumerable<string> ComparableElements(XContainer container)
46 {
47 return container.Descendants().Select(x => $"{x.Name.LocalName}:{String.Join(",", x.Attributes().OrderBy(a => a.Name.LocalName).Select(a => $"{a.Name.LocalName}={ComparableAttribute(a)}"))}");
48 }
49
50 private static string ComparableAttribute(XAttribute attribute)
51 {
52 switch (attribute.Name.LocalName)
53 {
54 case "SourceFile":
55 return "<SourceFile>";
56 default:
57 return attribute.Value;
58 }
59 }
60
61 public static void StringCollectionEmpty(IList<string> collection)
62 {
63 if (collection.Count > 0)
64 {
65 Assert.Fail($"The collection was expected to be empty, but instead was [{Environment.NewLine}\"{String.Join($"\", {Environment.NewLine}\"", collection)}\"{Environment.NewLine}]");
66 }
67 }
68
69 public static void StringEqual(string expected, string actual, bool ignoreCase = false)
70 {
71 WixStringEqualException.ThrowIfNotEqual(expected, actual, ignoreCase);
72 }
73
74 public static void NotStringEqual(string expected, string actual, bool ignoreCase = false)
75 {
76 var comparer = ignoreCase ? StringObjectEqualityComparer.InvariantCultureIgnoreCase : StringObjectEqualityComparer.InvariantCulture;
77 Assert.AreNotEqual(expected, actual, comparer);
78 }
79
80 public static void Single<T>(IEnumerable<T> collection)
81 {
82 Assert.AreEqual(1, collection.Count());
83 }
84
85 public static void Single<T>(IEnumerable<T> collection, Func<T, bool> predicate)
86 {
87 var results = collection.Where(predicate);
88 Assert.AreEqual(1, results.Count());
89 }
90
91 public static void Empty<T>(IEnumerable<T> collection)
92 {
93 Assert.AreEqual(0, collection.Count());
94 }
95
96 public static void Empty<T>(IEnumerable<T> collection, Func<T, bool> predicate)
97 {
98 var results = collection.Where(predicate);
99 Assert.AreEqual(0, results.Count());
100 }
101 }
102
103 internal class StringObjectEqualityComparer : IEqualityComparer<object>
104 {
105 public static readonly StringObjectEqualityComparer InvariantCultureIgnoreCase = new StringObjectEqualityComparer(true);
106 public static readonly StringObjectEqualityComparer InvariantCulture = new StringObjectEqualityComparer(false);
107
108 private readonly StringComparer stringComparer;
109
110 public StringObjectEqualityComparer(bool ignoreCase)
111 {
112 this.stringComparer = ignoreCase ? StringComparer.InvariantCultureIgnoreCase : StringComparer.InvariantCulture;
113 }
114
115 public new bool Equals(object x, object y)
116 {
117 return this.stringComparer.Equals((string)x, (string)y);
118 }
119
120 public int GetHashCode(object obj)
121 {
122 return this.stringComparer.GetHashCode((string)obj);
123 }
124 }
125
126 public class WixStringEqualException : AssertFailedException
127 {
128 public WixStringEqualException(string userMessage) : base(userMessage) { }
129
130 public static void ThrowIfNotEqual(string expected, string actual, bool ignoreCase)
131 {
132 var comparer = ignoreCase ? StringObjectEqualityComparer.InvariantCultureIgnoreCase : StringObjectEqualityComparer.InvariantCulture;
133 if (comparer.Equals(expected, actual))
134 {
135 return;
136 }
137
138 var sbMessage = new StringBuilder();
139
140 try
141 {
142 Assert.AreEqual(expected, actual, ignoreCase);
143 }
144 catch (AssertFailedException xe)
145 {
146 // If either string is not completely in the message, then make sure it gets in there.
147 if (!xe.Message.Contains(expected) || !xe.Message.Contains(actual))
148 {
149 sbMessage.AppendLine(xe.Message);
150 sbMessage.AppendLine();
151 sbMessage.AppendFormat("Expected: {0}", expected);
152 sbMessage.AppendLine();
153 sbMessage.AppendFormat("Actual: {0}", actual);
154 }
155 else
156 {
157 throw;
158 }
159 }
160
161 throw new WixStringEqualException(sbMessage.ToString());
162 }
163 }
164}
diff --git a/src/internal/WixInternal.MSTestSupport/WixInternal.MSTestSupport.csproj b/src/internal/WixInternal.MSTestSupport/WixInternal.MSTestSupport.csproj
new file mode 100644
index 00000000..b48aacd4
--- /dev/null
+++ b/src/internal/WixInternal.MSTestSupport/WixInternal.MSTestSupport.csproj
@@ -0,0 +1,27 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5
6 <PropertyGroup>
7 <TargetFrameworks>net6.0;net472</TargetFrameworks>
8 <IsPackable>true</IsPackable>
9 <DebugType>embedded</DebugType>
10 <PublishRepositoryUrl>true</PublishRepositoryUrl>
11 <CreateDocumentationFile>true</CreateDocumentationFile>
12 <NoWarn>$(NoWarn);CS1591</NoWarn>
13 <SignOutput>false</SignOutput>
14 <IsWixTestSupportProject>true</IsWixTestSupportProject>
15 </PropertyGroup>
16
17 <ItemGroup>
18 <PackageReference Include="Microsoft.Build.Tasks.Core" />
19 <PackageReference Include="WixToolset.Dtf.WindowsInstaller" />
20 <PackageReference Include="WixToolset.Dtf.Compression" />
21 <PackageReference Include="WixToolset.Dtf.Compression.Cab" />
22 </ItemGroup>
23
24 <ItemGroup>
25 <PackageReference Include="MSTest.TestFramework" />
26 </ItemGroup>
27</Project>
diff --git a/src/internal/WixInternal.TestSupport/WixAssert.cs b/src/internal/WixInternal.TestSupport/WixAssert.cs
new file mode 100644
index 00000000..40355131
--- /dev/null
+++ b/src/internal/WixInternal.TestSupport/WixAssert.cs
@@ -0,0 +1,143 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.MSTestSupport
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 using System.Text;
9 using System.Xml.Linq;
10 using Xunit;
11 using Xunit.Sdk;
12
13 public class WixAssert
14 {
15 public static void CompareLineByLine(string[] expectedLines, string[] actualLines)
16 {
17 var lineNumber = 0;
18
19 for (; lineNumber < expectedLines.Length && lineNumber < actualLines.Length; ++lineNumber)
20 {
21 StringEqual($"{lineNumber}: {expectedLines[lineNumber]}", $"{lineNumber}: {actualLines[lineNumber]}");
22 }
23
24 var additionalExpectedLines = expectedLines.Length > lineNumber ? String.Join(Environment.NewLine, expectedLines.Skip(lineNumber).Select((s, i) => $"{lineNumber + i}: {s}")) : $"Missing {actualLines.Length - lineNumber} lines";
25 var additionalActualLines = actualLines.Length > lineNumber ? String.Join(Environment.NewLine, actualLines.Skip(lineNumber).Select((s, i) => $"{lineNumber + i}: {s}")) : $"Missing {expectedLines.Length - lineNumber} lines";
26
27 Assert.Equal<object>(additionalExpectedLines, additionalActualLines, StringObjectEqualityComparer.InvariantCulture);
28 }
29
30 public static void CompareXml(XContainer xExpected, XContainer xActual)
31 {
32 var expecteds = ComparableElements(xExpected);
33 var actuals = ComparableElements(xActual);
34
35 CompareLineByLine(expecteds.OrderBy(s => s).ToArray(), actuals.OrderBy(s => s).ToArray());
36 }
37
38 public static void CompareXml(string expectedPath, string actualPath)
39 {
40 var expectedDoc = XDocument.Load(expectedPath, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
41 var actualDoc = XDocument.Load(actualPath, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
42
43 CompareXml(expectedDoc, actualDoc);
44 }
45
46 private static IEnumerable<string> ComparableElements(XContainer container)
47 {
48 return container.Descendants().Select(x => $"{x.Name.LocalName}:{String.Join(",", x.Attributes().OrderBy(a => a.Name.LocalName).Select(a => $"{a.Name.LocalName}={ComparableAttribute(a)}"))}");
49 }
50
51 private static string ComparableAttribute(XAttribute attribute)
52 {
53 switch (attribute.Name.LocalName)
54 {
55 case "SourceFile":
56 return "<SourceFile>";
57 default:
58 return attribute.Value;
59 }
60 }
61
62 public static void StringCollectionEmpty(IList<string> collection)
63 {
64 if (collection.Count > 0)
65 {
66 Assert.Fail($"The collection was expected to be empty, but instead was [{Environment.NewLine}\"{String.Join($"\", {Environment.NewLine}\"", collection)}\"{Environment.NewLine}]");
67 }
68 }
69
70 public static void StringEqual(string expected, string actual, bool ignoreCase = false)
71 {
72 WixStringEqualException.ThrowIfNotEqual(expected, actual, ignoreCase);
73 }
74
75 public static void NotStringEqual(string expected, string actual, bool ignoreCase = false)
76 {
77 var comparer = ignoreCase ? StringObjectEqualityComparer.InvariantCultureIgnoreCase : StringObjectEqualityComparer.InvariantCulture;
78 Assert.NotEqual(expected, actual, comparer);
79 }
80 }
81
82 internal class StringObjectEqualityComparer : IEqualityComparer<object>
83 {
84 public static readonly StringObjectEqualityComparer InvariantCultureIgnoreCase = new StringObjectEqualityComparer(true);
85 public static readonly StringObjectEqualityComparer InvariantCulture = new StringObjectEqualityComparer(false);
86
87 private readonly StringComparer stringComparer;
88
89 public StringObjectEqualityComparer(bool ignoreCase)
90 {
91 this.stringComparer = ignoreCase ? StringComparer.InvariantCultureIgnoreCase : StringComparer.InvariantCulture;
92 }
93
94 public new bool Equals(object x, object y)
95 {
96 return this.stringComparer.Equals((string)x, (string)y);
97 }
98
99 public int GetHashCode(object obj)
100 {
101 return this.stringComparer.GetHashCode((string)obj);
102 }
103 }
104
105 public class WixStringEqualException : XunitException
106 {
107 public WixStringEqualException(string userMessage) : base(userMessage) { }
108
109 public static void ThrowIfNotEqual(string expected, string actual, bool ignoreCase)
110 {
111 var comparer = ignoreCase ? StringObjectEqualityComparer.InvariantCultureIgnoreCase : StringObjectEqualityComparer.InvariantCulture;
112 if (comparer.Equals(expected, actual))
113 {
114 return;
115 }
116
117 var sbMessage = new StringBuilder();
118
119 try
120 {
121 Assert.Equal(expected, actual, ignoreCase);
122 }
123 catch (XunitException xe)
124 {
125 // If either string is not completely in the message, then make sure it gets in there.
126 if (!xe.Message.Contains(expected) || !xe.Message.Contains(actual))
127 {
128 sbMessage.AppendLine(xe.Message);
129 sbMessage.AppendLine();
130 sbMessage.AppendFormat("Expected: {0}", expected);
131 sbMessage.AppendLine();
132 sbMessage.AppendFormat("Actual: {0}", actual);
133 }
134 else
135 {
136 throw;
137 }
138 }
139
140 throw new WixStringEqualException(sbMessage.ToString());
141 }
142 }
143}
diff --git a/src/internal/WixInternal.TestSupport/XunitExtensions/WixAssert.cs b/src/internal/WixInternal.TestSupport/XunitExtensions/WixAssert.cs
index 5ac28de1..131d4e83 100644
--- a/src/internal/WixInternal.TestSupport/XunitExtensions/WixAssert.cs
+++ b/src/internal/WixInternal.TestSupport/XunitExtensions/WixAssert.cs
@@ -105,6 +105,32 @@ namespace WixInternal.TestSupport
105 Assert.NotEqual<object>(expected, actual, comparer); 105 Assert.NotEqual<object>(expected, actual, comparer);
106 } 106 }
107 107
108 public static void Single(IEnumerable<string> collection)
109 {
110 Assert.Single(collection);
111 // TODO: MSTEST: Assert.Equal(1, collection.Count());
112 }
113
114 public static void Single(IEnumerable<string> collection, Func<string, bool> predicate)
115 {
116 var results = collection.Where(predicate);
117 Assert.Single(results);
118 // TODO: MSTEST: Assert.Equal(1, results.Count());
119 }
120
121 public static void Empty(IEnumerable<string> collection)
122 {
123 Assert.Empty(collection);
124 // TODO: MSTEST: Assert.Equal(0, collection.Count());
125 }
126
127 public static void Empty(IEnumerable<string> collection, Func<string, bool> predicate)
128 {
129 var results = collection.Where(predicate);
130 Assert.Empty(results);
131 // TODO: MSTEST: Assert.Equal(0, results.Count());
132 }
133
108 // There appears to have been a bug in VC++, which might or might not have been partially 134 // There appears to have been a bug in VC++, which might or might not have been partially
109 // or completely corrected. It was unable to disambiguate a call to: 135 // or completely corrected. It was unable to disambiguate a call to:
110 // Xunit::Assert::Throws(System::Type^, System::Action^) 136 // Xunit::Assert::Throws(System::Type^, System::Action^)
diff --git a/src/internal/internal.sln b/src/internal/internal.sln
index e8d8db17..5514e543 100644
--- a/src/internal/internal.sln
+++ b/src/internal/internal.sln
@@ -9,6 +9,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WixInternal.TestSupport.Nat
9EndProject 9EndProject
10Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixInternal.BaseBuildTasks.Sources", "WixInternal.BaseBuildTasks.Sources\WixInternal.BaseBuildTasks.Sources.csproj", "{6B654490-AB0D-4F94-B564-DAA80044D5A3}" 10Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixInternal.BaseBuildTasks.Sources", "WixInternal.BaseBuildTasks.Sources\WixInternal.BaseBuildTasks.Sources.csproj", "{6B654490-AB0D-4F94-B564-DAA80044D5A3}"
11EndProject 11EndProject
12Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixInternal.XunitTestSupport", "WixInternal.XunitTestSupport\WixInternal.XunitTestSupport.csproj", "{AF7C4730-583B-46F8-9BB6-16D1F0330932}"
13EndProject
14Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixInternal.MSTestSupport", "WixInternal.MSTestSupport\WixInternal.MSTestSupport.csproj", "{E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}"
15EndProject
12Global 16Global
13 GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 Debug|Any CPU = Debug|Any CPU 18 Debug|Any CPU = Debug|Any CPU
@@ -65,6 +69,38 @@ Global
65 {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x64.Build.0 = Release|Any CPU 69 {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x64.Build.0 = Release|Any CPU
66 {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x86.ActiveCfg = Release|Any CPU 70 {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x86.ActiveCfg = Release|Any CPU
67 {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x86.Build.0 = Release|Any CPU 71 {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x86.Build.0 = Release|Any CPU
72 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
73 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Debug|Any CPU.Build.0 = Debug|Any CPU
74 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Debug|ARM64.ActiveCfg = Debug|Any CPU
75 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Debug|ARM64.Build.0 = Debug|Any CPU
76 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Debug|x64.ActiveCfg = Debug|Any CPU
77 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Debug|x64.Build.0 = Debug|Any CPU
78 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Debug|x86.ActiveCfg = Debug|Any CPU
79 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Debug|x86.Build.0 = Debug|Any CPU
80 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Release|Any CPU.ActiveCfg = Release|Any CPU
81 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Release|Any CPU.Build.0 = Release|Any CPU
82 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Release|ARM64.ActiveCfg = Release|Any CPU
83 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Release|ARM64.Build.0 = Release|Any CPU
84 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Release|x64.ActiveCfg = Release|Any CPU
85 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Release|x64.Build.0 = Release|Any CPU
86 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Release|x86.ActiveCfg = Release|Any CPU
87 {AF7C4730-583B-46F8-9BB6-16D1F0330932}.Release|x86.Build.0 = Release|Any CPU
88 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
89 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
90 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Debug|ARM64.ActiveCfg = Debug|Any CPU
91 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Debug|ARM64.Build.0 = Debug|Any CPU
92 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Debug|x64.ActiveCfg = Debug|Any CPU
93 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Debug|x64.Build.0 = Debug|Any CPU
94 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Debug|x86.ActiveCfg = Debug|Any CPU
95 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Debug|x86.Build.0 = Debug|Any CPU
96 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
97 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Release|Any CPU.Build.0 = Release|Any CPU
98 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Release|ARM64.ActiveCfg = Release|Any CPU
99 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Release|ARM64.Build.0 = Release|Any CPU
100 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Release|x64.ActiveCfg = Release|Any CPU
101 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Release|x64.Build.0 = Release|Any CPU
102 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Release|x86.ActiveCfg = Release|Any CPU
103 {E70898F2-8D08-4FCE-9CFF-EF1792FCA2E2}.Release|x86.Build.0 = Release|Any CPU
68 EndGlobalSection 104 EndGlobalSection
69 GlobalSection(SolutionProperties) = preSolution 105 GlobalSection(SolutionProperties) = preSolution
70 HideSolutionNode = FALSE 106 HideSolutionNode = FALSE
diff --git a/src/internal/internal_t.proj b/src/internal/internal_t.proj
index 7dd52354..ab96b6c8 100644
--- a/src/internal/internal_t.proj
+++ b/src/internal/internal_t.proj
@@ -2,6 +2,7 @@
2 <ItemGroup> 2 <ItemGroup>
3 <ProjectReference Include="WixInternal.BaseBuildTasks.Sources\WixInternal.BaseBuildTasks.Sources.csproj" Targets="Pack" /> 3 <ProjectReference Include="WixInternal.BaseBuildTasks.Sources\WixInternal.BaseBuildTasks.Sources.csproj" Targets="Pack" />
4 <ProjectReference Include="WixInternal.TestSupport\WixInternal.TestSupport.csproj" Targets="Pack" /> 4 <ProjectReference Include="WixInternal.TestSupport\WixInternal.TestSupport.csproj" Targets="Pack" />
5 <ProjectReference Include="WixInternal.MSTestSupport\WixInternal.MSTestSupport.csproj" Targets="Pack" />
5 <ProjectReference Include="WixInternal.TestSupport.Native\WixInternal.TestSupport.Native.vcxproj" Properties="Platform=x86" /> 6 <ProjectReference Include="WixInternal.TestSupport.Native\WixInternal.TestSupport.Native.vcxproj" Properties="Platform=x86" />
6 <ProjectReference Include="WixInternal.TestSupport.Native\WixInternal.TestSupport.Native.vcxproj" Properties="Platform=x64" /> 7 <ProjectReference Include="WixInternal.TestSupport.Native\WixInternal.TestSupport.Native.vcxproj" Properties="Platform=x64" />
7 </ItemGroup> 8 </ItemGroup>
diff --git a/src/wix.runsettings b/src/wix.runsettings
new file mode 100644
index 00000000..97e4acda
--- /dev/null
+++ b/src/wix.runsettings
@@ -0,0 +1,7 @@
1<RunSettings>
2 <MSTest>
3 <Parallelize>
4 <Scope>MethodLevel</Scope>
5 </Parallelize>
6 </MSTest>
7</RunSettings>
diff --git a/src/wix/WixInternal.Core.MSTestPackage/BundleExtractor.cs b/src/wix/WixInternal.Core.MSTestPackage/BundleExtractor.cs
new file mode 100644
index 00000000..c491ad56
--- /dev/null
+++ b/src/wix/WixInternal.Core.MSTestPackage/BundleExtractor.cs
@@ -0,0 +1,156 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.Core.MSTestPackage
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Xml;
9 using WixToolset.Data.Burn;
10 using WixToolset.Extensibility.Services;
11
12 /// <summary>
13 /// Class to extract bundle contents for testing.
14 /// </summary>
15 public class BundleExtractor
16 {
17 private const string BurnNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn";
18 private const string BADataFileName = "BootstrapperApplicationData.xml";
19 private const string BootstrapperExtensionDataFileName = "BootstrapperExtensionData.xml";
20
21 /// <summary>
22 /// Extracts the BA container.
23 /// </summary>
24 /// <param name="messaging"></param>
25 /// <param name="bundleFilePath">Path to the bundle.</param>
26 /// <param name="destinationFolderPath">Path to extract to.</param>
27 /// <param name="tempFolderPath">Temp path for extraction.</param>
28 /// <returns></returns>
29 public static ExtractBAContainerResult ExtractBAContainer(IMessaging messaging, string bundleFilePath, string destinationFolderPath, string tempFolderPath)
30 {
31 return ExtractAllContainers(messaging, bundleFilePath, destinationFolderPath, null, tempFolderPath);
32 }
33
34 /// <summary>
35 /// Extracts the BA container.
36 /// </summary>
37 /// <param name="messaging"></param>
38 /// <param name="bundleFilePath">Path to the bundle.</param>
39 /// <param name="baFolderPath">Path to extract BA to.</param>
40 /// <param name="otherContainersFolderPath">Optional path to extract other attached containers to.</param>
41 /// <param name="tempFolderPath">Temp path for extraction.</param>
42 /// <returns></returns>
43 public static ExtractBAContainerResult ExtractAllContainers(IMessaging messaging, string bundleFilePath, string baFolderPath, string otherContainersFolderPath, string tempFolderPath)
44 {
45 Directory.CreateDirectory(tempFolderPath);
46
47 var args = new List<string>
48 {
49 "burn", "extract",
50 "-intermediatefolder", tempFolderPath,
51 bundleFilePath,
52 "-oba", baFolderPath
53 };
54
55 if (!String.IsNullOrEmpty(otherContainersFolderPath))
56 {
57 args.Add("-o");
58 args.Add(otherContainersFolderPath);
59 }
60
61 var runnerResult = WixRunner.Execute(args.ToArray());
62
63 var result = new ExtractBAContainerResult();
64
65 if (runnerResult.ExitCode == 0)
66 {
67 result.Success = true;
68 result.ManifestDocument = LoadBurnManifest(baFolderPath);
69 result.ManifestNamespaceManager = GetBurnNamespaceManager(result.ManifestDocument, "burn");
70
71 result.BADataDocument = LoadBAData(baFolderPath);
72 result.BADataNamespaceManager = GetBADataNamespaceManager(result.BADataDocument, "ba");
73
74 result.BootstrapperExtensionDataDocument = LoadBootstrapperExtensionData(baFolderPath);
75 result.BootstrapperExtensionDataNamespaceManager = GetBootstrapperExtensionDataNamespaceManager(result.BootstrapperExtensionDataDocument, "be");
76 }
77
78 return result;
79 }
80
81 /// <summary>
82 /// Gets an <see cref="XmlNamespaceManager"/> for BootstrapperApplicationData.xml with the given prefix assigned to the root namespace.
83 /// </summary>
84 /// <param name="document"></param>
85 /// <param name="prefix"></param>
86 /// <returns></returns>
87 public static XmlNamespaceManager GetBADataNamespaceManager(XmlDocument document, string prefix)
88 {
89 var namespaceManager = new XmlNamespaceManager(document.NameTable);
90 namespaceManager.AddNamespace(prefix, BurnConstants.BootstrapperApplicationDataNamespace);
91 return namespaceManager;
92 }
93
94 /// <summary>
95 /// Gets an <see cref="XmlNamespaceManager"/> for BootstrapperExtensionData.xml with the given prefix assigned to the root namespace.
96 /// </summary>
97 /// <param name="document"></param>
98 /// <param name="prefix"></param>
99 /// <returns></returns>
100 public static XmlNamespaceManager GetBootstrapperExtensionDataNamespaceManager(XmlDocument document, string prefix)
101 {
102 var namespaceManager = new XmlNamespaceManager(document.NameTable);
103 namespaceManager.AddNamespace(prefix, BurnConstants.BootstrapperExtensionDataNamespace);
104 return namespaceManager;
105 }
106
107 /// <summary>
108 /// Gets an <see cref="XmlNamespaceManager"/> for the Burn manifest.xml with the given prefix assigned to the root namespace.
109 /// </summary>
110 /// <param name="document"></param>
111 /// <param name="prefix"></param>
112 /// <returns></returns>
113 public static XmlNamespaceManager GetBurnNamespaceManager(XmlDocument document, string prefix)
114 {
115 var namespaceManager = new XmlNamespaceManager(document.NameTable);
116 namespaceManager.AddNamespace(prefix, BurnNamespace);
117 return namespaceManager;
118 }
119
120 /// <summary>
121 /// Loads an XmlDocument with the BootstrapperApplicationData.xml from the given folder that contains the contents of the BA container.
122 /// </summary>
123 /// <param name="baFolderPath"></param>
124 /// <returns></returns>
125 public static XmlDocument LoadBAData(string baFolderPath)
126 {
127 var document = new XmlDocument();
128 document.Load(Path.Combine(baFolderPath, BADataFileName));
129 return document;
130 }
131
132 /// <summary>
133 /// Loads an XmlDocument with the BootstrapperApplicationData.xml from the given folder that contains the contents of the BA container.
134 /// </summary>
135 /// <param name="baFolderPath"></param>
136 /// <returns></returns>
137 public static XmlDocument LoadBootstrapperExtensionData(string baFolderPath)
138 {
139 var document = new XmlDocument();
140 document.Load(Path.Combine(baFolderPath, BootstrapperExtensionDataFileName));
141 return document;
142 }
143
144 /// <summary>
145 /// Loads an XmlDocument with the BootstrapperApplicationData.xml from the given folder that contains the contents of the BA container.
146 /// </summary>
147 /// <param name="baFolderPath"></param>
148 /// <returns></returns>
149 public static XmlDocument LoadBurnManifest(string baFolderPath)
150 {
151 var document = new XmlDocument();
152 document.Load(Path.Combine(baFolderPath, "manifest.xml"));
153 return document;
154 }
155 }
156}
diff --git a/src/wix/WixInternal.Core.MSTestPackage/ExtractBAContainerResult.cs b/src/wix/WixInternal.Core.MSTestPackage/ExtractBAContainerResult.cs
new file mode 100644
index 00000000..47759188
--- /dev/null
+++ b/src/wix/WixInternal.Core.MSTestPackage/ExtractBAContainerResult.cs
@@ -0,0 +1,156 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.Core.MSTestPackage
4{
5 using System.Collections.Generic;
6 using System.IO;
7 using System.Xml;
8 using Microsoft.VisualStudio.TestTools.UnitTesting;
9
10 /// <summary>
11 /// The result of extracting the BA container.
12 /// </summary>
13 public class ExtractBAContainerResult
14 {
15 /// <summary>
16 /// <see cref="XmlDocument"/> for BootstrapperExtensionData.xml.
17 /// </summary>
18 public XmlDocument BootstrapperExtensionDataDocument { get; set; }
19
20 /// <summary>
21 /// <see cref="XmlNamespaceManager"/> for BootstrapperExtensionData.xml.
22 /// </summary>
23 public XmlNamespaceManager BootstrapperExtensionDataNamespaceManager { get; set; }
24
25 /// <summary>
26 /// <see cref="XmlDocument"/> for BootstrapperApplicationData.xml.
27 /// </summary>
28 public XmlDocument BADataDocument { get; set; }
29
30 /// <summary>
31 /// <see cref="XmlNamespaceManager"/> for BootstrapperApplicationData.xml.
32 /// </summary>
33 public XmlNamespaceManager BADataNamespaceManager { get; set; }
34
35 /// <summary>
36 /// <see cref="XmlDocument"/> for the Burn manifest.xml.
37 /// </summary>
38 public XmlDocument ManifestDocument { get; set; }
39
40 /// <summary>
41 /// <see cref="XmlNamespaceManager"/> for the Burn manifest.xml.
42 /// </summary>
43 public XmlNamespaceManager ManifestNamespaceManager { get; set; }
44
45 /// <summary>
46 /// Whether extraction succeeded.
47 /// </summary>
48 public bool Success { get; set; }
49
50 /// <summary>
51 /// Whether attached containers extraction succeeded.
52 /// </summary>
53 public bool? AttachedContainersSuccess { get; set; }
54
55 /// <summary>
56 ///
57 /// </summary>
58 /// <returns></returns>
59 public ExtractBAContainerResult AssertSuccess()
60 {
61 Assert.IsTrue(this.Success);
62 Assert.IsTrue(!this.AttachedContainersSuccess.HasValue || this.AttachedContainersSuccess.Value);
63 return this;
64 }
65
66 /// <summary>
67 /// Returns the relative path of the BA entry point dll in the given folder.
68 /// </summary>
69 /// <param name="extractedBAContainerFolderPath"></param>
70 /// <returns></returns>
71 public string GetBAFilePath(string extractedBAContainerFolderPath)
72 {
73 var uxPayloads = this.SelectManifestNodes("/burn:BurnManifest/burn:UX/burn:Payload");
74 var baPayload = uxPayloads[0];
75 var relativeBAPath = baPayload.Attributes["FilePath"].Value;
76 return Path.Combine(extractedBAContainerFolderPath, relativeBAPath);
77 }
78
79 /// <summary>
80 /// Returns the relative path of the BootstrapperExtension entry point dll in the given folder.
81 /// </summary>
82 /// <param name="extractedBAContainerFolderPath"></param>
83 /// <param name="extensionId"></param>
84 /// <returns></returns>
85 public string GetBootstrapperExtensionFilePath(string extractedBAContainerFolderPath, string extensionId)
86 {
87 var uxPayloads = this.SelectManifestNodes($"/burn:BurnManifest/burn:UX/burn:Payload[@Id='{extensionId}']");
88 var bextPayload = uxPayloads[0];
89 var relativeBextPath = bextPayload.Attributes["FilePath"].Value;
90 return Path.Combine(extractedBAContainerFolderPath, relativeBextPath);
91 }
92
93 /// <summary>
94 ///
95 /// </summary>
96 /// <param name="xpath">elements must have the 'ba' prefix</param>
97 /// <returns></returns>
98 public XmlNodeList SelectBADataNodes(string xpath)
99 {
100 return this.BADataDocument.SelectNodes(xpath, this.BADataNamespaceManager);
101 }
102
103 /// <summary>
104 ///
105 /// </summary>
106 /// <param name="xpath">elements must have the 'ba' prefix</param>
107 /// <param name="ignoredAttributesByElementName">Attributes for which the value should be set to '*'.</param>
108 /// <returns></returns>
109 public string[] GetBADataTestXmlLines(string xpath, Dictionary<string, List<string>> ignoredAttributesByElementName = null)
110 {
111 return this.SelectBADataNodes(xpath).GetTestXmlLines(ignoredAttributesByElementName);
112 }
113
114 /// <summary>
115 ///
116 /// </summary>
117 /// <param name="xpath">elements must have the 'be' prefix</param>
118 /// <returns></returns>
119 public XmlNodeList SelectBootstrapperExtensionDataNodes(string xpath)
120 {
121 return this.BootstrapperExtensionDataDocument.SelectNodes(xpath, this.BootstrapperExtensionDataNamespaceManager);
122 }
123
124 /// <summary>
125 ///
126 /// </summary>
127 /// <param name="xpath">elements must have the 'be' prefix</param>
128 /// <param name="ignoredAttributesByElementName">Attributes for which the value should be set to '*'.</param>
129 /// <returns></returns>
130 public string[] GetBootstrapperExtensionTestXmlLines(string xpath, Dictionary<string, List<string>> ignoredAttributesByElementName = null)
131 {
132 return this.SelectBootstrapperExtensionDataNodes(xpath).GetTestXmlLines(ignoredAttributesByElementName);
133 }
134
135 /// <summary>
136 ///
137 /// </summary>
138 /// <param name="xpath">elements must have the 'burn' prefix</param>
139 /// <returns></returns>
140 public XmlNodeList SelectManifestNodes(string xpath)
141 {
142 return this.ManifestDocument.SelectNodes(xpath, this.ManifestNamespaceManager);
143 }
144
145 /// <summary>
146 ///
147 /// </summary>
148 /// <param name="xpath">elements must have the 'burn' prefix</param>
149 /// <param name="ignoredAttributesByElementName">Attributes for which the value should be set to '*'.</param>
150 /// <returns></returns>
151 public string[] GetManifestTestXmlLines(string xpath, Dictionary<string, List<string>> ignoredAttributesByElementName = null)
152 {
153 return this.SelectManifestNodes(xpath).GetTestXmlLines(ignoredAttributesByElementName);
154 }
155 }
156}
diff --git a/src/wix/WixInternal.Core.MSTestPackage/TestMessageListener.cs b/src/wix/WixInternal.Core.MSTestPackage/TestMessageListener.cs
new file mode 100644
index 00000000..d8bde43f
--- /dev/null
+++ b/src/wix/WixInternal.Core.MSTestPackage/TestMessageListener.cs
@@ -0,0 +1,57 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.Core.MSTestPackage
4{
5 using System.Collections.Generic;
6 using WixToolset.Data;
7 using WixToolset.Extensibility;
8 using WixToolset.Extensibility.Services;
9
10 /// <summary>
11 /// An <see cref="IMessageListener"/> that simply stores all the messages.
12 /// </summary>
13 public sealed class TestMessageListener : IMessageListener
14 {
15 /// <summary>
16 /// All messages that have been received.
17 /// </summary>
18 public List<Message> Messages { get; } = new List<Message>();
19
20 /// <summary>
21 ///
22 /// </summary>
23 public string ShortAppName => "TEST";
24
25 /// <summary>
26 ///
27 /// </summary>
28 public string LongAppName => "Test";
29
30 /// <summary>
31 /// Stores the message in <see cref="Messages"/>.
32 /// </summary>
33 /// <param name="message"></param>
34 public void Write(Message message)
35 {
36 this.Messages.Add(message);
37 }
38
39 /// <summary>
40 /// Stores the message in <see cref="Messages"/>.
41 /// </summary>
42 /// <param name="message"></param>
43 public void Write(string message)
44 {
45 this.Messages.Add(new Message(null, MessageLevel.Information, 0, message));
46 }
47
48 /// <summary>
49 /// Always returns defaultMessageLevel.
50 /// </summary>
51 /// <param name="messaging"></param>
52 /// <param name="message"></param>
53 /// <param name="defaultMessageLevel"></param>
54 /// <returns></returns>
55 public MessageLevel CalculateMessageLevel(IMessaging messaging, Message message, MessageLevel defaultMessageLevel) => defaultMessageLevel;
56 }
57}
diff --git a/src/wix/WixInternal.Core.MSTestPackage/WixInternal.Core.MSTestPackage.csproj b/src/wix/WixInternal.Core.MSTestPackage/WixInternal.Core.MSTestPackage.csproj
new file mode 100644
index 00000000..6b4bbefe
--- /dev/null
+++ b/src/wix/WixInternal.Core.MSTestPackage/WixInternal.Core.MSTestPackage.csproj
@@ -0,0 +1,35 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFrameworks>net6.0;net472</TargetFrameworks>
7 <Description>Internal WiX Toolset MSTest Package</Description>
8 <DebugType>embedded</DebugType>
9 <PublishRepositoryUrl>true</PublishRepositoryUrl>
10 <CreateDocumentationFile>true</CreateDocumentationFile>
11 <SignOutput>false</SignOutput>
12 <IsWixTestSupportProject>true</IsWixTestSupportProject>
13 </PropertyGroup>
14
15 <ItemGroup>
16 <ProjectReference Include="..\WixToolset.Core.Native\WixToolset.Core.Native.csproj" PrivateAssets="true" />
17 <ProjectReference Include="..\WixToolset.Core\WixToolset.Core.csproj" PrivateAssets="true" />
18 <ProjectReference Include="..\WixToolset.Core.Burn\WixToolset.Core.Burn.csproj" PrivateAssets="true" />
19 <ProjectReference Include="..\WixToolset.Core.ExtensionCache\WixToolset.Core.ExtensionCache.csproj" PrivateAssets="true" />
20 <ProjectReference Include="..\WixToolset.Core.WindowsInstaller\WixToolset.Core.WindowsInstaller.csproj" PrivateAssets="true" />
21 </ItemGroup>
22
23 <ItemGroup>
24 <PackageReference Include="WixToolset.Data" />
25 <PackageReference Include="WixToolset.Extensibility" />
26 </ItemGroup>
27
28 <ItemGroup>
29 <PackageReference Include="WixInternal.MSTestSupport" />
30 </ItemGroup>
31
32 <ItemGroup>
33 <PackageReference Include="MSTest.TestFramework" />
34 </ItemGroup>
35</Project>
diff --git a/src/wix/WixInternal.Core.MSTestPackage/WixMessageFormatter.cs b/src/wix/WixInternal.Core.MSTestPackage/WixMessageFormatter.cs
new file mode 100644
index 00000000..c103f5d2
--- /dev/null
+++ b/src/wix/WixInternal.Core.MSTestPackage/WixMessageFormatter.cs
@@ -0,0 +1,40 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.Core.MSTestPackage
4{
5 using System;
6 using WixToolset.Data;
7
8 /// <summary>
9 /// Utility class to help format messages.
10 /// </summary>
11 public static class WixMessageFormatter
12 {
13 /// <summary>
14 /// Formats a message into a standard string with the level, id, and message.
15 /// </summary>
16 /// <param name="message">Message to format</param>
17 /// <returns>Standard message formatting with the level, id, and message.</returns>
18 public static string FormatMessage(Message message)
19 {
20 return $"{message.Level} {message.Id}: {message}";
21 }
22
23 /// <summary>
24 /// Formats a message into a standard string with the level, id, and message.
25 /// </summary>
26 /// <param name="message">Message to format</param>
27 /// <param name="replacementMatch">Match for the replacement</param>
28 /// <param name="replacement">Value to replace</param>
29 /// <returns>Standard message formatting with the level, id, and message.</returns>
30 public static string FormatMessage(Message message, string replacementMatch, string replacement)
31 {
32 if (replacement is null)
33 {
34 throw new ArgumentNullException(nameof(replacement));
35 }
36
37 return $"{message.Level} {message.Id}: {message}".Replace(replacementMatch, replacement);
38 }
39 }
40}
diff --git a/src/wix/WixInternal.Core.MSTestPackage/WixRunner.cs b/src/wix/WixInternal.Core.MSTestPackage/WixRunner.cs
new file mode 100644
index 00000000..d83ba93e
--- /dev/null
+++ b/src/wix/WixInternal.Core.MSTestPackage/WixRunner.cs
@@ -0,0 +1,90 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.Core.MSTestPackage
4{
5 using System.Collections.Generic;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using WixToolset.Core;
9 using WixToolset.Core.Burn;
10 using WixToolset.Core.ExtensionCache;
11 using WixToolset.Core.WindowsInstaller;
12 using WixToolset.Data;
13 using WixToolset.Extensibility.Services;
14
15 /// <summary>
16 /// Utility class to emulate wix.exe with standard backends.
17 /// </summary>
18 public static class WixRunner
19 {
20 /// <summary>
21 /// Emulates calling wix.exe with standard backends.
22 /// </summary>
23 /// <param name="args"></param>
24 /// <param name="messages"></param>
25 /// <param name="warningsAsErrors"></param>
26 /// <returns></returns>
27 public static int Execute(string[] args, out List<Message> messages, bool warningsAsErrors = true)
28 {
29 var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider();
30 var task = Execute(args, serviceProvider, out messages, warningsAsErrors: warningsAsErrors);
31 return task.Result;
32 }
33
34 /// <summary>
35 /// Emulates calling wix.exe with standard backends.
36 /// This overload always treats warnings as errors.
37 /// </summary>
38 /// <param name="args"></param>
39 /// <returns></returns>
40 public static WixRunnerResult Execute(params string[] args)
41 {
42 return Execute(true, args);
43 }
44
45 /// <summary>
46 /// Emulates calling wix.exe with standard backends.
47 /// </summary>
48 /// <param name="warningsAsErrors"></param>
49 /// <param name="args"></param>
50 /// <returns></returns>
51 public static WixRunnerResult Execute(bool warningsAsErrors, params string[] args)
52 {
53 var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider();
54 var exitCode = Execute(args, serviceProvider, out var messages, warningsAsErrors: warningsAsErrors);
55 return new WixRunnerResult { ExitCode = exitCode.Result, Messages = messages.ToArray() };
56 }
57
58 /// <summary>
59 /// Emulates calling wix.exe with standard backends.
60 /// </summary>
61 /// <param name="args"></param>
62 /// <param name="coreProvider"></param>
63 /// <param name="messages"></param>
64 /// <param name="warningsAsErrors"></param>
65 /// <returns></returns>
66 public static Task<int> Execute(string[] args, IWixToolsetCoreServiceProvider coreProvider, out List<Message> messages, bool warningsAsErrors = true)
67 {
68 coreProvider.AddWindowsInstallerBackend()
69 .AddBundleBackend()
70 .AddExtensionCacheManager();
71
72 var listener = new TestMessageListener();
73
74 messages = listener.Messages;
75
76 var messaging = coreProvider.GetService<IMessaging>();
77 messaging.SetListener(listener);
78
79 var arguments = new List<string>(args);
80 if (warningsAsErrors)
81 {
82 arguments.Add("-wx");
83 }
84
85 var commandLine = coreProvider.GetService<ICommandLine>();
86 var command = commandLine.CreateCommand(arguments.ToArray());
87 return command?.ExecuteAsync(CancellationToken.None) ?? Task.FromResult(1);
88 }
89 }
90}
diff --git a/src/wix/WixInternal.Core.MSTestPackage/WixRunnerResult.cs b/src/wix/WixInternal.Core.MSTestPackage/WixRunnerResult.cs
new file mode 100644
index 00000000..4a8c784d
--- /dev/null
+++ b/src/wix/WixInternal.Core.MSTestPackage/WixRunnerResult.cs
@@ -0,0 +1,62 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.Core.MSTestPackage
4{
5 using System;
6 using System.Collections.Generic;
7 using WixToolset.Data;
8 using Microsoft.VisualStudio.TestTools.UnitTesting;
9
10 /// <summary>
11 /// The result of an Execute method of <see cref="WixRunner"/>.
12 /// </summary>
13 public class WixRunnerResult
14 {
15 /// <summary>
16 /// ExitCode for the operation.
17 /// </summary>
18 public int ExitCode { get; set; }
19
20 /// <summary>
21 /// Messages from the operation.
22 /// </summary>
23 public Message[] Messages { get; set; }
24
25 /// <summary>
26 ///
27 /// </summary>
28 /// <returns></returns>
29 public WixRunnerResult AssertSuccess()
30 {
31 AssertSuccess(this.ExitCode, this.Messages);
32 return this;
33 }
34
35 /// <summary>
36 ///
37 /// </summary>
38 /// <param name="exitCode"></param>
39 /// <param name="messages"></param>
40 public static void AssertSuccess(int exitCode, IEnumerable<Message> messages)
41 {
42 Assert.IsTrue(0 == exitCode, $"\r\n\r\nWixRunner failed with exit code: {exitCode}\r\n Output: {String.Join("\r\n ", FormatMessages(messages))}\r\n");
43 }
44
45 private static IEnumerable<string> FormatMessages(IEnumerable<Message> messages)
46 {
47 foreach (var message in messages)
48 {
49 var filename = message.SourceLineNumbers?.FileName ?? "TEST";
50 var line = message.SourceLineNumbers?.LineNumber ?? -1;
51 var type = message.Level.ToString().ToLowerInvariant();
52
53 if (line > 0)
54 {
55 filename = String.Concat(filename, "(", line, ")");
56 }
57
58 yield return String.Format("{0} : {1} {2}{3:0000}: {4}", filename, type, "TEST", message.Id, message.ToString());
59 }
60 }
61 }
62}
diff --git a/src/wix/WixInternal.Core.MSTestPackage/XmlNodeExtensions.cs b/src/wix/WixInternal.Core.MSTestPackage/XmlNodeExtensions.cs
new file mode 100644
index 00000000..11a7b209
--- /dev/null
+++ b/src/wix/WixInternal.Core.MSTestPackage/XmlNodeExtensions.cs
@@ -0,0 +1,115 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixInternal.Core.MSTestPackage
4{
5 using System.Collections.Generic;
6 using System.IO;
7 using System.Linq;
8 using System.Text.RegularExpressions;
9 using System.Xml;
10
11 /// <summary>
12 /// Utility class to help compare XML in tests using string comparisons by using single quotes and stripping all namespaces.
13 /// </summary>
14 public static class XmlNodeExtensions
15 {
16 /// <summary>
17 /// Adds root element around XML then returns it using single quotes and stripping all namespaces.
18 /// </summary>
19 /// <param name="xmlFragment"></param>
20 /// <param name="ignoredAttributesByElementName">Attributes for which the value should be set to '*'.</param>
21 /// <returns></returns>
22 public static string GetFragmentTestXml(this string xmlFragment, Dictionary<string, List<string>> ignoredAttributesByElementName = null)
23 {
24 return $"<root>{xmlFragment}</root>".GetTestXml(ignoredAttributesByElementName);
25 }
26
27 /// <summary>
28 /// Returns the node's outer XML using single quotes and stripping all namespaces.
29 /// </summary>
30 /// <param name="node"></param>
31 /// <param name="ignoredAttributesByElementName">Attributes for which the value should be set to '*'.</param>
32 /// <returns></returns>
33 public static string GetTestXml(this XmlNode node, Dictionary<string, List<string>> ignoredAttributesByElementName = null)
34 {
35 return node.OuterXml.GetTestXml(ignoredAttributesByElementName);
36 }
37
38 /// <summary>
39 /// Returns the XML using single quotes and stripping all namespaces.
40 /// </summary>
41 /// <param name="xml"></param>
42 /// <param name="ignoredAttributesByElementName">Attributes for which the value should be set to '*'.</param>
43 /// <returns></returns>
44 public static string GetTestXml(this string xml, Dictionary<string, List<string>> ignoredAttributesByElementName = null)
45 {
46 string formattedXml;
47 using (var sw = new StringWriter())
48 using (var writer = new TestXmlWriter(sw))
49 {
50 var doc = new XmlDocument();
51 doc.LoadXml(xml);
52
53 if (ignoredAttributesByElementName != null)
54 {
55 HandleIgnoredAttributes(doc, ignoredAttributesByElementName);
56 }
57
58 doc.Save(writer);
59 formattedXml = sw.ToString();
60 }
61
62 return Regex.Replace(formattedXml, " xmlns(:[^=]+)?='[^']*'", "");
63 }
64
65 /// <summary>
66 /// Returns the XML for each node using single quotes and stripping all namespaces.
67 /// </summary>
68 /// <param name="nodeList"></param>
69 /// <param name="ignoredAttributesByElementName">Attributes for which the value should be set to '*'.</param>
70 /// <returns></returns>
71 public static string[] GetTestXmlLines(this XmlNodeList nodeList, Dictionary<string, List<string>> ignoredAttributesByElementName = null)
72 {
73 return nodeList.Cast<XmlNode>()
74 .Select(x => x.GetTestXml(ignoredAttributesByElementName))
75 .ToArray();
76 }
77
78 private static void HandleIgnoredAttributes(XmlNode node, Dictionary<string, List<string>> ignoredAttributesByElementName)
79 {
80 if (node.Attributes != null && ignoredAttributesByElementName.TryGetValue(node.LocalName, out var ignoredAttributes))
81 {
82 foreach (var ignoredAttribute in ignoredAttributes)
83 {
84 var attribute = node.Attributes[ignoredAttribute];
85 if (attribute != null)
86 {
87 attribute.Value = "*";
88 }
89 }
90 }
91
92 if (node.ChildNodes != null)
93 {
94 foreach (XmlNode childNode in node.ChildNodes)
95 {
96 HandleIgnoredAttributes(childNode, ignoredAttributesByElementName);
97 }
98 }
99 }
100
101 private class TestXmlWriter : XmlTextWriter
102 {
103 public TestXmlWriter(TextWriter w)
104 : base(w)
105 {
106 this.QuoteChar = '\'';
107 }
108
109 public override void WriteStartDocument()
110 {
111 //OmitXmlDeclaration
112 }
113 }
114 }
115}
diff --git a/src/wix/pack_t.proj b/src/wix/pack_t.proj
index cd2cf634..7090f19b 100644
--- a/src/wix/pack_t.proj
+++ b/src/wix/pack_t.proj
@@ -8,6 +8,7 @@
8 <ProjectReference Include="WixToolset.Core.Burn\WixToolset.Core.Burn.csproj" Properties="NoBuild=true" Targets="Pack" /> 8 <ProjectReference Include="WixToolset.Core.Burn\WixToolset.Core.Burn.csproj" Properties="NoBuild=true" Targets="Pack" />
9 <ProjectReference Include="WixToolset.Core.ExtensionCache\WixToolset.Core.ExtensionCache.csproj" Properties="NoBuild=true" Targets="Pack" /> 9 <ProjectReference Include="WixToolset.Core.ExtensionCache\WixToolset.Core.ExtensionCache.csproj" Properties="NoBuild=true" Targets="Pack" />
10 <ProjectReference Include="WixInternal.Core.TestPackage\WixInternal.Core.TestPackage.csproj" Properties="NoBuild=true" Targets="Pack" /> 10 <ProjectReference Include="WixInternal.Core.TestPackage\WixInternal.Core.TestPackage.csproj" Properties="NoBuild=true" Targets="Pack" />
11 <ProjectReference Include="WixInternal.Core.MSTestPackage\WixInternal.Core.MSTestPackage.csproj" Properties="NoBuild=true" Targets="Pack" />
11 <ProjectReference Include="WixToolset.Core.WindowsInstaller\WixToolset.Core.WindowsInstaller.csproj" Properties="NoBuild=true" Targets="Pack" /> 12 <ProjectReference Include="WixToolset.Core.WindowsInstaller\WixToolset.Core.WindowsInstaller.csproj" Properties="NoBuild=true" Targets="Pack" />
12 13
13 <ProjectReference Include="WixToolset.Converters\WixToolset.Converters.csproj" Properties="NoBuild=true" Targets="Pack" /> 14 <ProjectReference Include="WixToolset.Converters\WixToolset.Converters.csproj" Properties="NoBuild=true" Targets="Pack" />
diff --git a/src/wix/wix.sln b/src/wix/wix.sln
index f64b22c0..7eec8e8a 100644
--- a/src/wix/wix.sln
+++ b/src/wix/wix.sln
@@ -48,6 +48,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pack-wix", "pack-wix\pack-w
48EndProject 48EndProject
49Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Core", "test\WixToolsetTest.Core\WixToolsetTest.Core.csproj", "{392817AE-4493-4BED-A7FD-2399379E1B1C}" 49Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Core", "test\WixToolsetTest.Core\WixToolsetTest.Core.csproj", "{392817AE-4493-4BED-A7FD-2399379E1B1C}"
50EndProject 50EndProject
51Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixInternal.Core.MSTestPackage", "WixInternal.Core.MSTestPackage\WixInternal.Core.MSTestPackage.csproj", "{61003299-4D78-4291-862C-73806C62C3BD}"
52EndProject
51Global 53Global
52 GlobalSection(SolutionConfigurationPlatforms) = preSolution 54 GlobalSection(SolutionConfigurationPlatforms) = preSolution
53 Debug|Any CPU = Debug|Any CPU 55 Debug|Any CPU = Debug|Any CPU
@@ -412,6 +414,22 @@ Global
412 {392817AE-4493-4BED-A7FD-2399379E1B1C}.Release|x64.Build.0 = Release|Any CPU 414 {392817AE-4493-4BED-A7FD-2399379E1B1C}.Release|x64.Build.0 = Release|Any CPU
413 {392817AE-4493-4BED-A7FD-2399379E1B1C}.Release|x86.ActiveCfg = Release|Any CPU 415 {392817AE-4493-4BED-A7FD-2399379E1B1C}.Release|x86.ActiveCfg = Release|Any CPU
414 {392817AE-4493-4BED-A7FD-2399379E1B1C}.Release|x86.Build.0 = Release|Any CPU 416 {392817AE-4493-4BED-A7FD-2399379E1B1C}.Release|x86.Build.0 = Release|Any CPU
417 {61003299-4D78-4291-862C-73806C62C3BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
418 {61003299-4D78-4291-862C-73806C62C3BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
419 {61003299-4D78-4291-862C-73806C62C3BD}.Debug|ARM64.ActiveCfg = Debug|Any CPU
420 {61003299-4D78-4291-862C-73806C62C3BD}.Debug|ARM64.Build.0 = Debug|Any CPU
421 {61003299-4D78-4291-862C-73806C62C3BD}.Debug|x64.ActiveCfg = Debug|Any CPU
422 {61003299-4D78-4291-862C-73806C62C3BD}.Debug|x64.Build.0 = Debug|Any CPU
423 {61003299-4D78-4291-862C-73806C62C3BD}.Debug|x86.ActiveCfg = Debug|Any CPU
424 {61003299-4D78-4291-862C-73806C62C3BD}.Debug|x86.Build.0 = Debug|Any CPU
425 {61003299-4D78-4291-862C-73806C62C3BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
426 {61003299-4D78-4291-862C-73806C62C3BD}.Release|Any CPU.Build.0 = Release|Any CPU
427 {61003299-4D78-4291-862C-73806C62C3BD}.Release|ARM64.ActiveCfg = Release|Any CPU
428 {61003299-4D78-4291-862C-73806C62C3BD}.Release|ARM64.Build.0 = Release|Any CPU
429 {61003299-4D78-4291-862C-73806C62C3BD}.Release|x64.ActiveCfg = Release|Any CPU
430 {61003299-4D78-4291-862C-73806C62C3BD}.Release|x64.Build.0 = Release|Any CPU
431 {61003299-4D78-4291-862C-73806C62C3BD}.Release|x86.ActiveCfg = Release|Any CPU
432 {61003299-4D78-4291-862C-73806C62C3BD}.Release|x86.Build.0 = Release|Any CPU
415 EndGlobalSection 433 EndGlobalSection
416 GlobalSection(SolutionProperties) = preSolution 434 GlobalSection(SolutionProperties) = preSolution
417 HideSolutionNode = FALSE 435 HideSolutionNode = FALSE