From c843b47d6233153fa961c6d0e61edf7cedf255bb Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 8 Nov 2022 14:58:05 -0800 Subject: Separate WixInternal content from official WixToolset namespace --- src/internal/WixBuildTools.TestSupport/Builder.cs | 158 --------- .../DisposableFileSystem.cs | 93 ----- .../WixBuildTools.TestSupport/DotnetRunner.cs | 57 ---- .../ExternalExecutable.cs | 374 --------------------- .../ExternalExecutableResult.cs | 19 -- .../WixBuildTools.TestSupport/FakeBuildEngine.cs | 33 -- .../WixBuildTools.TestSupport/MsbuildRunner.cs | 112 ------ .../MsbuildRunnerResult.cs | 19 -- .../WixBuildTools.TestSupport/MsbuildUtilities.cs | 101 ------ src/internal/WixBuildTools.TestSupport/Pushd.cs | 46 --- src/internal/WixBuildTools.TestSupport/Query.cs | 172 ---------- .../WixBuildTools.TestSupport/RobocopyRunner.cs | 16 - src/internal/WixBuildTools.TestSupport/TestData.cs | 78 ----- .../TestDataFolderFileSystem.cs | 42 --- .../WixBuildTools.TestSupport/VswhereRunner.cs | 41 --- .../WixBuildTools.TestSupport.csproj | 27 -- .../XunitExtensions/SkipTestException.cs | 15 - .../XunitExtensions/SkippableFactAttribute.cs | 13 - .../XunitExtensions/SkippableFactDiscoverer.cs | 23 -- .../XunitExtensions/SkippableFactMessageBus.cs | 40 --- .../XunitExtensions/SkippableFactTestCase.cs | 40 --- .../XunitExtensions/SkippableTheoryAttribute.cs | 12 - .../XunitExtensions/SkippableTheoryDiscoverer.cs | 41 --- .../XunitExtensions/SkippableTheoryTestCase.cs | 41 --- .../XunitExtensions/SpecificReturnCodeException.cs | 20 -- .../XunitExtensions/SucceededException.cs | 19 -- .../XunitExtensions/WixAssert.cs | 201 ----------- 27 files changed, 1853 deletions(-) delete mode 100644 src/internal/WixBuildTools.TestSupport/Builder.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/DisposableFileSystem.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/DotnetRunner.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/ExternalExecutable.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/ExternalExecutableResult.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/FakeBuildEngine.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/MsbuildRunnerResult.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/MsbuildUtilities.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/Pushd.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/Query.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/RobocopyRunner.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/TestData.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/TestDataFolderFileSystem.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/VswhereRunner.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/WixBuildTools.TestSupport.csproj delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SkipTestException.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactAttribute.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactDiscoverer.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactMessageBus.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactTestCase.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryAttribute.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryDiscoverer.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryTestCase.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/SucceededException.cs delete mode 100644 src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs (limited to 'src/internal/WixBuildTools.TestSupport') diff --git a/src/internal/WixBuildTools.TestSupport/Builder.cs b/src/internal/WixBuildTools.TestSupport/Builder.cs deleted file mode 100644 index 31df0084..00000000 --- a/src/internal/WixBuildTools.TestSupport/Builder.cs +++ /dev/null @@ -1,158 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.Collections.Generic; - using System.IO; - - public class Builder - { - public Builder(string sourceFolder, Type extensionType = null, string[] bindPaths = null, string outputFile = null) - { - this.SourceFolder = sourceFolder; - this.ExtensionType = extensionType; - this.BindPaths = bindPaths; - this.OutputFile = outputFile ?? "test.msi"; - } - - public string[] BindPaths { get; set; } - - public Type ExtensionType { get; set; } - - public string OutputFile { get; set; } - - public string SourceFolder { get; } - - public string[] BuildAndQuery(Action buildFunc, params string[] tables) - { - var sourceFiles = Directory.GetFiles(this.SourceFolder, "*.wxs"); - var wxlFiles = Directory.GetFiles(this.SourceFolder, "*.wxl"); - - using (var fs = new DisposableFileSystem()) - { - var intermediateFolder = fs.GetFolder(); - var outputPath = Path.Combine(intermediateFolder, "bin", this.OutputFile); - - var args = new List - { - "build", - "-o", outputPath, - "-intermediateFolder", intermediateFolder, - }; - - if (this.ExtensionType != null) - { - args.Add("-ext"); - args.Add(Path.GetFullPath(new Uri(this.ExtensionType.Assembly.CodeBase).LocalPath)); - } - - args.AddRange(sourceFiles); - - foreach (var wxlFile in wxlFiles) - { - args.Add("-loc"); - args.Add(wxlFile); - } - - foreach (var bindPath in this.BindPaths) - { - args.Add("-bindpath"); - args.Add(bindPath); - } - - buildFunc(args.ToArray()); - - return Query.QueryDatabase(outputPath, tables); - } - } - - public void BuildAndDecompileAndBuild(Action buildFunc, Action decompileFunc, string decompilePath) - { - var sourceFiles = Directory.GetFiles(this.SourceFolder, "*.wxs"); - var wxlFiles = Directory.GetFiles(this.SourceFolder, "*.wxl"); - - using (var fs = new DisposableFileSystem()) - { - var intermediateFolder = fs.GetFolder(); - var outputFolder = Path.Combine(intermediateFolder, "bin"); - var decompileExtractFolder = Path.Combine(intermediateFolder, "decompiled", "extract"); - var decompileIntermediateFolder = Path.Combine(intermediateFolder, "decompiled", "obj"); - var decompileBuildFolder = Path.Combine(intermediateFolder, "decompiled", "bin"); - var outputPath = Path.Combine(outputFolder, this.OutputFile); - var decompileBuildPath = Path.Combine(decompileBuildFolder, this.OutputFile); - - // First build. - var firstBuildArgs = new List - { - "build", - "-o", outputPath, - "-intermediateFolder", intermediateFolder, - }; - - if (this.ExtensionType != null) - { - firstBuildArgs.Add("-ext"); - firstBuildArgs.Add(Path.GetFullPath(new Uri(this.ExtensionType.Assembly.CodeBase).LocalPath)); - } - - firstBuildArgs.AddRange(sourceFiles); - - foreach (var wxlFile in wxlFiles) - { - firstBuildArgs.Add("-loc"); - firstBuildArgs.Add(wxlFile); - } - - foreach (var bindPath in this.BindPaths) - { - firstBuildArgs.Add("-bindpath"); - firstBuildArgs.Add(bindPath); - } - - buildFunc(firstBuildArgs.ToArray()); - - // Decompile built output. - var decompileArgs = new List - { - "msi", "decompile", - outputPath, - "-intermediateFolder", decompileIntermediateFolder, - "-x", decompileExtractFolder, - "-o", decompilePath - }; - - if (this.ExtensionType != null) - { - decompileArgs.Add("-ext"); - decompileArgs.Add(Path.GetFullPath(new Uri(this.ExtensionType.Assembly.CodeBase).LocalPath)); - } - - decompileFunc(decompileArgs.ToArray()); - - // Build decompiled output. - var secondBuildArgs = new List - { - "build", - decompilePath, - "-o", decompileBuildPath, - "-intermediateFolder", decompileIntermediateFolder - }; - - if (this.ExtensionType != null) - { - secondBuildArgs.Add("-ext"); - secondBuildArgs.Add(Path.GetFullPath(new Uri(this.ExtensionType.Assembly.CodeBase).LocalPath)); - } - - secondBuildArgs.Add("-bindpath"); - secondBuildArgs.Add(outputFolder); - - secondBuildArgs.Add("-bindpath"); - secondBuildArgs.Add(decompileExtractFolder); - - buildFunc(secondBuildArgs.ToArray()); - } - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/DisposableFileSystem.cs b/src/internal/WixBuildTools.TestSupport/DisposableFileSystem.cs deleted file mode 100644 index f096db72..00000000 --- a/src/internal/WixBuildTools.TestSupport/DisposableFileSystem.cs +++ /dev/null @@ -1,93 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.Collections.Generic; - using System.IO; - - public class DisposableFileSystem : IDisposable - { - protected bool Disposed { get; private set; } - - private List CleanupPaths { get; } = new List(); - - public bool Keep { get; } - - public DisposableFileSystem(bool keep = false) - { - this.Keep = keep; - } - - protected string GetFile(bool create = false) - { - var path = Path.GetTempFileName(); - - if (!create) - { - File.Delete(path); - } - - this.CleanupPaths.Add(path); - - return path; - } - - public string GetFolder(bool create = false) - { - var path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - - if (create) - { - Directory.CreateDirectory(path); - } - - this.CleanupPaths.Add(path); - - return path; - } - - - #region // IDisposable - - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (this.Disposed) - { - return; - } - - if (disposing && !this.Keep) - { - foreach (var path in this.CleanupPaths) - { - try - { - if (File.Exists(path)) - { - File.Delete(path); - } - else if (Directory.Exists(path)) - { - Directory.Delete(path, true); - } - } - catch - { - // Best effort delete, so ignore any failures. - } - } - } - - this.Disposed = true; - } - - #endregion - } -} diff --git a/src/internal/WixBuildTools.TestSupport/DotnetRunner.cs b/src/internal/WixBuildTools.TestSupport/DotnetRunner.cs deleted file mode 100644 index 82391178..00000000 --- a/src/internal/WixBuildTools.TestSupport/DotnetRunner.cs +++ /dev/null @@ -1,57 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.Collections.Generic; - using System.IO; - - public class DotnetRunner : ExternalExecutable - { - private static readonly object InitLock = new object(); - private static bool Initialized; - private static DotnetRunner Instance; - - public static ExternalExecutableResult Execute(string command, string[] arguments = null) => - InitAndExecute(command, arguments); - - private static ExternalExecutableResult InitAndExecute(string command, string[] arguments) - { - lock (InitLock) - { - if (!Initialized) - { - Initialized = true; - var dotnetPath = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH"); - if (String.IsNullOrEmpty(dotnetPath) || !File.Exists(dotnetPath)) - { - dotnetPath = "dotnet"; - } - - Instance = new DotnetRunner(dotnetPath); - } - } - - return Instance.ExecuteCore(command, arguments); - } - - private DotnetRunner(string exePath) : base(exePath) { } - - private ExternalExecutableResult ExecuteCore(string command, string[] arguments) - { - var total = new List - { - command, - }; - - if (arguments != null) - { - total.AddRange(arguments); - } - - var args = CombineArguments(total); - var mergeErrorIntoOutput = true; - return this.Run(args, mergeErrorIntoOutput); - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/ExternalExecutable.cs b/src/internal/WixBuildTools.TestSupport/ExternalExecutable.cs deleted file mode 100644 index 4a932645..00000000 --- a/src/internal/WixBuildTools.TestSupport/ExternalExecutable.cs +++ /dev/null @@ -1,374 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.Collections.Concurrent; - using System.Collections.Generic; - using System.ComponentModel; - using System.Diagnostics; - using System.IO; - using System.Runtime.InteropServices; - using System.Text; - using System.Threading.Tasks; - using Microsoft.Win32.SafeHandles; - - public abstract class ExternalExecutable - { - private readonly string exePath; - - protected ExternalExecutable(string exePath) - { - this.exePath = exePath; - } - - protected ExternalExecutableResult Run(string args, bool mergeErrorIntoOutput = false, string workingDirectory = null) - { - // https://github.com/dotnet/runtime/issues/58492 - // Process.Start doesn't currently support starting a process with a long path, - // but the way to support long paths doesn't support searching for the executable if it was a relative path. - // Avoid the managed way of doing this even if the target isn't a long path to help verify that the native way works. - if (!Path.IsPathRooted(this.exePath)) - { - return this.RunManaged(args, mergeErrorIntoOutput, workingDirectory); - } - - // https://web.archive.org/web/20150331190801/https://support.microsoft.com/en-us/kb/190351 - var commandLine = $"\"{this.exePath}\" {args}"; - var currentDirectory = workingDirectory ?? Path.GetDirectoryName(this.exePath); - if (String.IsNullOrEmpty(currentDirectory)) - { - currentDirectory = null; - } - var processInfo = new PROCESS_INFORMATION(); - var startInfo = new STARTUPINFOW - { - cb = Marshal.SizeOf(typeof(STARTUPINFOW)), - dwFlags = StartupInfoFlags.STARTF_FORCEOFFFEEDBACK | StartupInfoFlags.STARTF_USESTDHANDLES, - hStdInput = GetStdHandle(StdHandleType.STD_INPUT_HANDLE), - }; - SafeFileHandle hStdOutputParent = null; - SafeFileHandle hStdErrorParent = null; - - try - { - CreatePipeForProcess(out hStdOutputParent, out startInfo.hStdOutput); - - if (!mergeErrorIntoOutput) - { - CreatePipeForProcess(out hStdErrorParent, out startInfo.hStdError); - } - else - { - if (!DuplicateHandle(GetCurrentProcess(), startInfo.hStdOutput, GetCurrentProcess(), out startInfo.hStdError, 0, true, DuplicateHandleOptions.DUPLICATE_SAME_ACCESS)) - { - throw new Win32Exception(); - } - } - - if (!CreateProcessW(this.exePath, commandLine, IntPtr.Zero, IntPtr.Zero, true, CreateProcessFlags.CREATE_NO_WINDOW, IntPtr.Zero, - currentDirectory, ref startInfo, ref processInfo)) - { - throw new Win32Exception(); - } - - startInfo.Dispose(); - - return GetResultFromNative(mergeErrorIntoOutput, hStdOutputParent, hStdErrorParent, processInfo.hProcess, this.exePath, args); - } - finally - { - hStdErrorParent?.Dispose(); - hStdOutputParent?.Dispose(); - - startInfo.Dispose(); - processInfo.Dispose(); - } - } - - private static ExternalExecutableResult GetResultFromNative(bool mergeErrorIntoOutput, SafeFileHandle hStdOutputParent, SafeFileHandle hStdErrorParent, IntPtr hProcess, string fileName, string args) - { - using (var outputStream = new StreamReader(new FileStream(hStdOutputParent, FileAccess.Read))) - using (var errorStream = mergeErrorIntoOutput ? null : new StreamReader(new FileStream(hStdErrorParent, FileAccess.Read))) - { - var outputTask = Task.Run(() => ReadProcessStreamLines(outputStream)); - var errorTask = Task.Run(() => ReadProcessStreamLines(errorStream)); - - while (!outputTask.Wait(100) || !errorTask.Wait(100)) { Task.Yield(); } - var standardOutput = outputTask.Result; - var standardError = errorTask.Result; - - if (WaitForSingleObject(hProcess, -1) != 0) - { - throw new Win32Exception(); - } - - if (!GetExitCodeProcess(hProcess, out var exitCode)) - { - throw new Win32Exception(); - } - - return new ExternalExecutableResult - { - ExitCode = exitCode, - StandardError = standardError, - StandardOutput = standardOutput, - FileName = fileName, - Arguments = args, - }; - } - } - - private static string[] ReadProcessStreamLines(StreamReader streamReader) - { - if (streamReader == null) - { - return null; - } - - var lines = new List(); - while (true) - { - var line = streamReader.ReadLine(); - if (line == null) - { - break; - } - - lines.Add(line); - } - - return lines.ToArray(); - } - - protected ExternalExecutableResult RunManaged(string args, bool mergeErrorIntoOutput = false, string workingDirectory = null) - { - var startInfo = new ProcessStartInfo(this.exePath, args) - { - CreateNoWindow = true, - RedirectStandardError = true, - RedirectStandardOutput = true, - UseShellExecute = false, - WorkingDirectory = workingDirectory ?? Path.GetDirectoryName(this.exePath), - }; - - using (var process = Process.Start(startInfo)) - { - // This implementation of merging the streams does not guarantee that lines are retrieved in the same order that they were written. - // If the process is simultaneously writing to both streams, this is impossible to do anyway. - var standardOutput = new ConcurrentQueue(); - var standardError = mergeErrorIntoOutput ? standardOutput : new ConcurrentQueue(); - - process.ErrorDataReceived += (s, e) => { if (e.Data != null) { standardError.Enqueue(e.Data); } }; - process.OutputDataReceived += (s, e) => { if (e.Data != null) { standardOutput.Enqueue(e.Data); } }; - - process.BeginErrorReadLine(); - process.BeginOutputReadLine(); - - process.WaitForExit(); - - return new ExternalExecutableResult - { - ExitCode = process.ExitCode, - StandardError = mergeErrorIntoOutput ? null : standardError.ToArray(), - StandardOutput = standardOutput.ToArray(), - FileName = this.exePath, - Arguments = args, - }; - } - } - - // This is internal because it assumes backslashes aren't used as escape characters and there aren't any double quotes. - internal static string CombineArguments(IEnumerable arguments) - { - if (arguments == null) - { - return null; - } - - var sb = new StringBuilder(); - - foreach (var arg in arguments) - { - if (sb.Length > 0) - { - sb.Append(' '); - } - - if (arg.IndexOf(' ') > -1) - { - sb.Append("\""); - sb.Append(arg); - sb.Append("\""); - } - else - { - sb.Append(arg); - } - } - - return sb.ToString(); - } - - private static void CreatePipeForProcess(out SafeFileHandle hReadPipe, out IntPtr hWritePipe) - { - var securityAttributes = new SECURITY_ATTRIBUTES - { - nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)), - bInheritHandle = true, - }; - - if (!CreatePipe(out var hReadTemp, out hWritePipe, ref securityAttributes, 0)) - { - throw new Win32Exception(); - } - - // Only the handle passed to the process should be inheritable, so have to duplicate the other handle to get an uninheritable one. - if (!DuplicateHandle(GetCurrentProcess(), hReadTemp, GetCurrentProcess(), out var hReadPipePtr, 0, false, DuplicateHandleOptions.DUPLICATE_CLOSE_SOURCE | DuplicateHandleOptions.DUPLICATE_SAME_ACCESS)) - { - throw new Win32Exception(); - } - - hReadPipe = new SafeFileHandle(hReadPipePtr, true); - } - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] - private extern static IntPtr GetStdHandle(StdHandleType nStdHandle); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private extern static bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private extern static bool CreateProcessW( - string lpApplicationName, - string lpCommandLine, - IntPtr lpProcessAttributes, - IntPtr lpThreadAttributes, - [MarshalAs(UnmanagedType.Bool)] bool bInheritHandles, - CreateProcessFlags dwCreationFlags, - IntPtr lpEnvironment, - string lpCurrentDirectory, - ref STARTUPINFOW lpStartupInfo, - ref PROCESS_INFORMATION lpProcessInformation); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] - private extern static IntPtr GetCurrentProcess(); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private extern static bool GetExitCodeProcess(IntPtr hHandle, out int lpExitCode); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] - private extern static int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private extern static bool CloseHandle(IntPtr hObject); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private extern static bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, DuplicateHandleOptions dwOptions); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct SECURITY_ATTRIBUTES - { - public int nLength; - public IntPtr lpSecurityDescriptor; - [MarshalAs(UnmanagedType.Bool)] - public bool bInheritHandle; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct STARTUPINFOW - { - public int cb; - public string lpReserved; - public string lpDesktop; - public string lpTitle; - public int dwX; - public int dwY; - public int dwXSize; - public int dwYSize; - public int dwXCountChars; - public int dwYCountChars; - public int dwFillAttribute; - public StartupInfoFlags dwFlags; - public short wShowWindow; - public short cbReserved2; - public IntPtr lpReserved2; - public IntPtr hStdInput; - public IntPtr hStdOutput; - public IntPtr hStdError; - - public void Dispose() - { - // This makes assumptions based on how it's used above. - if (this.hStdError != IntPtr.Zero) - { - CloseHandle(this.hStdError); - this.hStdError = IntPtr.Zero; - } - - if (this.hStdOutput != IntPtr.Zero) - { - CloseHandle(this.hStdOutput); - this.hStdOutput = IntPtr.Zero; - } - } - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct PROCESS_INFORMATION - { - public IntPtr hProcess; - public IntPtr hThread; - public int dwProcessId; - public int dwThreadId; - - public void Dispose() - { - if (this.hProcess != IntPtr.Zero) - { - CloseHandle(this.hProcess); - this.hProcess = IntPtr.Zero; - } - - if (this.hThread != IntPtr.Zero) - { - CloseHandle(this.hThread); - this.hThread = IntPtr.Zero; - } - } - } - - private enum StdHandleType - { - STD_INPUT_HANDLE = -10, - STD_OUTPUT_HANDLE = -11, - STD_ERROR_HANDLE = -12, - } - - [Flags] - private enum CreateProcessFlags - { - None = 0x0, - CREATE_NO_WINDOW = 0x08000000, - } - - [Flags] - private enum StartupInfoFlags - { - None = 0x0, - STARTF_FORCEOFFFEEDBACK = 0x80, - STARTF_USESTDHANDLES = 0x100, - } - - private enum DuplicateHandleOptions - { - DUPLICATE_CLOSE_SOURCE = 1, - DUPLICATE_SAME_ACCESS = 2, - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/ExternalExecutableResult.cs b/src/internal/WixBuildTools.TestSupport/ExternalExecutableResult.cs deleted file mode 100644 index 950ee4bd..00000000 --- a/src/internal/WixBuildTools.TestSupport/ExternalExecutableResult.cs +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System.Diagnostics; - - public class ExternalExecutableResult - { - public int ExitCode { get; set; } - - public string[] StandardError { get; set; } - - public string[] StandardOutput { get; set; } - - public string FileName { get; set; } - - public string Arguments { get; set; } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/FakeBuildEngine.cs b/src/internal/WixBuildTools.TestSupport/FakeBuildEngine.cs deleted file mode 100644 index 20545970..00000000 --- a/src/internal/WixBuildTools.TestSupport/FakeBuildEngine.cs +++ /dev/null @@ -1,33 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System.Collections; - using System.Text; - using Microsoft.Build.Framework; - - public class FakeBuildEngine : IBuildEngine - { - private readonly StringBuilder output = new StringBuilder(); - - public int ColumnNumberOfTaskNode => 0; - - public bool ContinueOnError => false; - - public int LineNumberOfTaskNode => 0; - - public string ProjectFileOfTaskNode => "fake_wix.targets"; - - public string Output => this.output.ToString(); - - public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs) => throw new System.NotImplementedException(); - - public void LogCustomEvent(CustomBuildEventArgs e) => this.output.AppendLine(e.Message); - - public void LogErrorEvent(BuildErrorEventArgs e) => this.output.AppendLine(e.Message); - - public void LogMessageEvent(BuildMessageEventArgs e) => this.output.AppendLine(e.Message); - - public void LogWarningEvent(BuildWarningEventArgs e) => this.output.AppendLine(e.Message); - } -} diff --git a/src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs b/src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs deleted file mode 100644 index ac7caf0e..00000000 --- a/src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs +++ /dev/null @@ -1,112 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.Collections.Generic; - using System.IO; - - public class MsbuildRunner : ExternalExecutable - { - private static readonly string VswhereFindArguments = "-property installationPath -version [17.0,18.0)"; - private static readonly string MsbuildCurrentRelativePath = @"MSBuild\Current\Bin\MSBuild.exe"; - private static readonly string MsbuildCurrentRelativePath64 = @"MSBuild\Current\Bin\amd64\MSBuild.exe"; - - private static readonly object InitLock = new object(); - - private static bool Initialized; - private static MsbuildRunner MsbuildCurrentRunner; - private static MsbuildRunner MsbuildCurrentRunner64; - - public static MsbuildRunnerResult Execute(string projectPath, string[] arguments = null, bool x64 = false) => - InitAndExecute(String.Empty, projectPath, arguments, x64); - - public static MsbuildRunnerResult ExecuteWithMsbuildCurrent(string projectPath, string[] arguments = null, bool x64 = false) => - InitAndExecute("Current", projectPath, arguments, x64); - - private static MsbuildRunnerResult InitAndExecute(string msbuildVersion, string projectPath, string[] arguments, bool x64) - { - lock (InitLock) - { - if (!Initialized) - { - Initialized = true; - var vswhereResult = VswhereRunner.Execute(VswhereFindArguments, true); - if (vswhereResult.ExitCode != 0) - { - throw new InvalidOperationException($"Failed to execute vswhere.exe, exit code: {vswhereResult.ExitCode}. Output:\r\n{String.Join("\r\n", vswhereResult.StandardOutput)}"); - } - - string msbuildCurrentPath = null; - string msbuildCurrentPath64 = null; - - foreach (var installPath in vswhereResult.StandardOutput) - { - if (msbuildCurrentPath == null) - { - var path = Path.Combine(installPath, MsbuildCurrentRelativePath); - if (File.Exists(path)) - { - msbuildCurrentPath = path; - } - } - - if (msbuildCurrentPath64 == null) - { - var path = Path.Combine(installPath, MsbuildCurrentRelativePath64); - if (File.Exists(path)) - { - msbuildCurrentPath64 = path; - } - } - } - - if (msbuildCurrentPath != null) - { - MsbuildCurrentRunner = new MsbuildRunner(msbuildCurrentPath); - } - - if (msbuildCurrentPath64 != null) - { - MsbuildCurrentRunner64 = new MsbuildRunner(msbuildCurrentPath64); - } - } - } - - MsbuildRunner runner = x64 ? MsbuildCurrentRunner64 : MsbuildCurrentRunner; - - if (runner == null) - { - throw new InvalidOperationException($"Failed to find an installed{(x64 ? " 64-bit" : String.Empty)} MSBuild{msbuildVersion}"); - } - - return runner.ExecuteCore(projectPath, arguments); - } - - private MsbuildRunner(string exePath) : base(exePath) { } - - private MsbuildRunnerResult ExecuteCore(string projectPath, string[] arguments) - { - var total = new List - { - projectPath, - }; - - if (arguments != null) - { - total.AddRange(arguments); - } - - var args = CombineArguments(total); - var mergeErrorIntoOutput = true; - var workingFolder = Path.GetDirectoryName(projectPath); - var result = this.Run(args, mergeErrorIntoOutput, workingFolder); - - return new MsbuildRunnerResult - { - ExitCode = result.ExitCode, - Output = result.StandardOutput, - }; - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/MsbuildRunnerResult.cs b/src/internal/WixBuildTools.TestSupport/MsbuildRunnerResult.cs deleted file mode 100644 index fb61122d..00000000 --- a/src/internal/WixBuildTools.TestSupport/MsbuildRunnerResult.cs +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using Xunit; - - public class MsbuildRunnerResult - { - public int ExitCode { get; set; } - - public string[] Output { get; set; } - - public void AssertSuccess() - { - Assert.True(0 == this.ExitCode, $"MSBuild failed unexpectedly. Output:{Environment.NewLine}{String.Join(Environment.NewLine, this.Output)}"); - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/MsbuildUtilities.cs b/src/internal/WixBuildTools.TestSupport/MsbuildUtilities.cs deleted file mode 100644 index 3271cc20..00000000 --- a/src/internal/WixBuildTools.TestSupport/MsbuildUtilities.cs +++ /dev/null @@ -1,101 +0,0 @@ -// 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. - -namespace WixToolsetTest.Sdk -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using WixBuildTools.TestSupport; - - public enum BuildSystem - { - DotNetCoreSdk, - MSBuild, - MSBuild64, - } - - public static class MsbuildUtilities - { - public static MsbuildRunnerResult BuildProject(BuildSystem buildSystem, string projectPath, string[] arguments = null, string configuration = "Release", string verbosityLevel = "normal", bool suppressValidation = true) - { - var allArgs = new List - { - $"-verbosity:{verbosityLevel}", - $"-p:Configuration={configuration}", - $"-p:SuppressValidation={suppressValidation}", - // Node reuse means that child msbuild processes can stay around after the build completes. - // Under that scenario, the root msbuild does not reliably close its streams which causes us to hang. - "-nr:false", - $"-bl:{Path.ChangeExtension(projectPath, ".binlog")}" - }; - - if (arguments != null) - { - allArgs.AddRange(arguments); - } - - switch (buildSystem) - { - case BuildSystem.DotNetCoreSdk: - { - allArgs.Add(projectPath); - var result = DotnetRunner.Execute("msbuild", allArgs.ToArray()); - return new MsbuildRunnerResult - { - ExitCode = result.ExitCode, - Output = result.StandardOutput, - }; - } - case BuildSystem.MSBuild: - case BuildSystem.MSBuild64: - { - return MsbuildRunner.Execute(projectPath, allArgs.ToArray(), buildSystem == BuildSystem.MSBuild64); - } - default: - { - throw new NotImplementedException(); - } - } - } - - public static string GetQuotedPropertySwitch(BuildSystem buildSystem, string propertyName, string valueToQuote) - { - switch (buildSystem) - { - case BuildSystem.DotNetCoreSdk: - { - // If the value ends with a backslash, double-escape it (it should end up with four backslashes). - if (valueToQuote?.EndsWith("\\") == true) - { - valueToQuote += @"\\\"; - } - - return $"-p:{propertyName}=\\\"{valueToQuote}\\\""; - } - case BuildSystem.MSBuild: - case BuildSystem.MSBuild64: - { - // If the value ends with a backslash, escape it. - if (valueToQuote?.EndsWith("\\") == true) - { - valueToQuote += @"\"; - } - - return $"-p:{propertyName}=\"{valueToQuote}\""; - } - default: - { - throw new NotImplementedException(); - } - } - } - - public static IEnumerable GetToolCommandLines(MsbuildRunnerResult result, string toolName, string operation, BuildSystem buildSystem) - { - var expectedToolExe = buildSystem == BuildSystem.DotNetCoreSdk ? $"{toolName}.dll\"" : $"{toolName}.exe"; - var expectedToolCommand = $"{expectedToolExe} {operation}"; - return result.Output.Where(line => line.Contains(expectedToolCommand)); - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/Pushd.cs b/src/internal/WixBuildTools.TestSupport/Pushd.cs deleted file mode 100644 index d0545215..00000000 --- a/src/internal/WixBuildTools.TestSupport/Pushd.cs +++ /dev/null @@ -1,46 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.IO; - - public class Pushd : IDisposable - { - protected bool Disposed { get; private set; } - - public Pushd(string path) - { - this.PreviousDirectory = Directory.GetCurrentDirectory(); - - Directory.SetCurrentDirectory(path); - } - - public string PreviousDirectory { get; } - - #region // IDisposable - - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (this.Disposed) - { - return; - } - - if (disposing) - { - Directory.SetCurrentDirectory(this.PreviousDirectory); - } - - this.Disposed = true; - } - - #endregion - } -} diff --git a/src/internal/WixBuildTools.TestSupport/Query.cs b/src/internal/WixBuildTools.TestSupport/Query.cs deleted file mode 100644 index 101a8890..00000000 --- a/src/internal/WixBuildTools.TestSupport/Query.cs +++ /dev/null @@ -1,172 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Text; - using WixToolset.Dtf.Compression.Cab; - using WixToolset.Dtf.WindowsInstaller; - - public class Query - { - public static string[] QueryDatabase(string path, string[] tables) - { - var results = new List(); - var resultsByTable = QueryDatabaseByTable(path, tables); - var sortedTables = tables.ToList(); - sortedTables.Sort(); - foreach (var tableName in sortedTables) - { - var rows = resultsByTable[tableName]; - rows?.ForEach(r => results.Add($"{tableName}:{r}")); - } - return results.ToArray(); - } - - /// - /// Returns rows from requested tables formatted to facilitate testing. - /// If the table did not exist in the database, its list will be null. - /// - /// - /// - /// - public static Dictionary> QueryDatabaseByTable(string path, string[] tables) - { - var results = new Dictionary>(); - - if (tables?.Length > 0) - { - var sb = new StringBuilder(); - using (var db = new Database(path)) - { - foreach (var table in tables) - { - if (table == "_SummaryInformation") - { - var entries = new List(); - results.Add(table, entries); - - entries.Add($"Title\t{db.SummaryInfo.Title}"); - entries.Add($"Subject\t{db.SummaryInfo.Subject}"); - entries.Add($"Author\t{db.SummaryInfo.Author}"); - entries.Add($"Keywords\t{db.SummaryInfo.Keywords}"); - entries.Add($"Comments\t{db.SummaryInfo.Comments}"); - entries.Add($"Template\t{db.SummaryInfo.Template}"); - entries.Add($"CodePage\t{db.SummaryInfo.CodePage}"); - entries.Add($"PageCount\t{db.SummaryInfo.PageCount}"); - entries.Add($"WordCount\t{db.SummaryInfo.WordCount}"); - entries.Add($"CharacterCount\t{db.SummaryInfo.CharacterCount}"); - entries.Add($"Security\t{db.SummaryInfo.Security}"); - - continue; - } - - if (!db.IsTablePersistent(table)) - { - results.Add(table, null); - continue; - } - - var rows = new List(); - results.Add(table, rows); - - using (var view = db.OpenView("SELECT * FROM `{0}`", table)) - { - view.Execute(); - - Record record; - while ((record = view.Fetch()) != null) - { - sb.Clear(); - - using (record) - { - for (var i = 0; i < record.FieldCount; ++i) - { - if (i > 0) - { - sb.Append("\t"); - } - - sb.Append(record[i + 1]?.ToString()); - } - } - - rows.Add(sb.ToString()); - } - } - rows.Sort(); - } - } - } - - return results; - } - - public static CabFileInfo[] GetCabinetFiles(string path) - { - var cab = new CabInfo(path); - - var result = cab.GetFiles(); - - return result.Select(c => c).ToArray(); - } - - public static void ExtractStream(string path, string streamName, string outputPath) - { - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - - using (var db = new Database(path)) - using (var view = db.OpenView("SELECT `Data` FROM `_Streams` WHERE `Name` = '{0}'", streamName)) - { - view.Execute(); - - using (var record = view.Fetch()) - { - record.GetStream(1, outputPath); - } - } - } - - public static void ExtractSubStorage(string path, string subStorageName, string outputPath) - { - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - - using (var db = new Database(path)) - using (var view = db.OpenView("SELECT `Name`, `Data` FROM `_Storages` WHERE `Name` = '{0}'", subStorageName)) - { - view.Execute(); - - using (var record = view.Fetch()) - { - var name = record.GetString(1); - record.GetStream(2, outputPath); - } - } - } - - public static string[] GetSubStorageNames(string path) - { - var result = new List(); - - using (var db = new Database(path)) - using (var view = db.OpenView("SELECT `Name` FROM `_Storages`")) - { - view.Execute(); - - Record record; - while ((record = view.Fetch()) != null) - { - var name = record.GetString(1); - result.Add(name); - } - } - - result.Sort(); - return result.ToArray(); - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/RobocopyRunner.cs b/src/internal/WixBuildTools.TestSupport/RobocopyRunner.cs deleted file mode 100644 index 49d53351..00000000 --- a/src/internal/WixBuildTools.TestSupport/RobocopyRunner.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - public class RobocopyRunner : ExternalExecutable - { - private static readonly RobocopyRunner Instance = new RobocopyRunner(); - - private RobocopyRunner() : base("robocopy") { } - - public static ExternalExecutableResult Execute(string args) - { - return Instance.Run(args); - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/TestData.cs b/src/internal/WixBuildTools.TestSupport/TestData.cs deleted file mode 100644 index fc1ae4cc..00000000 --- a/src/internal/WixBuildTools.TestSupport/TestData.cs +++ /dev/null @@ -1,78 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.IO; - using System.Reflection; - using System.Runtime.CompilerServices; - - public class TestData - { - public static void CreateFile(string path, long size, bool fill = false) - { - // Ensure the directory exists. - path = Path.GetFullPath(path); - Directory.CreateDirectory(Path.GetDirectoryName(path)); - - using (var file = File.OpenWrite(path)) - { - if (fill) - { - var random = new Random(); - var bytes = new byte[4096]; - var generated = 0L; - - // Put fill bytes in the file so it doesn't compress trivially. - while (generated < size) - { - var generate = (int)Math.Min(size - generated, bytes.Length); - - random.NextBytes(bytes); - - file.Write(bytes, 0, generate); - - generated += generate; - } - } - else - { - file.SetLength(size); - } - } - } - - public static string Get(params string[] paths) - { - var localPath = Path.GetDirectoryName(new Uri(Assembly.GetCallingAssembly().CodeBase).LocalPath); - return Path.Combine(localPath, Path.Combine(paths)); - } - - public static string GetUnitTestLogsFolder([CallerFilePath] string path = "", [CallerMemberName] string method = "") - { - var startingPath = Path.GetDirectoryName(new Uri(Assembly.GetCallingAssembly().CodeBase).LocalPath); - var buildPath = startingPath; - - while (!String.IsNullOrEmpty(buildPath)) - { - var folderName = Path.GetFileName(buildPath); - if (String.Equals("build", folderName, StringComparison.OrdinalIgnoreCase)) - { - break; - } - - buildPath = Path.GetDirectoryName(buildPath); - } - - if (String.IsNullOrEmpty(buildPath)) - { - 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."); - } - - var testLogsFolder = Path.Combine(buildPath, "logs", "UnitTests", $"{Path.GetFileNameWithoutExtension(path)}_{method}"); - Directory.CreateDirectory(testLogsFolder); - - return testLogsFolder; - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/TestDataFolderFileSystem.cs b/src/internal/WixBuildTools.TestSupport/TestDataFolderFileSystem.cs deleted file mode 100644 index 15b7631d..00000000 --- a/src/internal/WixBuildTools.TestSupport/TestDataFolderFileSystem.cs +++ /dev/null @@ -1,42 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - - /// - /// This class builds on top of DisposableFileSystem - /// to make it easy to write a test that needs a whole folder of test data copied to a temp location - /// that will automatically be cleaned up at the end of the test. - /// - public class TestDataFolderFileSystem : IDisposable - { - private DisposableFileSystem fileSystem; - - public string BaseFolder { get; private set; } - - public void Dispose() - { - this.fileSystem?.Dispose(); - } - - public void Initialize(string sourceDirectoryPath) - { - if (this.fileSystem != null) - { - throw new InvalidOperationException(); - } - this.fileSystem = new DisposableFileSystem(); - - this.BaseFolder = this.fileSystem.GetFolder(); - - RobocopyFolder(sourceDirectoryPath, this.BaseFolder); - } - - public static ExternalExecutableResult RobocopyFolder(string sourceFolderPath, string destinationFolderPath) - { - var args = $"\"{sourceFolderPath}\" \"{destinationFolderPath}\" /E /R:1 /W:1"; - return RobocopyRunner.Execute(args); - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/VswhereRunner.cs b/src/internal/WixBuildTools.TestSupport/VswhereRunner.cs deleted file mode 100644 index 0197e125..00000000 --- a/src/internal/WixBuildTools.TestSupport/VswhereRunner.cs +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.IO; - - public class VswhereRunner : ExternalExecutable - { - private static readonly string VswhereRelativePath = @"Microsoft Visual Studio\Installer\vswhere.exe"; - - private static readonly object InitLock = new object(); - private static bool Initialized; - private static VswhereRunner Instance; - - public static ExternalExecutableResult Execute(string args, bool mergeErrorIntoOutput = false) => - InitAndExecute(args, mergeErrorIntoOutput); - - private static ExternalExecutableResult InitAndExecute(string args, bool mergeErrorIntoOutput) - { - lock (InitLock) - { - if (!Initialized) - { - Initialized = true; - var vswherePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), VswhereRelativePath); - if (!File.Exists(vswherePath)) - { - throw new InvalidOperationException($"Failed to find vswhere at: {vswherePath}"); - } - - Instance = new VswhereRunner(vswherePath); - } - } - - return Instance.Run(args, mergeErrorIntoOutput); - } - - private VswhereRunner(string exePath) : base(exePath) { } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/WixBuildTools.TestSupport.csproj b/src/internal/WixBuildTools.TestSupport/WixBuildTools.TestSupport.csproj deleted file mode 100644 index 4e1c3c26..00000000 --- a/src/internal/WixBuildTools.TestSupport/WixBuildTools.TestSupport.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - netstandard2.0;net472 - true - embedded - true - true - $(NoWarn);CS1591 - false - true - - - - - - - - - - - - - diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkipTestException.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkipTestException.cs deleted file mode 100644 index bd7d23f9..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkipTestException.cs +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport.XunitExtensions -{ - using System; - - public class SkipTestException : Exception - { - public SkipTestException(string reason) - : base(reason) - { - - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactAttribute.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactAttribute.cs deleted file mode 100644 index 4974d489..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactAttribute.cs +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport.XunitExtensions -{ - using Xunit; - using Xunit.Sdk; - - // https://github.com/xunit/samples.xunit/blob/5dc1d35a63c3394a8678ac466b882576a70f56f6/DynamicSkipExample - [XunitTestCaseDiscoverer("WixBuildTools.TestSupport.XunitExtensions.SkippableFactDiscoverer", "WixBuildTools.TestSupport")] - public class SkippableFactAttribute : FactAttribute - { - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactDiscoverer.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactDiscoverer.cs deleted file mode 100644 index b692c912..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactDiscoverer.cs +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport.XunitExtensions -{ - using System.Collections.Generic; - using Xunit.Abstractions; - using Xunit.Sdk; - - public class SkippableFactDiscoverer : IXunitTestCaseDiscoverer - { - private IMessageSink DiagnosticMessageSink { get; } - - public SkippableFactDiscoverer(IMessageSink diagnosticMessageSink) - { - this.DiagnosticMessageSink = diagnosticMessageSink; - } - - public IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute) - { - yield return new SkippableFactTestCase(this.DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), discoveryOptions.MethodDisplayOptionsOrDefault(), testMethod); - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactMessageBus.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactMessageBus.cs deleted file mode 100644 index 6d01889e..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactMessageBus.cs +++ /dev/null @@ -1,40 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport.XunitExtensions -{ - using System.Linq; - using Xunit.Abstractions; - using Xunit.Sdk; - - public class SkippableFactMessageBus : IMessageBus - { - private IMessageBus InnerBus { get; } - - public SkippableFactMessageBus(IMessageBus innerBus) - { - this.InnerBus = innerBus; - } - - public int DynamicallySkippedTestCount { get; private set; } - - public void Dispose() - { - } - - public bool QueueMessage(IMessageSinkMessage message) - { - if (message is ITestFailed testFailed) - { - var exceptionType = testFailed.ExceptionTypes.FirstOrDefault(); - if (exceptionType == typeof(SkipTestException).FullName) - { - ++this.DynamicallySkippedTestCount; - return this.InnerBus.QueueMessage(new TestSkipped(testFailed.Test, testFailed.Messages.FirstOrDefault())); - } - } - - // Nothing we care about, send it on its way - return this.InnerBus.QueueMessage(message); - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactTestCase.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactTestCase.cs deleted file mode 100644 index f13fec83..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactTestCase.cs +++ /dev/null @@ -1,40 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport.XunitExtensions -{ - using System; - using System.ComponentModel; - using System.Threading; - using System.Threading.Tasks; - using Xunit.Abstractions; - using Xunit.Sdk; - - public class SkippableFactTestCase : XunitTestCase - { - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")] - public SkippableFactTestCase() { } - - public SkippableFactTestCase(IMessageSink diagnosticMessageSink, TestMethodDisplay defaultMethodDisplay, TestMethodDisplayOptions defaultMethodDisplayOptions, ITestMethod testMethod, object[] testMethodArguments = null) - : base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod, testMethodArguments) - { - } - - public override async Task RunAsync(IMessageSink diagnosticMessageSink, - IMessageBus messageBus, - object[] constructorArguments, - ExceptionAggregator aggregator, - CancellationTokenSource cancellationTokenSource) - { - var skipMessageBus = new SkippableFactMessageBus(messageBus); - var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, constructorArguments, aggregator, cancellationTokenSource); - if (skipMessageBus.DynamicallySkippedTestCount > 0) - { - result.Failed -= skipMessageBus.DynamicallySkippedTestCount; - result.Skipped += skipMessageBus.DynamicallySkippedTestCount; - } - - return result; - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryAttribute.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryAttribute.cs deleted file mode 100644 index e026bb59..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryAttribute.cs +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport.XunitExtensions -{ - using Xunit; - using Xunit.Sdk; - - [XunitTestCaseDiscoverer("WixBuildTools.TestSupport.XunitExtensions.SkippableFactDiscoverer", "WixBuildTools.TestSupport")] - public class SkippableTheoryAttribute : TheoryAttribute - { - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryDiscoverer.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryDiscoverer.cs deleted file mode 100644 index cf4e2b43..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryDiscoverer.cs +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport.XunitExtensions -{ - using System.Collections.Generic; - using Xunit.Abstractions; - using Xunit.Sdk; - - public class SkippableTheoryDiscoverer : IXunitTestCaseDiscoverer - { - private IMessageSink DiagnosticMessageSink { get; } - private TheoryDiscoverer TheoryDiscoverer { get; } - - public SkippableTheoryDiscoverer(IMessageSink diagnosticMessageSink) - { - this.DiagnosticMessageSink = diagnosticMessageSink; - - this.TheoryDiscoverer = new TheoryDiscoverer(diagnosticMessageSink); - } - - public IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute) - { - var defaultMethodDisplay = discoveryOptions.MethodDisplayOrDefault(); - var defaultMethodDisplayOptions = discoveryOptions.MethodDisplayOptionsOrDefault(); - - // Unlike fact discovery, the underlying algorithm for theories is complex, so we let the theory discoverer - // do its work, and do a little on-the-fly conversion into our own test cases. - foreach (var testCase in this.TheoryDiscoverer.Discover(discoveryOptions, testMethod, factAttribute)) - { - if (testCase is XunitTheoryTestCase) - { - yield return new SkippableTheoryTestCase(this.DiagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testCase.TestMethod); - } - else - { - yield return new SkippableFactTestCase(this.DiagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testCase.TestMethod, testCase.TestMethodArguments); - } - } - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryTestCase.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryTestCase.cs deleted file mode 100644 index 3299fe7e..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryTestCase.cs +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport.XunitExtensions -{ - using System; - using System.ComponentModel; - using System.Threading; - using System.Threading.Tasks; - using Xunit.Abstractions; - using Xunit.Sdk; - - public class SkippableTheoryTestCase : XunitTheoryTestCase - { - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")] - public SkippableTheoryTestCase() { } - - public SkippableTheoryTestCase(IMessageSink diagnosticMessageSink, TestMethodDisplay defaultMethodDisplay, TestMethodDisplayOptions defaultMethodDisplayOptions, ITestMethod testMethod) - : base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod) - { - } - - public override async Task RunAsync(IMessageSink diagnosticMessageSink, - IMessageBus messageBus, - object[] constructorArguments, - ExceptionAggregator aggregator, - CancellationTokenSource cancellationTokenSource) - { - // Duplicated code from SkippableFactTestCase. I'm sure we could find a way to de-dup with some thought. - var skipMessageBus = new SkippableFactMessageBus(messageBus); - var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, constructorArguments, aggregator, cancellationTokenSource); - if (skipMessageBus.DynamicallySkippedTestCount > 0) - { - result.Failed -= skipMessageBus.DynamicallySkippedTestCount; - result.Skipped += skipMessageBus.DynamicallySkippedTestCount; - } - - return result; - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs deleted file mode 100644 index c703e90a..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs +++ /dev/null @@ -1,20 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using Xunit.Sdk; - - public class SpecificReturnCodeException : XunitException - { - public SpecificReturnCodeException(int hrExpected, int hr, string userMessage) - : base(String.Format("WixAssert.SpecificReturnCode() Failure\r\n" + - "Expected HRESULT: 0x{0:X8}\r\n" + - "Actual HRESULT: 0x{1:X8}\r\n" + - "Message: {2}", - hrExpected, hr, userMessage)) - { - this.HResult = hr; - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SucceededException.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SucceededException.cs deleted file mode 100644 index 704fba28..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SucceededException.cs +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using Xunit.Sdk; - - public class SucceededException : XunitException - { - public SucceededException(int hr, string userMessage) - : base(String.Format("WixAssert.Succeeded() Failure\r\n" + - "HRESULT: 0x{0:X8}\r\n" + - "Message: {1}", - hr, userMessage)) - { - this.HResult = hr; - } - } -} diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs deleted file mode 100644 index a8513bfb..00000000 --- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs +++ /dev/null @@ -1,201 +0,0 @@ -// 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. - -namespace WixBuildTools.TestSupport -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using System.Xml.Linq; - using WixBuildTools.TestSupport.XunitExtensions; - using Xunit; - using Xunit.Sdk; - - public class WixAssert : Assert - { - public static void CompareLineByLine(string[] expectedLines, string[] actualLines) - { - var lineNumber = 0; - - for (; lineNumber < expectedLines.Length && lineNumber < actualLines.Length; ++lineNumber) - { - WixAssert.StringEqual($"{lineNumber}: {expectedLines[lineNumber]}", $"{lineNumber}: {actualLines[lineNumber]}"); - } - - var additionalExpectedLines = expectedLines.Length > lineNumber ? String.Join(Environment.NewLine, expectedLines.Skip(lineNumber).Select((s, i) => $"{lineNumber + i}: {s}")) : $"Missing {actualLines.Length - lineNumber} lines"; - var additionalActualLines = actualLines.Length > lineNumber ? String.Join(Environment.NewLine, actualLines.Skip(lineNumber).Select((s, i) => $"{lineNumber + i}: {s}")) : $"Missing {expectedLines.Length - lineNumber} lines"; - - Assert.Equal(additionalExpectedLines, additionalActualLines, StringObjectEqualityComparer.InvariantCulture); - } - - public static void CompareXml(XContainer xExpected, XContainer xActual) - { - var expecteds = xExpected.Descendants().Select(x => $"{x.Name.LocalName}:{String.Join(",", x.Attributes().OrderBy(a => a.Name.LocalName).Select(a => $"{a.Name.LocalName}={a.Value}"))}"); - var actuals = xActual.Descendants().Select(x => $"{x.Name.LocalName}:{String.Join(",", x.Attributes().OrderBy(a => a.Name.LocalName).Select(a => $"{a.Name.LocalName}={a.Value}"))}"); - - CompareLineByLine(expecteds.OrderBy(s => s).ToArray(), actuals.OrderBy(s => s).ToArray()); - } - - public static void CompareXml(string expectedPath, string actualPath) - { - var expectedDoc = XDocument.Load(expectedPath, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo); - var actualDoc = XDocument.Load(actualPath, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo); - - CompareXml(expectedDoc, actualDoc); - } - - /// - /// Dynamically skips the test. - /// Requires that the test was marked with a fact attribute derived from - /// or - /// - public static void Skip(string message) - { - throw new SkipTestException(message); - } - - public static void SpecificReturnCode(int hrExpected, int hr, string format, params object[] formatArgs) - { - if (hrExpected != hr) - { - throw new SpecificReturnCodeException(hrExpected, hr, String.Format(format, formatArgs)); - } - } - - public static void Succeeded(int hr, string format, params object[] formatArgs) - { - if (0 > hr) - { - throw new SucceededException(hr, String.Format(format, formatArgs)); - } - } - - public static void StringCollectionEmpty(IList collection) - { - if (collection.Count > 0) - { - Assert.True(false, $"The collection was expected to be empty, but instead was [{Environment.NewLine}\"{String.Join($"\", {Environment.NewLine}\"", collection)}\"{Environment.NewLine}]"); - } - } - - public static void StringEqual(string expected, string actual, bool ignoreCase = false) - { - WixStringEqualException.ThrowIfNotEqual(expected, actual, ignoreCase); - } - - public static void NotStringEqual(string expected, string actual, bool ignoreCase = false) - { - var comparer = ignoreCase ? StringObjectEqualityComparer.InvariantCultureIgnoreCase : StringObjectEqualityComparer.InvariantCulture; - Assert.NotEqual(expected, actual, comparer); - } - - // There appears to have been a bug in VC++, which might or might not have been partially - // or completely corrected. It was unable to disambiguate a call to: - // Xunit::Assert::Throws(System::Type^, System::Action^) - // from a call to: - // Xunit::Assert::Throws(System::Type^, System::Func^) - // that implicitly ignores its return value. - // - // The ambiguity may have been reported by some versions of the compiler and not by others. - // Some versions of the compiler may not have emitted any code in this situation, making it - // appear that the test has passed when, in fact, it hasn't been run. - // - // This situation is not an issue for C#. - // - // The following method is used to isolate DUtilTests in order to overcome the above problem. - - /// - /// This shim allows C++/CLR code to call the Xunit method with the same signature - /// without getting an ambiguous overload error. If the specified test code - /// fails to generate an exception of the exact specified type, an assertion - /// exception is thrown. Otherwise, execution flow proceeds as normal. - /// - /// The type name of the expected exception. - /// An Action delegate to run the test code. - public static new void Throws(System.Action testCode) - where T : System.Exception - { - Xunit.Assert.Throws(testCode); - } - - // This shim has been tested, but is not currently used anywhere. It was provided - // at the same time as the preceding shim because it involved the same overload - // resolution conflict. - - /// - /// This shim allows C++/CLR code to call the Xunit method with the same signature - /// without getting an ambiguous overload error. If the specified test code - /// fails to generate an exception of the exact specified type, an assertion - /// exception is thrown. Otherwise, execution flow proceeds as normal. - /// - /// The type object associated with exceptions of the expected type. - /// An Action delegate to run the test code. - /// An exception of a type other than the type specified, is such an exception is thrown. - public static new System.Exception Throws(System.Type exceptionType, System.Action testCode) - { - return Xunit.Assert.Throws(exceptionType, testCode); - } - } - - internal class StringObjectEqualityComparer : IEqualityComparer - { - public static readonly StringObjectEqualityComparer InvariantCultureIgnoreCase = new StringObjectEqualityComparer(true); - public static readonly StringObjectEqualityComparer InvariantCulture = new StringObjectEqualityComparer(false); - - private readonly StringComparer stringComparer; - - public StringObjectEqualityComparer(bool ignoreCase) - { - this.stringComparer = ignoreCase ? StringComparer.InvariantCultureIgnoreCase : StringComparer.InvariantCulture; - } - - public new bool Equals(object x, object y) - { - return this.stringComparer.Equals((string)x, (string)y); - } - - public int GetHashCode(object obj) - { - return this.stringComparer.GetHashCode((string)obj); - } - } - - public class WixStringEqualException : XunitException - { - public WixStringEqualException(string userMessage) : base(userMessage) { } - - public static void ThrowIfNotEqual(string expected, string actual, bool ignoreCase) - { - var comparer = ignoreCase ? StringObjectEqualityComparer.InvariantCultureIgnoreCase : StringObjectEqualityComparer.InvariantCulture; - if (comparer.Equals(expected, actual)) - { - return; - } - - var sbMessage = new StringBuilder(); - - try - { - Assert.Equal(expected, actual, ignoreCase); - } - catch (XunitException xe) - { - // If either string is not completely in the message, then make sure it gets in there. - if (!xe.Message.Contains(expected) || !xe.Message.Contains(actual)) - { - sbMessage.AppendLine(xe.Message); - sbMessage.AppendLine(); - sbMessage.AppendFormat("Expected: {0}", expected); - sbMessage.AppendLine(); - sbMessage.AppendFormat("Actual: {0}", actual); - } - else - { - throw; - } - } - - throw new WixStringEqualException(sbMessage.ToString()); - } - } -} -- cgit v1.2.3-55-g6feb