From f4d7df9189d3b8ab04c6ba9a94dc8ccff255224e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emek=20Vysok=C3=BD?= Date: Thu, 25 Mar 2021 11:20:53 +0100 Subject: [PATCH] Multi-target XHarness at .NET 3.1 and 6.0 (#516) - Adds the .NET 6.0 target to XHarness CLI - We need both first so that Helix SDK doesn't break, switch it there and remove 3.1 after - Changes libraries from `netstandard2.1` to `net6.0` and multitargets to both where needed (Apple, Android) - Fixes warnings that would break the build - WebClient is deprecated - Nullability issues - Resolves most of the build messages to clean the solution - Naming - Static methods where possible - Calling `GC.SuppressFinalize` - using `new ()` #456 --- azure-pipelines.yml | 2 +- eng/download-mlaunch.ps1 | 10 ++- eng/download-mlaunch.sh | 18 +++-- .../AdbRunner.cs | 23 +++--- .../Execution/AdbProcessManager.cs | 2 +- .../Microsoft.DotNet.XHarness.Android.csproj | 3 +- .../AppRunner.cs | 4 +- .../AppTester.cs | 2 +- .../ErrorKnowledgeBase.cs | 6 +- .../ExitCodeDetector.cs | 2 +- .../Microsoft.DotNet.XHarness.Apple.csproj | 3 +- .../AndroidGetDeviceCommandArguments.cs | 6 +- .../AndroidGetStateCommandArguments.cs | 2 +- .../Android/AndroidInstallCommandArguments.cs | 9 ++- .../Android/AndroidRunCommandArguments.cs | 5 +- .../Android/AndroidTestCommandArguments.cs | 6 +- .../AndroidUninstallCommandArguments.cs | 5 +- .../AppRunCommandArguments.cs | 2 +- .../Apple/AppleAppRunArguments.cs | 4 +- .../Apple/AppleGetStateCommandArguments.cs | 2 +- .../Apple/AppleTestCommandArguments.cs | 4 +- .../Apple/Simulators/FindCommandArguments.cs | 2 +- .../Simulators/InstallCommandArguments.cs | 2 +- .../Apple/Simulators/ListCommandArguments.cs | 2 +- .../Simulators/SimulatorsCommandArguments.cs | 5 +- .../CommandArguments/TestCommandArguments.cs | 4 +- .../WASM/WasmTestBrowserCommandArguments.cs | 3 +- .../WASM/WasmTestCommandArguments.cs | 5 +- .../Android/AndroidGetDeviceCommand.cs | 2 +- .../Commands/Android/AndroidInstallCommand.cs | 6 +- .../Commands/Android/AndroidRunCommand.cs | 6 +- .../Commands/Android/AndroidTestCommand.cs | 27 +++---- .../Android/AndroidUninstallCommand.cs | 2 +- .../Commands/Apple/AppleAppCommand.cs | 4 +- .../Commands/Apple/AppleGetStateCommand.cs | 4 +- .../Commands/Apple/AppleRunCommand.cs | 2 +- .../Commands/Apple/AppleTestCommand.cs | 2 +- .../Commands/Apple/Simulators/FindCommand.cs | 2 +- .../Apple/Simulators/InstallCommand.cs | 45 +++-------- .../Commands/Apple/Simulators/ListCommand.cs | 2 +- .../Apple/Simulators/SimulatorsCommand.cs | 75 ++++++++++++------- .../WASM/Browser/WasmBrowserTestRunner.cs | 23 +++--- .../WASM/Browser/WasmTestBrowserCommand.cs | 6 +- .../WASM/Browser/WasmTestWebServerStartup.cs | 7 +- .../Commands/WASM/JS/WasmTestCommand.cs | 4 +- .../WASM/WasmTestMessagesProcessor.cs | 8 +- .../Commands/XHarnessHelpCommand.cs | 2 +- .../Microsoft.DotNet.XHarness.CLI.csproj | 35 +++++---- .../CLI/Commands/XHarnessCommand.cs | 2 +- .../Execution/MacOSProcessManager.cs | 8 +- .../Execution/ProcessManager.cs | 9 ++- .../Logging/CallbackLog.cs | 1 + .../Logging/ConsoleLog.cs | 1 + .../Logging/MemoryLog.cs | 2 + .../Logging/NullLog.cs | 4 +- .../Microsoft.DotNet.XHarness.Common.csproj | 2 +- .../DefaultAndroidEntryPoint.cs | 12 +-- ...ness.DefaultAndroidEntryPoint.Xunit.csproj | 4 +- .../ApplicationOptions.cs | 6 +- ....DotNet.XHarness.TestRunners.Common.csproj | 4 +- .../FilterBuilder.cs | 1 + .../INUnitTestRunner.cs | 1 + ...t.DotNet.XHarness.TestRunners.NUnit.csproj | 4 +- .../NUnit3XmlOutputWriter.cs | 10 ++- .../NUnitTestRunner.cs | 1 + .../TestStatusExtensions.cs | 2 +- ...t.DotNet.XHarness.TestRunners.Xunit.csproj | 5 +- .../ThreadlessXunitTestRunner.cs | 2 +- .../WasmApplicationEntryPoint.cs | 5 +- .../XUnitFilter.cs | 4 +- .../XUnitTestRunner.cs | 8 +- .../Hardware/HardwareDeviceLoader.cs | 9 ++- .../Listeners/SimpleListener.cs | 6 +- .../Listeners/TcpTunnel.cs | 6 +- .../Listeners/TunnelBore.cs | 1 + .../Logging/AppInstallMonitorLog.cs | 1 + .../Logging/CaptureLog.cs | 1 + .../Logging/LogFile.cs | 1 + .../Logging/Logs.cs | 1 + ...icrosoft.DotNet.XHarness.iOS.Shared.csproj | 5 +- .../Utilities/Extensions.cs | 8 +- .../Utilities/ProjectFileExtensions.cs | 4 +- .../AdbRunnerTests.cs | 8 +- .../AppInstallerTests.cs | 6 +- .../AppRunnerTests.cs | 6 +- .../AppTesterTests.cs | 6 +- .../ErrorKnowledgeBaseTests.cs | 1 + .../ExitCodeDetectorTests.cs | 3 +- .../Logging/ConsoleLogTest.cs | 1 + .../NUnit/NUnit3XmlOutputWriterTests.cs | 6 +- .../AppBundleInformationParserTests.cs | 1 + .../CrashSnapshotReporterTests.cs | 6 +- .../Listeners/SimpleFileListenerTest.cs | 1 + .../Listeners/SimpleListenerFactoryTest.cs | 6 +- .../Logging/CaptureLogTest.cs | 1 + .../Logging/LogFileTest.cs | 1 + .../Logging/LogsTest.cs | 1 + .../TestReporterTests.cs | 1 + .../Utilities/ProjectFileExtensionsTests.cs | 2 +- .../XmlResultParserTests.cs | 2 +- 100 files changed, 349 insertions(+), 258 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c5bb0f05c3d8a..83416bf20f4b6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -80,7 +80,7 @@ stages: - task: ComponentGovernanceComponentDetection@0 displayName: Component Governance scan inputs: - ignoreDirectories: '$(Build.SourcesDirectory)/.packages,$(Build.SourcesDirectory)/artifacts/obj/Microsoft.DotNet.XHarness.CLI/$(_BuildConfig)/netcoreapp3.1/android-tools-unzipped' + ignoreDirectories: '$(Build.SourcesDirectory)/.packages,$(Build.SourcesDirectory)/artifacts/obj/Microsoft.DotNet.XHarness.CLI/$(_BuildConfig)/net6.0/android-tools-unzipped' - ${{ if eq(variables._RunAsPublic, True) }}: - stage: Build_OSX diff --git a/eng/download-mlaunch.ps1 b/eng/download-mlaunch.ps1 index 8403de844df1a..7f4798acfceef 100644 --- a/eng/download-mlaunch.ps1 +++ b/eng/download-mlaunch.ps1 @@ -4,17 +4,17 @@ Revision is cached in a temp dir and re-used for new builds. #> -[CmdletBinding(PositionalBinding=$false)] +[CmdletBinding(PositionalBinding = $false)] Param( [ValidateNotNullOrEmpty()] - [Parameter(Mandatory=$True)] + [Parameter(Mandatory = $True)] [string] $Commit, [ValidateNotNullOrEmpty()] - [Parameter(Mandatory=$True)] + [Parameter(Mandatory = $True)] [string] $TargetDir, - [switch] $RemoveSymbols=$False + [switch] $RemoveSymbols = $False ) function Copy-Mlaunch([string] $sourceDir, [string] $targetDir, [bool] $removeSymbols) { @@ -37,6 +37,8 @@ function Copy-Mlaunch([string] $sourceDir, [string] $targetDir, [bool] $removeSy New-Item -Path $TargetDir -ItemType Directory -ErrorAction SilentlyContinue +$ErrorActionPreference = 'Stop' + Write-Host "Getting mlaunch revision $commit into $TargetDir" $tagFile = Join-Path $TargetDir "$commit.tag" diff --git a/eng/download-mlaunch.sh b/eng/download-mlaunch.sh index 49e0360e10c7e..2f1cecfd20017 100755 --- a/eng/download-mlaunch.sh +++ b/eng/download-mlaunch.sh @@ -15,27 +15,29 @@ set -e source="${BASH_SOURCE[0]}" # resolve $source until the file is no longer a symlink while [[ -h "$source" ]]; do - scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + script_root="$( cd -P "$( dirname "$source" )" && pwd )" source="$(readlink "$source")" # if $source was a relative symlink, we need to resolve it relative to the path where the # symlink file was located - [[ $source != /* ]] && source="$scriptroot/$source" + [[ $source != /* ]] && source="$script_root/$source" done -scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" -. "$scriptroot/common/tools.sh" +script_root="$( cd -P "$( dirname "$source" )" && pwd )" + +# shellcheck source=./common/tools.sh +source "$script_root/common/tools.sh" copy_mlaunch () { # Copy mlaunch to the target folder - cp -Rv $1 $2 + cp -Rv "$1" "$2" # Clean what we don't need rm -rf "$2/lib/mlaunch/mlaunch.app/Contents/MacOS/mlaunch.dSYM" if [ "$3" = true ]; then echo "Removing debug symbols" - rm -v $2/lib/mlaunch/mlaunch.app/Contents/MonoBundle/*.pdb - rm -v $2/lib/mlaunch/mlaunch.app/Contents/MonoBundle/*.mdb + rm -v "$2"/lib/mlaunch/mlaunch.app/Contents/MonoBundle/*.pdb + rm -v "$2"/lib/mlaunch/mlaunch.app/Contents/MonoBundle/*.mdb fi } @@ -44,7 +46,7 @@ target_dir="$artifacts_dir/mlaunch" remove_symbols=false while (($# > 0)); do - lowerI="$(echo $1 | awk '{print tolower($0)}')" + lowerI="$(echo "$1" | awk '{print tolower($0)}')" case $lowerI in --commit) shift diff --git a/src/Microsoft.DotNet.XHarness.Android/AdbRunner.cs b/src/Microsoft.DotNet.XHarness.Android/AdbRunner.cs index 9b6e02cb12fba..a07680fb31918 100644 --- a/src/Microsoft.DotNet.XHarness.Android/AdbRunner.cs +++ b/src/Microsoft.DotNet.XHarness.Android/AdbRunner.cs @@ -25,9 +25,11 @@ public class AdbRunner private readonly string _absoluteAdbExePath; private readonly ILogger _log; private readonly IAdbProcessManager _processManager; - private readonly Dictionary CommandList = new Dictionary{ - { "architecture", "shell getprop ro.product.cpu.abi"}, - { "app", "shell pm list packages -3"} }; + private readonly Dictionary _commandList = new() + { + { "architecture", "shell getprop ro.product.cpu.abi"}, + { "app", "shell pm list packages -3"} + }; public AdbRunner(ILogger log, string adbExePath = "") : this(log, new AdbProcessManager(log), adbExePath) { } @@ -40,7 +42,7 @@ public AdbRunner(ILogger log, IAdbProcessManager processManager, string adbExePa _processManager = processManager ?? throw new ArgumentNullException(nameof(processManager)); // We need to find ADB.exe somewhere - string environmentPath = Environment.GetEnvironmentVariable(AdbEnvironmentVariableName); + string? environmentPath = Environment.GetEnvironmentVariable(AdbEnvironmentVariableName); if (!string.IsNullOrEmpty(environmentPath)) { _log.LogDebug($"Using {AdbEnvironmentVariableName} environment variable ({environmentPath}) for ADB path."); @@ -114,7 +116,7 @@ public void DumpAdbLog(string outputFilePath, string filterSpec = "") } else { - Directory.CreateDirectory(Path.GetDirectoryName(outputFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(outputFilePath) ?? throw new ArgumentNullException(nameof(outputFilePath))); File.WriteAllText(outputFilePath, result.StandardOutput); _log.LogInformation($"Wrote current ADB log to {outputFilePath}"); } @@ -199,7 +201,7 @@ public int InstallApk(string apkPath) _log.LogInformation($"Attempting to install {apkPath}: "); if (string.IsNullOrEmpty(apkPath)) { - throw new ArgumentNullException($"No value supplied for {nameof(apkPath)} "); + throw new ArgumentException($"No value supplied for {nameof(apkPath)} "); } if (!File.Exists(apkPath)) { @@ -330,7 +332,7 @@ public List PullFiles(string devicePath, string localPath) } else { - Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); + Directory.CreateDirectory(Path.GetDirectoryName(destinationPath) ?? throw new ArgumentException(nameof(destinationPath))); File.Move(filePath, destinationPath); copiedFiles.Add(destinationPath); } @@ -349,7 +351,7 @@ public List PullFiles(string devicePath, string localPath) { var devicesAndProperties = new Dictionary(); - string command = CommandList[property]; + string command = _commandList[property]; var result = RunAdbCommand("devices -l", TimeSpan.FromSeconds(30)); string[] standardOutputLines = result.StandardOutput.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries); @@ -445,7 +447,7 @@ public List PullFiles(string devicePath, string localPath) public Dictionary GetAllDevicesToUse(ILogger logger, string apkRequiredProperty, string propertyName) { - Dictionary allDevicesAndTheirProperties = new Dictionary(); + var allDevicesAndTheirProperties = new Dictionary(); try { allDevicesAndTheirProperties = GetAttachedDevicesWithProperties(propertyName); @@ -466,11 +468,12 @@ public Dictionary GetAllDevicesToUse(ILogger logger, string apkR .Where(kvp => !string.IsNullOrEmpty(kvp.Value) && kvp.Value.Split().Contains(apkRequiredProperty)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value) as Dictionary; - if (result.Count() == 0) + if (result.Count == 0) { // In this case, the enumeration worked, we found one or more devices, but nothing matched the APK's architecture; fail out. logger.LogError($"No devices with {propertyName} '{apkRequiredProperty}' was found among attached devices."); } + return result; } diff --git a/src/Microsoft.DotNet.XHarness.Android/Execution/AdbProcessManager.cs b/src/Microsoft.DotNet.XHarness.Android/Execution/AdbProcessManager.cs index 928ba0a4b4532..c5810ac1b017f 100644 --- a/src/Microsoft.DotNet.XHarness.Android/Execution/AdbProcessManager.cs +++ b/src/Microsoft.DotNet.XHarness.Android/Execution/AdbProcessManager.cs @@ -30,7 +30,7 @@ public ProcessExecutionResults Run(string adbExePath, string arguments, TimeSpan { CreateNoWindow = true, UseShellExecute = false, - WorkingDirectory = Path.GetDirectoryName(adbExePath), + WorkingDirectory = Path.GetDirectoryName(adbExePath) ?? throw new ArgumentNullException(nameof(adbExePath)), RedirectStandardOutput = true, RedirectStandardError = true, FileName = adbExePath, diff --git a/src/Microsoft.DotNet.XHarness.Android/Microsoft.DotNet.XHarness.Android.csproj b/src/Microsoft.DotNet.XHarness.Android/Microsoft.DotNet.XHarness.Android.csproj index 9099b52afe6d7..83a5635b64c73 100644 --- a/src/Microsoft.DotNet.XHarness.Android/Microsoft.DotNet.XHarness.Android.csproj +++ b/src/Microsoft.DotNet.XHarness.Android/Microsoft.DotNet.XHarness.Android.csproj @@ -1,8 +1,9 @@ - netstandard2.1 + netstandard2.1;net6.0 enable + 9.0 diff --git a/src/Microsoft.DotNet.XHarness.Apple/AppRunner.cs b/src/Microsoft.DotNet.XHarness.Apple/AppRunner.cs index 276c365ad70b2..b315f602483ab 100644 --- a/src/Microsoft.DotNet.XHarness.Apple/AppRunner.cs +++ b/src/Microsoft.DotNet.XHarness.Apple/AppRunner.cs @@ -285,7 +285,7 @@ private static MlaunchArguments GetCommonArguments(IEnumerable extraAppA return args; } - private MlaunchArguments GetSimulatorArguments( + private static MlaunchArguments GetSimulatorArguments( AppBundleInformation appInformation, ISimulatorDevice simulator, IEnumerable extraAppArguments, @@ -315,7 +315,7 @@ private MlaunchArguments GetSimulatorArguments( return args; } - private MlaunchArguments GetDeviceArguments( + private static MlaunchArguments GetDeviceArguments( AppBundleInformation appInformation, string deviceName, bool isWatchTarget, diff --git a/src/Microsoft.DotNet.XHarness.Apple/AppTester.cs b/src/Microsoft.DotNet.XHarness.Apple/AppTester.cs index f0c4caeaaa6ad..4b66c590b2200 100644 --- a/src/Microsoft.DotNet.XHarness.Apple/AppTester.cs +++ b/src/Microsoft.DotNet.XHarness.Apple/AppTester.cs @@ -60,7 +60,7 @@ public AppTester( _snapshotReporterFactory = snapshotReporterFactory ?? throw new ArgumentNullException(nameof(snapshotReporterFactory)); _captureLogFactory = captureLogFactory ?? throw new ArgumentNullException(nameof(captureLogFactory)); _deviceLogCapturerFactory = deviceLogCapturerFactory ?? throw new ArgumentNullException(nameof(deviceLogCapturerFactory)); - _testReporterFactory = reporterFactory ?? throw new ArgumentNullException(nameof(_testReporterFactory)); + _testReporterFactory = reporterFactory ?? throw new ArgumentNullException(nameof(reporterFactory)); _resultParser = resultParser ?? throw new ArgumentNullException(nameof(resultParser)); _mainLog = mainLog ?? throw new ArgumentNullException(nameof(mainLog)); _logs = logs ?? throw new ArgumentNullException(nameof(logs)); diff --git a/src/Microsoft.DotNet.XHarness.Apple/ErrorKnowledgeBase.cs b/src/Microsoft.DotNet.XHarness.Apple/ErrorKnowledgeBase.cs index c22951bb200d7..9ca159779fe91 100644 --- a/src/Microsoft.DotNet.XHarness.Apple/ErrorKnowledgeBase.cs +++ b/src/Microsoft.DotNet.XHarness.Apple/ErrorKnowledgeBase.cs @@ -13,7 +13,7 @@ namespace Microsoft.DotNet.XHarness.Apple { public class ErrorKnowledgeBase : IErrorKnowledgeBase { - private static readonly Dictionary s_testErrorMaps = new Dictionary + private static readonly Dictionary s_testErrorMaps = new() { ["Failed to communicate with the device"] = // Known issue but not a failure. ("Failed to communicate with the device. Please ensure the cable is properly connected, and try rebooting the device", null), @@ -28,9 +28,9 @@ public class ErrorKnowledgeBase : IErrorKnowledgeBase ("This application requires a newer version of MacOS", null), }; - private static readonly Dictionary s_buildErrorMaps = new Dictionary(); + private static readonly Dictionary s_buildErrorMaps = new(); - private static readonly Dictionary s_installErrorMaps = new Dictionary + private static readonly Dictionary s_installErrorMaps = new() { ["IncorrectArchitecture"] = ("IncorrectArchitecture: Failed to find matching device arch for the application", null), // known failure, but not an issue diff --git a/src/Microsoft.DotNet.XHarness.Apple/ExitCodeDetector.cs b/src/Microsoft.DotNet.XHarness.Apple/ExitCodeDetector.cs index a6d9222c980d3..307618f7c509a 100644 --- a/src/Microsoft.DotNet.XHarness.Apple/ExitCodeDetector.cs +++ b/src/Microsoft.DotNet.XHarness.Apple/ExitCodeDetector.cs @@ -23,7 +23,7 @@ public int DetectExitCode(AppBundleInformation appBundleInfo, IReadableLog syste { var line = reader.ReadLine(); - if (IsSignalLine(appBundleInfo, line)) + if (!string.IsNullOrEmpty(line) && IsSignalLine(appBundleInfo, line)) { var match = ExitCodeRegex.Match(line); diff --git a/src/Microsoft.DotNet.XHarness.Apple/Microsoft.DotNet.XHarness.Apple.csproj b/src/Microsoft.DotNet.XHarness.Apple/Microsoft.DotNet.XHarness.Apple.csproj index e078b5c6b0550..15815e0d81683 100644 --- a/src/Microsoft.DotNet.XHarness.Apple/Microsoft.DotNet.XHarness.Apple.csproj +++ b/src/Microsoft.DotNet.XHarness.Apple/Microsoft.DotNet.XHarness.Apple.csproj @@ -1,9 +1,10 @@ - netstandard2.1 + netstandard2.1;net6.0 enable true + 9.0 diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidGetDeviceCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidGetDeviceCommandArguments.cs index d6c36af54b5db..a179895f4074e 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidGetDeviceCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidGetDeviceCommandArguments.cs @@ -14,7 +14,7 @@ internal class AndroidGetDeviceCommandArguments : TestCommandArguments /// public string? DeviceArchitecture { get; set; } - protected override OptionSet GetTestCommandOptions() => new OptionSet + protected override OptionSet GetTestCommandOptions() => new() { { "device-arch=", "If specified, forces running on a device with given architecture (x86, x86_64, arm64-v8a or armeabi-v7a). Otherwise inferred from supplied APK", v => DeviceArchitecture = v @@ -23,8 +23,10 @@ internal class AndroidGetDeviceCommandArguments : TestCommandArguments public override void Validate() { + base.Validate(); + // Validate this field - AppPackagePath = AppPackagePath; + _ = AppPackagePath; } } } diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidGetStateCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidGetStateCommandArguments.cs index ba3d6eb273667..508c124f7675b 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidGetStateCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidGetStateCommandArguments.cs @@ -8,7 +8,7 @@ namespace Microsoft.DotNet.XHarness.CLI.CommandArguments.Android { internal class AndroidGetStateCommandArguments : GetStateCommandArguments { - protected override OptionSet GetCommandOptions() => new OptionSet(); + protected override OptionSet GetCommandOptions() => new(); public override void Validate() { diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidInstallCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidInstallCommandArguments.cs index ab8cf6712aa9e..58f023f8dd19e 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidInstallCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidInstallCommandArguments.cs @@ -25,7 +25,7 @@ public string PackageName /// public string? DeviceArchitecture { get; set; } - protected override OptionSet GetTestCommandOptions() => new OptionSet + protected override OptionSet GetTestCommandOptions() => new() { { "package-name=|p=", "Package name contained within the supplied APK", v => PackageName = v @@ -38,10 +38,11 @@ public string PackageName public override void Validate() { + base.Validate(); + // Validate this field - PackageName = PackageName; - AppPackagePath = AppPackagePath; - DeviceId = DeviceId; + _ = PackageName; + _ = AppPackagePath; } } } diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidRunCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidRunCommandArguments.cs index b337b1466945c..766a5428e36d6 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidRunCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidRunCommandArguments.cs @@ -38,7 +38,7 @@ public string PackageName /// public int ExpectedExitCode { get; set; } = (int)Common.CLI.ExitCode.SUCCESS; - protected override OptionSet GetTestCommandOptions() => new OptionSet + protected override OptionSet GetTestCommandOptions() => new() { { "device-out-folder=|dev-out=", "If specified, copy this folder recursively off the device to the path specified by the output directory", v => DeviceOutputFolder = RootPath(v) @@ -88,8 +88,7 @@ public override void Validate() base.Validate(); // Validate this field - PackageName = PackageName; - DeviceId = DeviceId; + _ = PackageName; } } } diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidTestCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidTestCommandArguments.cs index 4f735d728b6a3..449f0b54e0e00 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidTestCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidTestCommandArguments.cs @@ -42,7 +42,7 @@ public string PackageName /// public int ExpectedExitCode { get; set; } = (int)Common.CLI.ExitCode.SUCCESS; - protected override OptionSet GetTestCommandOptions() => new OptionSet + protected override OptionSet GetTestCommandOptions() => new() { { "device-arch=", "If specified, only run on a device with the listed architecture (x86, x86_64, arm64-v8a or armeabi-v7a). Otherwise infer from supplied APK", v => DeviceArchitecture = v @@ -91,8 +91,8 @@ public override void Validate() base.Validate(); // Validate this field - PackageName = PackageName; - AppPackagePath = AppPackagePath; + _ = PackageName; + _ = AppPackagePath; } } } diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidUninstallCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidUninstallCommandArguments.cs index 5181128c5165c..3e2d5fbfcdc0e 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidUninstallCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Android/AndroidUninstallCommandArguments.cs @@ -19,7 +19,7 @@ public string PackageName public string? DeviceId { get; set; } - protected override OptionSet GetTestCommandOptions() => new OptionSet + protected override OptionSet GetTestCommandOptions() => new() { { "package-name=|p=", "Package name contained within the supplied APK", v => PackageName = v @@ -33,8 +33,7 @@ public string PackageName public override void Validate() { // Validate this field - PackageName = PackageName; - DeviceId = DeviceId; + _ = PackageName; } } } diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/AppRunCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/AppRunCommandArguments.cs index 1c289ab835b23..7dc68426c3f74 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/AppRunCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/AppRunCommandArguments.cs @@ -43,7 +43,7 @@ public string OutputDirectory /// public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(15); - protected override OptionSet GetCommandOptions() => new OptionSet + protected override OptionSet GetCommandOptions() => new() { { "app|a=", "Path to already-packaged app", diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleAppRunArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleAppRunArguments.cs index 1b2dda335e002..1bd8815e80b6a 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleAppRunArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleAppRunArguments.cs @@ -41,7 +41,7 @@ internal abstract class AppleAppRunArguments : AppRunCommandArguments /// Environmental variables set when executing the application. /// public IReadOnlyCollection<(string, string)> EnvironmentalVariables => _environmentalVariables; - private readonly List<(string, string)> _environmentalVariables = new List<(string, string)>(); + private readonly List<(string, string)> _environmentalVariables = new(); /// /// Kills running simulator processes and removes any previous data before running. @@ -55,7 +55,7 @@ protected set { var testTargets = new List(); - foreach (var targetName in value ?? throw new ArgumentNullException("Targets cannot be empty")) + foreach (var targetName in value ?? throw new ArgumentException("Targets cannot be empty")) { try { diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleGetStateCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleGetStateCommandArguments.cs index e566b166b12b8..3a96a4bab9f6a 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleGetStateCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleGetStateCommandArguments.cs @@ -25,7 +25,7 @@ internal class AppleGetStateCommandArguments : XHarnessCommandArguments public bool UseJson { get; set; } = false; - protected override OptionSet GetCommandOptions() => new OptionSet + protected override OptionSet GetCommandOptions() => new() { { "mlaunch=", "Path to the mlaunch binary", v => MlaunchPath = RootPath(v) }, { "include-simulator-uuid", "Include the simulators UUID. Defaults to false.", v => ShowSimulatorsUUID = v != null }, diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleTestCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleTestCommandArguments.cs index 858a877780abb..84efa9c4986c5 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleTestCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/AppleTestCommandArguments.cs @@ -29,8 +29,8 @@ internal enum CommunicationChannel internal class AppleTestCommandArguments : AppleAppRunArguments { - private readonly List _singleMethodFilters = new List(); - private readonly List _classMethodFilters = new List(); + private readonly List _singleMethodFilters = new(); + private readonly List _classMethodFilters = new(); /// /// Methods to be included in the test run while all others are ignored. diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/FindCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/FindCommandArguments.cs index bd8e90f829d95..34865794e03c1 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/FindCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/FindCommandArguments.cs @@ -8,6 +8,6 @@ namespace Microsoft.DotNet.XHarness.CLI.CommandArguments.Apple.Simulators { internal class FindCommandArguments : SimulatorsCommandArguments { - protected override OptionSet GetAdditionalOptions() => new OptionSet(); + protected override OptionSet GetAdditionalOptions() => new(); } } diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/InstallCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/InstallCommandArguments.cs index 5579679060351..a000e2c6436fe 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/InstallCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/InstallCommandArguments.cs @@ -10,7 +10,7 @@ internal class InstallCommandArguments : SimulatorsCommandArguments { public bool Force { get; private set; } = false; - protected override OptionSet GetAdditionalOptions() => new OptionSet + protected override OptionSet GetAdditionalOptions() => new() { { "force", "Install again even if already installed", v => Force = true }, }; diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/ListCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/ListCommandArguments.cs index f3a46bfff37e8..4420db540bdd1 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/ListCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/ListCommandArguments.cs @@ -10,7 +10,7 @@ internal class ListCommandArguments : SimulatorsCommandArguments { public bool ListInstalledOnly { get; private set; } = false; - protected override OptionSet GetAdditionalOptions() => new OptionSet + protected override OptionSet GetAdditionalOptions() => new() { { "installed", "Lists installed simulators only", v => ListInstalledOnly = true }, }; diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/SimulatorsCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/SimulatorsCommandArguments.cs index 8a92fc3a23f59..330325918321e 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/SimulatorsCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Apple/Simulators/SimulatorsCommandArguments.cs @@ -24,7 +24,7 @@ public string XcodeRoot if (_xcodeRoot == null) { // Determine it automatically from xcode-select - _xcodeRoot = new MacOSProcessManager().XcodeRoot; + _xcodeRoot = MacOSProcessManager.DetectXcodePath(); } return _xcodeRoot; @@ -36,7 +36,8 @@ protected sealed override OptionSet GetCommandOptions() { var options = GetAdditionalOptions(); - options.Add("xcode=", "Path to where Xcode is located, e.g. /Application/Xcode114.app. If not set, xcode-select is used to determine the location",v => XcodeRoot = RootPath(v)); + options.Add("xcode=", "Path to where Xcode is located, e.g. /Application/Xcode114.app. If not set, xcode-select is used to determine the location", + v => XcodeRoot = RootPath(v)); return options; } diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/TestCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/TestCommandArguments.cs index 0234c4a6af8a2..8e1d8bffaef15 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/TestCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/TestCommandArguments.cs @@ -9,8 +9,8 @@ namespace Microsoft.DotNet.XHarness.CLI.CommandArguments { internal abstract class TestCommandArguments : AppRunCommandArguments { - private readonly List _singleMethodFilters = new List(); - private readonly List _classMethodFilters = new List(); + private readonly List _singleMethodFilters = new(); + private readonly List _classMethodFilters = new(); /// /// Methods to be included in the test run while all others are ignored. diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestBrowserCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestBrowserCommandArguments.cs index 69c9232bae7f2..05e1a62bb5a5f 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestBrowserCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestBrowserCommandArguments.cs @@ -45,7 +45,8 @@ internal class WasmTestBrowserCommandArguments : TestCommandArguments public string HTMLFile { get; set; } = "index.html"; public int ExpectedExitCode { get; set; } = (int)Common.CLI.ExitCode.SUCCESS; - protected override OptionSet GetTestCommandOptions() => new OptionSet{ + protected override OptionSet GetTestCommandOptions() => new() + { { "browser=|b=", "Specifies the browser to be used. Default is Chrome", v => Browser = ParseArgument("browser", v) }, diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestCommandArguments.cs index 66e0d96505888..764a852400a3c 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestCommandArguments.cs @@ -43,7 +43,8 @@ public JavaScriptEngine Engine public int ExpectedExitCode { get; set; } = (int)Common.CLI.ExitCode.SUCCESS; - protected override OptionSet GetTestCommandOptions() => new OptionSet{ + protected override OptionSet GetTestCommandOptions() => new() + { { "engine=|e=", "Specifies the JavaScript engine to be used", v => Engine = ParseArgument("engine", v) }, @@ -69,7 +70,7 @@ public JavaScriptEngine Engine public override void Validate() { base.Validate(); - Engine = Engine; + _ = Engine; } } } diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidGetDeviceCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidGetDeviceCommand.cs index 85cb73ef446ef..751e75bceef8f 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidGetDeviceCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidGetDeviceCommand.cs @@ -17,7 +17,7 @@ namespace Microsoft.DotNet.XHarness.CLI.Commands.Android { internal class AndroidGetDeviceCommand : XHarnessCommand { - private readonly AndroidGetDeviceCommandArguments _arguments = new AndroidGetDeviceCommandArguments(); + private readonly AndroidGetDeviceCommandArguments _arguments = new(); protected override XHarnessCommandArguments Arguments => _arguments; diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidInstallCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidInstallCommand.cs index 753ce2342e6ba..14fa471ae3f34 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidInstallCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidInstallCommand.cs @@ -14,7 +14,7 @@ namespace Microsoft.DotNet.XHarness.CLI.Commands.Android internal class AndroidInstallCommand : XHarnessCommand { - private readonly AndroidInstallCommandArguments _arguments = new AndroidInstallCommandArguments(); + private readonly AndroidInstallCommandArguments _arguments = new(); protected override XHarnessCommandArguments Arguments => _arguments; @@ -71,7 +71,7 @@ protected override Task InvokeInternal(ILogger logger) runner: runner)); } - public ExitCode InvokeHelper(ILogger logger, string apkPackageName, string appPackagePath, string? apkRequiredArchitecture, string? deviceId, AdbRunner runner) + public static ExitCode InvokeHelper(ILogger logger, string apkPackageName, string appPackagePath, string? apkRequiredArchitecture, string? deviceId, AdbRunner runner) { try { @@ -84,7 +84,7 @@ public ExitCode InvokeHelper(ILogger logger, string apkPackageName, string appPa // otherwise - from test command - apkRequiredArchitecture was set by user or .apk architecture deviceId ??= apkRequiredArchitecture != null ? runner.GetDeviceToUse(logger, apkRequiredArchitecture, "architecture") - : throw new ArgumentNullException("Required architecture not specified"); + : throw new ArgumentException("Required architecture not specified"); if (deviceId == null) { diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidRunCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidRunCommand.cs index c6ffa7badca19..87256e255750e 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidRunCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidRunCommand.cs @@ -21,7 +21,7 @@ internal class AndroidRunCommand : XHarnessCommand private const string ReturnCodeVariableName = "return-code"; private const string ProcessCrashedShortMessage = "Process crashed"; - private readonly AndroidRunCommandArguments _arguments = new AndroidRunCommandArguments(); + private readonly AndroidRunCommandArguments _arguments = new(); protected override XHarnessCommandArguments Arguments => _arguments; @@ -90,7 +90,7 @@ protected override Task InvokeInternal(ILogger logger) runner)); } - public ExitCode InvokeHelper( + public static ExitCode InvokeHelper( ILogger logger, string apkPackageName, string? instrumentationName, @@ -216,7 +216,7 @@ public ExitCode InvokeHelper( return ExitCode.GENERAL_FAILURE; } - private (Dictionary values, int exitCode) ParseInstrumentationOutputs(ILogger logger, string stdOut) + private static (Dictionary values, int exitCode) ParseInstrumentationOutputs(ILogger logger, string stdOut) { // If ADB.exe's output changes (which we control when we take updates in this repo), we'll need to fix this. string resultPrefix = "INSTRUMENTATION_RESULT:"; diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidTestCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidTestCommand.cs index c4ccc3c87e381..ee358d35096a2 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidTestCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidTestCommand.cs @@ -19,7 +19,7 @@ internal class AndroidTestCommand : XHarnessCommand { private const string ReturnCodeVariableName = "return-code"; - private readonly AndroidTestCommandArguments _arguments = new AndroidTestCommandArguments(); + private readonly AndroidTestCommandArguments _arguments = new(); protected override XHarnessCommandArguments Arguments => _arguments; @@ -72,12 +72,9 @@ protected override Task InvokeInternal(ILogger logger) string apkPackageName = _arguments.PackageName; string appPackagePath = _arguments.AppPackagePath; - var installer = new AndroidInstallCommand(); - var testRunner = new AndroidRunCommand(); - try { - var exitCode = installer.InvokeHelper( + var exitCode = AndroidInstallCommand.InvokeHelper( logger: logger, apkPackageName: apkPackageName, appPackagePath: appPackagePath, @@ -87,16 +84,16 @@ protected override Task InvokeInternal(ILogger logger) if (exitCode == ExitCode.SUCCESS) { - exitCode = testRunner.InvokeHelper( - logger: logger, - apkPackageName: apkPackageName, - instrumentationName: _arguments.InstrumentationName, - instrumentationArguments: _arguments.InstrumentationArguments, - outputDirectory: _arguments.OutputDirectory, - deviceOutputFolder: _arguments.DeviceOutputFolder, - timeout: _arguments.Timeout, - expectedExitCode: _arguments.ExpectedExitCode, - runner: runner); + exitCode = AndroidRunCommand.InvokeHelper( + logger: logger, + apkPackageName: apkPackageName, + instrumentationName: _arguments.InstrumentationName, + instrumentationArguments: _arguments.InstrumentationArguments, + outputDirectory: _arguments.OutputDirectory, + deviceOutputFolder: _arguments.DeviceOutputFolder, + timeout: _arguments.Timeout, + expectedExitCode: _arguments.ExpectedExitCode, + runner: runner); } runner.UninstallApk(apkPackageName); diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidUninstallCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidUninstallCommand.cs index faeff2aa683e5..4eb645f1ca0de 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidUninstallCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Android/AndroidUninstallCommand.cs @@ -15,7 +15,7 @@ namespace Microsoft.DotNet.XHarness.CLI.Commands.Android { internal class AndroidUninstallCommand : XHarnessCommand { - private readonly AndroidUninstallCommandArguments _arguments = new AndroidUninstallCommandArguments(); + private readonly AndroidUninstallCommandArguments _arguments = new(); protected override XHarnessCommandArguments Arguments => _arguments; diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleAppCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleAppCommand.cs index 9048c820974de..e49ef296e4652 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleAppCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleAppCommand.cs @@ -27,7 +27,7 @@ internal abstract class AppleAppCommand : XHarnessCommand { protected static readonly string s_mlaunchLldbConfigFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".mtouch-launch-with-lldb"); - protected readonly ErrorKnowledgeBase ErrorKnowledgeBase = new ErrorKnowledgeBase(); + protected readonly ErrorKnowledgeBase ErrorKnowledgeBase = new(); protected override XHarnessCommandArguments Arguments => iOSRunArguments; protected abstract AppleAppRunArguments iOSRunArguments { get; } @@ -65,7 +65,7 @@ protected abstract Task RunAppInternal( protected static bool IsLldbEnabled() => File.Exists(s_mlaunchLldbConfigFile); - protected void NotifyUserLldbCommand(ILogger logger, string line) + protected static void NotifyUserLldbCommand(ILogger logger, string line) { if (!line.Contains("mtouch-lldb-prep-cmds")) { diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleGetStateCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleGetStateCommand.cs index 45fd50d4cff99..a29dbfdf53074 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleGetStateCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleGetStateCommand.cs @@ -67,11 +67,11 @@ public SystemInfo(string machineName, string oSName, string oSVersion, string oS private const string SimulatorPrefix = "com.apple.CoreSimulator.SimDeviceType."; - private readonly AppleGetStateCommandArguments _arguments = new AppleGetStateCommandArguments(); + private readonly AppleGetStateCommandArguments _arguments = new(); protected override XHarnessCommandArguments Arguments => _arguments; - private async Task AsJson(SystemInfo info) + private static async Task AsJson(SystemInfo info) { var options = new JsonSerializerOptions { diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleRunCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleRunCommand.cs index eae3af163aa24..c3c3346e5668f 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleRunCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleRunCommand.cs @@ -25,7 +25,7 @@ internal class AppleRunCommand : AppleAppCommand { private const string CommandHelp = "Runs a given iOS/tvOS/watchOS/MacCatalyst application bundle in a target device/simulator and tries to detect exit code (might not work reliably across iOS versions)."; - private readonly AppleRunCommandArguments _arguments = new AppleRunCommandArguments(); + private readonly AppleRunCommandArguments _arguments = new(); protected override AppleAppRunArguments iOSRunArguments => _arguments; protected override string CommandUsage { get; } = "apple run [OPTIONS] [-- [RUNTIME ARGUMENTS]]"; diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleTestCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleTestCommand.cs index afa0de5a3e283..9414433814521 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleTestCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleTestCommand.cs @@ -26,7 +26,7 @@ internal class AppleTestCommand : AppleAppCommand { private const string CommandHelp = "Runs a given iOS/tvOS/watchOS/MacCatalyst test application bundle containing TestRunner in a target device/simulator"; - private readonly AppleTestCommandArguments _arguments = new AppleTestCommandArguments(); + private readonly AppleTestCommandArguments _arguments = new(); protected override string CommandUsage { get; } = "apple test [OPTIONS] [-- [RUNTIME ARGUMENTS]]"; protected override string CommandDescription { get; } = CommandHelp; diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/FindCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/FindCommand.cs index 1e15164d1a83f..5c155137c70a0 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/FindCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/FindCommand.cs @@ -20,7 +20,7 @@ internal class FindCommand : SimulatorsCommand protected override string CommandDescription => CommandHelp + Environment.NewLine + Environment.NewLine + SimulatorHelpString; - private readonly FindCommandArguments _arguments = new FindCommandArguments(); + private readonly FindCommandArguments _arguments = new(); protected override SimulatorsCommandArguments SimulatorsArguments => _arguments; public FindCommand() : base(CommandName, true, CommandHelp) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/InstallCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/InstallCommand.cs index 392649186df89..5c983c4230acb 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/InstallCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/InstallCommand.cs @@ -6,8 +6,7 @@ using System.Diagnostics; using System.IO; using System.Linq; -using System.Net; -using System.Threading; +using System.Net.Http; using System.Threading.Tasks; using System.Xml; using Microsoft.DotNet.XHarness.CLI.CommandArguments.Apple.Simulators; @@ -20,12 +19,13 @@ internal class InstallCommand : SimulatorsCommand { private const string CommandName = "install"; private const string CommandHelp = "Installs given simulators"; + private static readonly HttpClient s_client = new(); protected override string CommandUsage => CommandName + " [OPTIONS] [SIMULATOR] [SIMULATOR] .."; protected override string CommandDescription => CommandHelp + Environment.NewLine + Environment.NewLine + SimulatorHelpString; - private readonly InstallCommandArguments _arguments = new InstallCommandArguments(); + private readonly InstallCommandArguments _arguments = new(); protected override SimulatorsCommandArguments SimulatorsArguments => _arguments; public InstallCommand() : base(CommandName, true, CommandHelp) @@ -144,41 +144,18 @@ private async Task Install(Simulator simulator) if (download) { - var downloadDone = new ManualResetEvent(false); - var wc = new WebClient(); - long lastProgress = 0; var watch = Stopwatch.StartNew(); - wc.DownloadProgressChanged += (sender, progressArgs) => - { - var progress = progressArgs.BytesReceived * 100 / simulator.FileSize; - if (progress > lastProgress) - { - lastProgress = progress; - var duration = watch.Elapsed.TotalSeconds; - var speed = progressArgs.BytesReceived / duration; - var timeLeft = TimeSpan.FromSeconds((progressArgs.TotalBytesToReceive - progressArgs.BytesReceived) / speed); - - Logger.LogDebug($"Downloaded {progressArgs.BytesReceived:N0}/{simulator.FileSize:N0} bytes = " + - $"{progress}% in {duration:N1}s ({speed / 1024.0 / 1024.0:N1} MB/s; approximately " + - $"{new TimeSpan(timeLeft.Days, timeLeft.Hours, timeLeft.Minutes, timeLeft.Seconds)} left)"); - } - }; - wc.DownloadFileCompleted += (sender, completedArgs) => + using (var response = await s_client.GetAsync(simulator.Source)) + using (var fileStream = File.Create(downloadPath)) { - Logger.LogInformation($"Download completed in {watch.Elapsed.TotalSeconds}s"); - - if (completedArgs.Error != null) - { - Logger.LogError($" with error: {completedArgs.Error}"); - } - - downloadDone.Set(); - }; + await response.Content.CopyToAsync(fileStream); + } - await wc.DownloadFileTaskAsync(new Uri(simulator.Source), downloadPath); + watch.Stop(); - downloadDone.WaitOne(); + var size = new FileInfo(downloadPath).Length; + Logger.LogInformation($"Downloaded {size / 1024.0 / 1024.0:N1} MB in {(int)watch.Elapsed.TotalSeconds}s"); } var mount_point = Path.Combine(TempDirectory, filename + "-mount"); @@ -232,7 +209,7 @@ private async Task Install(Simulator simulator) // Add the install-location attribute to the pkg-info node var attr = packageInfoDoc.CreateAttribute("install-location"); attr.Value = simulator.InstallPrefix; - packageInfoDoc.SelectSingleNode("/pkg-info").Attributes.Append(attr); + packageInfoDoc.SelectSingleNode("/pkg-info")?.Attributes?.Append(attr); packageInfoDoc.Save(packageInfoPath); var fixed_path = Path.Combine(Path.GetDirectoryName(downloadPath)!, Path.GetFileNameWithoutExtension(downloadPath) + "-fixed.pkg"); diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/ListCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/ListCommand.cs index f3a0c1f5b627c..5c11260aca702 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/ListCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/ListCommand.cs @@ -20,7 +20,7 @@ internal class ListCommand : SimulatorsCommand protected override string CommandDescription => CommandHelp; - private readonly ListCommandArguments _arguments = new ListCommandArguments(); + private readonly ListCommandArguments _arguments = new(); protected override SimulatorsCommandArguments SimulatorsArguments => _arguments; public ListCommand() : base(CommandName, false, CommandHelp) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/SimulatorsCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/SimulatorsCommand.cs index cfbbd277cc490..f91a49ca9813a 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/SimulatorsCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/SimulatorsCommand.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Runtime.Serialization; using System.Threading.Tasks; using System.Xml; @@ -35,7 +36,8 @@ internal abstract class SimulatorsCommand : XHarnessCommand "e.g. com.apple.pkg.AppleTVSimulatorSDK14_2 or you can use the format in which you specify " + "apple targets for XHarness tests (ios-simulator, tvos-simulator, watchos-simulator)."; - private readonly MacOSProcessManager _processManager = new MacOSProcessManager(); + private static readonly HttpClient s_client = new(); + private readonly MacOSProcessManager _processManager = new(); protected ILogger Logger { get; set; } = null!; @@ -105,19 +107,19 @@ static string Replace(string value, Dictionary replacements) var simulators = new List(); var downloadables = doc.SelectNodes("//plist/dict/key[text()='downloadables']/following-sibling::array/dict"); - foreach (XmlNode? downloadable in downloadables) + foreach (XmlNode? downloadable in downloadables!) { if (downloadable == null) { continue; } - var nameNode = downloadable.SelectSingleNode("key[text()='name']/following-sibling::string"); - var versionNode = downloadable.SelectSingleNode("key[text()='version']/following-sibling::string"); - var sourceNode = downloadable.SelectSingleNode("key[text()='source']/following-sibling::string"); - var identifierNode = downloadable.SelectSingleNode("key[text()='identifier']/following-sibling::string"); + var nameNode = downloadable.SelectSingleNode("key[text()='name']/following-sibling::string") ?? throw new Exception("Name node not found"); + var versionNode = downloadable.SelectSingleNode("key[text()='version']/following-sibling::string") ?? throw new Exception("Version node not found"); + var sourceNode = downloadable.SelectSingleNode("key[text()='source']/following-sibling::string") ?? throw new Exception("Source node not found"); + var identifierNode = downloadable.SelectSingleNode("key[text()='identifier']/following-sibling::string") ?? throw new Exception("Identifier node not found"); var fileSizeNode = downloadable.SelectSingleNode("key[text()='fileSize']/following-sibling::integer|key[text()='fileSize']/following-sibling::real"); - var installPrefixNode = downloadable.SelectSingleNode("key[text()='userInfo']/following-sibling::dict/key[text()='InstallPrefix']/following-sibling::string"); + var installPrefixNode = downloadable.SelectSingleNode("key[text()='userInfo']/following-sibling::dict/key[text()='InstallPrefix']/following-sibling::string") ?? throw new Exception("InstallPrefix node not found"); var version = versionNode.InnerText; var versions = version.Split('.'); @@ -133,7 +135,7 @@ static string Replace(string value, Dictionary replacements) dict.Add(IDENTIFIER_PLACEHOLDER, identifier); - double.TryParse(fileSizeNode?.InnerText, out var parsedFileSize); + _ = double.TryParse(fileSizeNode?.InnerText, out var parsedFileSize); simulators.Add(new Simulator( name: Replace(nameNode.InnerText, dict), @@ -221,26 +223,11 @@ protected IEnumerable ParseSimulatorIds() if (!File.Exists(tmpfile)) { - var client = new WebClient(); - try - { - Logger.LogInformation($"Downloading '{uri}'"); - client.DownloadFile(uri, tmpfile); - } - catch (Exception ex) - { - // 403 means 404 - if (ex is WebException we && (we.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.Forbidden) - { - Logger.LogWarning($"Failed to download {url}: Not found"); // Apple's servers return a 403 if the file doesn't exist, which can be quite confusing, so show a better error. - } - else - { - Logger.LogWarning($"Failed to download {url}: {ex}"); - } - - return null; - } + await DownloadFile(url, tmpfile); + } + else + { + Logger.LogInformation($"File '{tmpfile}' already exists, skipped download"); } var (succeeded, xmlResult) = await ExecuteCommand("plutil", TimeSpan.FromSeconds(30), "-convert", "xml1", "-o", "-", tmpfile); @@ -252,6 +239,38 @@ protected IEnumerable ParseSimulatorIds() return xmlResult; } + private async Task DownloadFile(string url, string destinationPath) + { + try + { + Logger.LogInformation($"Downloading {url}..."); + + var downloadTask = s_client.GetStreamAsync(url); + using var fileStream = new FileStream(destinationPath, FileMode.Create); + using var bodyStream = await downloadTask; + await bodyStream.CopyToAsync(fileStream); + } + catch (HttpRequestException e) + { + // 403 means 404 +#if NETCOREAPP3_1 + { +#else + if (e.StatusCode == HttpStatusCode.Forbidden) + { + // Apple's servers return a 403 if the file doesn't exist, which can be quite confusing, so show a better error. + Logger.LogWarning($"Failed to download {url}: Not found"); + } + else + { +#endif + Logger.LogWarning($"Failed to download {url}: {e}"); + } + + throw; + } + } + private async Task<(string XcodeVersion, string XcodeUuid)> GetXcodeInformation() { var plistPath = Path.Combine(SimulatorsArguments.XcodeRoot, "Contents", "Info.plist"); diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmBrowserTestRunner.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmBrowserTestRunner.cs index d1769f5543755..5126f9f0e9bc7 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmBrowserTestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmBrowserTestRunner.cs @@ -38,15 +38,15 @@ internal class WasmBrowserTestRunner // Messages from selenium prepend the url, and location where the message originated // Eg. `foo` becomes `http://localhost:8000/xyz.js 0:12 "foo" - static readonly Regex s_consoleLogRegex = new Regex(@"^\s*[a-z]*://[^\s]+\s+\d+:\d+\s+""(.*)""\s*$", RegexOptions.Compiled); + static readonly Regex s_consoleLogRegex = new(@"^\s*[a-z]*://[^\s]+\s+\d+:\d+\s+""(.*)""\s*$", RegexOptions.Compiled); public WasmBrowserTestRunner(WasmTestBrowserCommandArguments arguments, IEnumerable passThroughArguments, WasmTestMessagesProcessor messagesProcessor, ILogger logger) { - this._arguments = arguments; - this._logger = logger; - this._passThroughArguments = passThroughArguments; - this._messagesProcessor = messagesProcessor; + _arguments = arguments; + _logger = logger; + _passThroughArguments = passThroughArguments; + _messagesProcessor = messagesProcessor; } public async Task RunTestsWithWebDriver(DriverService driverService, IWebDriver driver) @@ -239,7 +239,7 @@ private string BuildUrl(string webServerAddr) foreach (var arg in _passThroughArguments) { if (sb.Length > 0) - sb.Append("&"); + sb.Append('&'); sb.Append($"arg={HttpUtility.UrlEncode(arg)}"); } @@ -271,10 +271,13 @@ private static async Task StartWebServer(string contentRoot, Func() - .Addresses - .First(); + + var ipAddress = host.ServerFeatures + .Get()? + .Addresses + .FirstOrDefault(); + + return ipAddress ?? throw new InvalidOperationException("Failed to determine web server's IP address"); } } } diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmTestBrowserCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmTestBrowserCommand.cs index 14eff750ea429..3e28466be0db8 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmTestBrowserCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmTestBrowserCommand.cs @@ -30,7 +30,7 @@ internal class WasmTestBrowserCommand : XHarnessCommand { private const string CommandHelp = "Executes tests on WASM using a browser"; - private readonly WasmTestBrowserCommandArguments _arguments = new WasmTestBrowserCommandArguments(); + private readonly WasmTestBrowserCommandArguments _arguments = new(); protected TestCommandArguments TestArguments => _arguments; protected override string CommandUsage { get; } = "wasm test-browser [OPTIONS] -- [BROWSER OPTIONS]"; @@ -207,8 +207,10 @@ protected override async Task InvokeInternal(ILogger logger) driverService.EnableVerboseLogging = true; driverService.LogPath = Path.Combine(_arguments.OutputDirectory, $"{driverName}-{retry_num}.log"); - if (!(Activator.CreateInstance(typeof(TDriver), driverService, options, _arguments.Timeout) is TDriver driver)) + if (Activator.CreateInstance(typeof(TDriver), driverService, options, _arguments.Timeout) is not TDriver driver) + { throw new ArgumentException($"Failed to create instance of {typeof(TDriver)}"); + } return (driverService, driver); } diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmTestWebServerStartup.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmTestWebServerStartup.cs index 3f79a99c0a1da..2871fad2beac9 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmTestWebServerStartup.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/Browser/WasmTestWebServerStartup.cs @@ -7,7 +7,6 @@ using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System; @@ -18,11 +17,11 @@ namespace Microsoft.DotNet.XHarness.CLI.Commands.Wasm { public class WasmTestWebServerStartup { - private readonly IWebHostEnvironment s_hostingEnvironment; + private readonly IWebHostEnvironment _hostingEnvironment; public WasmTestWebServerStartup(IWebHostEnvironment hostingEnvironment) { - this.s_hostingEnvironment = hostingEnvironment; + _hostingEnvironment = hostingEnvironment; } public void Configure(IApplicationBuilder app, IOptionsMonitor optionsAccessor) @@ -37,7 +36,7 @@ public void Configure(IApplicationBuilder app, IOptionsMonitor _arguments; protected override string CommandUsage { get; } = "wasm test [OPTIONS] -- [ENGINE OPTIONS]"; @@ -61,7 +61,7 @@ protected override async Task InvokeInternal(ILogger logger) JavaScriptEngine.V8 => "v8", JavaScriptEngine.JavaScriptCore => "jsc", JavaScriptEngine.SpiderMonkey => "sm", - _ => throw new ArgumentException() + _ => throw new ArgumentException("Engine not set") }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/WasmTestMessagesProcessor.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/WasmTestMessagesProcessor.cs index 0deb1798dca66..1672e58e63230 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/WasmTestMessagesProcessor.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WASM/WasmTestMessagesProcessor.cs @@ -22,10 +22,10 @@ public class WasmTestMessagesProcessor public WasmTestMessagesProcessor(string xmlResultsFilePath, string stdoutFilePath, ILogger logger) { - this._xmlResultsFilePath = xmlResultsFilePath; - this._stdoutFileWriter = File.CreateText(stdoutFilePath); - this._stdoutFileWriter.AutoFlush = true; - this._logger = logger; + _xmlResultsFilePath = xmlResultsFilePath; + _stdoutFileWriter = File.CreateText(stdoutFilePath); + _stdoutFileWriter.AutoFlush = true; + _logger = logger; } public void Invoke(string message) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/XHarnessHelpCommand.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/XHarnessHelpCommand.cs index 701e89d7a25ac..fd4eee7757774 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/XHarnessHelpCommand.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/XHarnessHelpCommand.cs @@ -82,7 +82,7 @@ public override int Invoke(IEnumerable arguments) return (int)ExitCode.HELP_SHOWN; } - private void PrintCommandHelp(CommandSet commandSet, string? subcommand) + private static void PrintCommandHelp(CommandSet commandSet, string? subcommand) { if (subcommand != null) { diff --git a/src/Microsoft.DotNet.XHarness.CLI/Microsoft.DotNet.XHarness.CLI.csproj b/src/Microsoft.DotNet.XHarness.CLI/Microsoft.DotNet.XHarness.CLI.csproj index fd4fc3e91b527..45782f2f8f6d3 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Microsoft.DotNet.XHarness.CLI.csproj +++ b/src/Microsoft.DotNet.XHarness.CLI/Microsoft.DotNet.XHarness.CLI.csproj @@ -2,12 +2,13 @@ Exe - netcoreapp3.1 + netcoreapp3.1;net6.0 enable true true xharness Major + 9.0 CS8002; @@ -46,13 +47,28 @@ - - + + + + + + + + -RemoveSymbols + --remove-symbols + + + + + + + + @@ -75,17 +91,7 @@ - - - - -RemoveSymbols - --remove-symbols - - - - - - + true @@ -93,6 +99,5 @@ PreserveNewest - diff --git a/src/Microsoft.DotNet.XHarness.Common/CLI/Commands/XHarnessCommand.cs b/src/Microsoft.DotNet.XHarness.Common/CLI/Commands/XHarnessCommand.cs index 6323c0eae7ccf..192fb2476b12a 100644 --- a/src/Microsoft.DotNet.XHarness.Common/CLI/Commands/XHarnessCommand.cs +++ b/src/Microsoft.DotNet.XHarness.Common/CLI/Commands/XHarnessCommand.cs @@ -128,7 +128,7 @@ public sealed override int Invoke(IEnumerable arguments) protected abstract Task InvokeInternal(ILogger logger); - private ILoggerFactory CreateLoggerFactory(LogLevel verbosity) => LoggerFactory.Create(builder => + private static ILoggerFactory CreateLoggerFactory(LogLevel verbosity) => LoggerFactory.Create(builder => { builder .AddConsoleFormatter(options => { diff --git a/src/Microsoft.DotNet.XHarness.Common/Execution/MacOSProcessManager.cs b/src/Microsoft.DotNet.XHarness.Common/Execution/MacOSProcessManager.cs index 86e690866641e..a9c32c64df794 100644 --- a/src/Microsoft.DotNet.XHarness.Common/Execution/MacOSProcessManager.cs +++ b/src/Microsoft.DotNet.XHarness.Common/Execution/MacOSProcessManager.cs @@ -45,7 +45,7 @@ public Version XcodeVersion try { doc.Load(plistPath); - _xcode_version = Version.Parse(doc.SelectSingleNode("//key[text() = 'CFBundleShortVersionString']/following-sibling::string").InnerText); + _xcode_version = Version.Parse(doc.SelectSingleNode("//key[text() = 'CFBundleShortVersionString']/following-sibling::string")?.InnerText ?? throw new Exception("Failed to find the CFBundleShortVersionString property")); } catch (IOException) { @@ -75,9 +75,9 @@ public Task ExecuteXcodeCommandAsync(string executable, #endregion - #region Private methods + #region Static methods - private static string DetectXcodePath() + public static string DetectXcodePath() { using var process = new Process(); process.StartInfo.FileName = "xcode-select"; @@ -93,7 +93,7 @@ private static string DetectXcodePath() log, stdout, stderr, - (pid, signal) => kill(pid, signal), + (pid, signal) => _ = kill(pid, signal), (log, pid) => GetChildProcessIdsInternal(log, pid), timeout) .GetAwaiter().GetResult(); diff --git a/src/Microsoft.DotNet.XHarness.Common/Execution/ProcessManager.cs b/src/Microsoft.DotNet.XHarness.Common/Execution/ProcessManager.cs index 1a9d7fd931bb1..451ee60eff0f5 100644 --- a/src/Microsoft.DotNet.XHarness.Common/Execution/ProcessManager.cs +++ b/src/Microsoft.DotNet.XHarness.Common/Execution/ProcessManager.cs @@ -253,8 +253,8 @@ protected static async Task RunAsyncInternal( if (process.StartInfo.EnvironmentVariables != null) { - var currentEnvironment = Environment.GetEnvironmentVariables().Cast().ToDictionary(v => v.Key.ToString(), v => v.Value?.ToString(), StringComparer.Ordinal); - var processEnvironment = process.StartInfo.EnvironmentVariables.Cast().ToDictionary(v => v.Key.ToString(), v => v.Value?.ToString(), StringComparer.Ordinal); + var currentEnvironment = ToDictionary(Environment.GetEnvironmentVariables()); + var processEnvironment = ToDictionary(process.StartInfo.EnvironmentVariables); var allVariables = currentEnvironment.Keys.Union(processEnvironment.Keys).Distinct(); bool headerShown = false; @@ -392,6 +392,9 @@ void ProcessExited(object? sender, EventArgs ea) } } -#endregion + private static Dictionary ToDictionary(IEnumerable enumerable) => + enumerable.Cast().ToDictionary(v => v.Key.ToString()!, v => v.Value?.ToString(), StringComparer.Ordinal); + + #endregion } } diff --git a/src/Microsoft.DotNet.XHarness.Common/Logging/CallbackLog.cs b/src/Microsoft.DotNet.XHarness.Common/Logging/CallbackLog.cs index 61730e2d7d0e9..2df1ae79c6f30 100644 --- a/src/Microsoft.DotNet.XHarness.Common/Logging/CallbackLog.cs +++ b/src/Microsoft.DotNet.XHarness.Common/Logging/CallbackLog.cs @@ -23,6 +23,7 @@ public CallbackLog(Action onWrite) public override void Dispose() { + GC.SuppressFinalize(this); } public override void Flush() diff --git a/src/Microsoft.DotNet.XHarness.Common/Logging/ConsoleLog.cs b/src/Microsoft.DotNet.XHarness.Common/Logging/ConsoleLog.cs index bf6ccc1164fce..19ea8fc447b5e 100644 --- a/src/Microsoft.DotNet.XHarness.Common/Logging/ConsoleLog.cs +++ b/src/Microsoft.DotNet.XHarness.Common/Logging/ConsoleLog.cs @@ -40,6 +40,7 @@ public override void Flush() public override void Dispose() { + GC.SuppressFinalize(this); } } } diff --git a/src/Microsoft.DotNet.XHarness.Common/Logging/MemoryLog.cs b/src/Microsoft.DotNet.XHarness.Common/Logging/MemoryLog.cs index 78896e54901b1..ae50b734c4e2f 100644 --- a/src/Microsoft.DotNet.XHarness.Common/Logging/MemoryLog.cs +++ b/src/Microsoft.DotNet.XHarness.Common/Logging/MemoryLog.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.IO; using System.Text; @@ -28,6 +29,7 @@ public override void Flush() public override void Dispose() { + GC.SuppressFinalize(this); } public override string ToString() => _captured.ToString(); diff --git a/src/Microsoft.DotNet.XHarness.Common/Logging/NullLog.cs b/src/Microsoft.DotNet.XHarness.Common/Logging/NullLog.cs index a09a7599666e5..a075a636ad967 100644 --- a/src/Microsoft.DotNet.XHarness.Common/Logging/NullLog.cs +++ b/src/Microsoft.DotNet.XHarness.Common/Logging/NullLog.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Text; namespace Microsoft.DotNet.XHarness.Common.Logging @@ -18,6 +19,7 @@ public class NullLog : ILog public void Dispose() { + GC.SuppressFinalize(this); } public void Flush() @@ -36,7 +38,7 @@ public void WriteLine(string value) { } - public void WriteLine(StringBuilder value) + public static void WriteLine(StringBuilder value) { } diff --git a/src/Microsoft.DotNet.XHarness.Common/Microsoft.DotNet.XHarness.Common.csproj b/src/Microsoft.DotNet.XHarness.Common/Microsoft.DotNet.XHarness.Common.csproj index a3e6a6479938b..66be32f35a310 100644 --- a/src/Microsoft.DotNet.XHarness.Common/Microsoft.DotNet.XHarness.Common.csproj +++ b/src/Microsoft.DotNet.XHarness.Common/Microsoft.DotNet.XHarness.Common.csproj @@ -1,7 +1,7 @@  - netstandard2.0;netcoreapp3.1 + netstandard2.0;net6.0 true enable diff --git a/src/Microsoft.DotNet.XHarness.InstrumentationBase.Xunit/DefaultAndroidEntryPoint.cs b/src/Microsoft.DotNet.XHarness.InstrumentationBase.Xunit/DefaultAndroidEntryPoint.cs index c845cbe71838b..7b59b9372b2f0 100644 --- a/src/Microsoft.DotNet.XHarness.InstrumentationBase.Xunit/DefaultAndroidEntryPoint.cs +++ b/src/Microsoft.DotNet.XHarness.InstrumentationBase.Xunit/DefaultAndroidEntryPoint.cs @@ -28,8 +28,8 @@ namespace Microsoft.DotNet.XHarness.DefaultAndroidEntryPoint.Xunit public class DefaultAndroidEntryPoint : AndroidApplicationEntryPoint { private readonly string _resultsPath; - private readonly string _excludeCategoriesDir; - private readonly string _excludeCategoriesFile; + private readonly string? _excludeCategoriesDir; + private readonly string? _excludeCategoriesFile; private readonly Dictionary _parsedArguments; public const string ResultsFileArgumentName = "results-file-name"; @@ -41,8 +41,8 @@ public class DefaultAndroidEntryPoint : AndroidApplicationEntryPoint public const string ExcludeClassArgumentName = "exclude-class"; public const string IncludeClassArgumentName = "include-class"; - protected override string IgnoreFilesDirectory => _excludeCategoriesDir; - protected override string IgnoredTraitsFilePath => _excludeCategoriesFile; + protected override string? IgnoreFilesDirectory => _excludeCategoriesDir; + protected override string? IgnoredTraitsFilePath => _excludeCategoriesFile; public DefaultAndroidEntryPoint(string resultsPath, Dictionary optionalBundle) { @@ -83,7 +83,7 @@ protected override void TerminateWithSuccess() { } - private void ConfigureFilters(string? filter, Action filterMethod, bool isExcluded) + private static void ConfigureFilters(string? filter, Action filterMethod, bool isExcluded) { if (filter != null) { @@ -98,7 +98,7 @@ protected override TestRunner GetTestRunner(LogWriter logWriter) { var testRunner = base.GetTestRunner(logWriter); - (string Filter, Action FilterMethod, bool IsExcluded)[] filters = + (string? Filter, Action FilterMethod, bool IsExcluded)[] filters = { (_parsedArguments.GetValueOrDefault(ExcludeMethodArgumentName), testRunner.SkipMethod, true), (_parsedArguments.GetValueOrDefault(ExcludeClassArgumentName), testRunner.SkipClass, true), diff --git a/src/Microsoft.DotNet.XHarness.InstrumentationBase.Xunit/Microsoft.DotNet.XHarness.DefaultAndroidEntryPoint.Xunit.csproj b/src/Microsoft.DotNet.XHarness.InstrumentationBase.Xunit/Microsoft.DotNet.XHarness.DefaultAndroidEntryPoint.Xunit.csproj index b498ab6a64634..597615417d38f 100644 --- a/src/Microsoft.DotNet.XHarness.InstrumentationBase.Xunit/Microsoft.DotNet.XHarness.DefaultAndroidEntryPoint.Xunit.csproj +++ b/src/Microsoft.DotNet.XHarness.InstrumentationBase.Xunit/Microsoft.DotNet.XHarness.DefaultAndroidEntryPoint.Xunit.csproj @@ -2,7 +2,7 @@ true - netstandard2.1 + net6.0 enable Microsoft.DotNet.XHarness.TestRunners.Xunit Library @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Common/ApplicationOptions.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Common/ApplicationOptions.cs index cd1691916ebdb..47ca125617fdf 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Common/ApplicationOptions.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Common/ApplicationOptions.cs @@ -18,9 +18,9 @@ internal enum XmlMode internal class ApplicationOptions { - public static ApplicationOptions Current = new ApplicationOptions(); - private readonly List _singleMethodFilters = new List(); - private readonly List _classMethodFilters = new List(); + public static ApplicationOptions Current = new(); + private readonly List _singleMethodFilters = new(); + private readonly List _classMethodFilters = new(); public ApplicationOptions() { diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Common/Microsoft.DotNet.XHarness.TestRunners.Common.csproj b/src/Microsoft.DotNet.XHarness.TestRunners.Common/Microsoft.DotNet.XHarness.TestRunners.Common.csproj index dd145f662f860..352979ed4afbe 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Common/Microsoft.DotNet.XHarness.TestRunners.Common.csproj +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Common/Microsoft.DotNet.XHarness.TestRunners.Common.csproj @@ -1,11 +1,11 @@ + netstandard2.1;net6.0 true - netstandard2.1;netcoreapp3.1 CS8002; - Microsoft.DotNet.XHarness.TestRunners.Common + 9.0 diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/FilterBuilder.cs b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/FilterBuilder.cs index ad80a2d149557..aa87dbf5ed3c4 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/FilterBuilder.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/FilterBuilder.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using NUnit.Engine; +#nullable enable namespace Microsoft.DotNet.XHarness.TestRunners.NUnit { /// diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/INUnitTestRunner.cs b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/INUnitTestRunner.cs index 63857e270b651..0b092dbdde97e 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/INUnitTestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/INUnitTestRunner.cs @@ -4,6 +4,7 @@ using Microsoft.DotNet.XHarness.TestRunners.Common; +#nullable enable namespace Microsoft.DotNet.XHarness.TestRunners.NUnit { /// diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/Microsoft.DotNet.XHarness.TestRunners.NUnit.csproj b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/Microsoft.DotNet.XHarness.TestRunners.NUnit.csproj index 593a8516cb346..b1c78c2260c56 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/Microsoft.DotNet.XHarness.TestRunners.NUnit.csproj +++ b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/Microsoft.DotNet.XHarness.TestRunners.NUnit.csproj @@ -1,11 +1,11 @@ + netstandard2.1;net6.0 true - enable - netstandard2.1;netcoreapp3.1 CS8002; + disable diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnit3XmlOutputWriter.cs b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnit3XmlOutputWriter.cs index 0f563e8b088dd..8aad80f2374d2 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnit3XmlOutputWriter.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnit3XmlOutputWriter.cs @@ -10,6 +10,7 @@ using Microsoft.DotNet.XHarness.Common; using NUnit.Framework.Internal; +#nullable enable namespace Microsoft.DotNet.XHarness.TestRunners.NUnit { /// @@ -120,6 +121,11 @@ private void WriteEnvironmentElement() private void WriteResultElement(IResultSummary result) { + if (_xmlWriter == null) // should never happen, would mean a programmer's error + { + throw new InvalidOperationException("Null writer"); + } + // much simpler than in other writers, we just need to get the child nodes of each of the test-run and write // them. NUnit3 already gave us the xml we need to use foreach (var testRun in result) @@ -127,12 +133,12 @@ private void WriteResultElement(IResultSummary result) for (var i = 0; i < testRun.Result.ChildNodes.Count; i++) { var node = testRun.Result.ChildNodes[i]; - if (node.Name == "environment") + if (node?.Name == "environment") { continue; } - node.WriteTo(_xmlWriter); + node?.WriteTo(_xmlWriter); } } } diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnitTestRunner.cs b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnitTestRunner.cs index e0d2742106452..af2edd4a0fc7a 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnitTestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnitTestRunner.cs @@ -12,6 +12,7 @@ using Microsoft.DotNet.XHarness.TestRunners.Common; using NUnit.Engine; +#nullable enable namespace Microsoft.DotNet.XHarness.TestRunners.NUnit { internal class NUnitTestRunner : TestRunner, INUnitTestRunner diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/TestStatusExtensions.cs b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/TestStatusExtensions.cs index b14e27ff17e11..18239698721f5 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/TestStatusExtensions.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/TestStatusExtensions.cs @@ -36,7 +36,7 @@ internal static class TestStatusExtensions TestStatus.Skipped => "Skip", _ => "Fail", }, - _ => throw new ArgumentOutOfRangeException(), + _ => throw new ArgumentOutOfRangeException(nameof(status)), }; } } diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/Microsoft.DotNet.XHarness.TestRunners.Xunit.csproj b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/Microsoft.DotNet.XHarness.TestRunners.Xunit.csproj index bce8cdccf7861..1444cf429d324 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/Microsoft.DotNet.XHarness.TestRunners.Xunit.csproj +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/Microsoft.DotNet.XHarness.TestRunners.Xunit.csproj @@ -1,9 +1,10 @@ + netstandard2.1;net6.0 true - netstandard2.1;netcoreapp3.1 - Microsoft.DotNet.XHarness.TestRunners.Xunit + disable + 9.0 diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/ThreadlessXunitTestRunner.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/ThreadlessXunitTestRunner.cs index b1d5e317aa121..de3fe52dc1301 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/ThreadlessXunitTestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/ThreadlessXunitTestRunner.cs @@ -19,7 +19,7 @@ namespace Microsoft.DotNet.XHarness.TestRunners.Xunit { internal class ThreadlessXunitTestRunner { - public async Task Run(string assemblyFileName, bool printXml, XunitFilters filters) + public static async Task Run(string assemblyFileName, bool printXml, XunitFilters filters) { var configuration = new TestAssemblyConfiguration() { ShadowCopy = false, ParallelizeAssembly = false, ParallelizeTestCollections = false, MaxParallelThreads = 1, PreEnumerateTheories = false }; var discoveryOptions = TestFrameworkOptions.ForDiscovery(configuration); diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmApplicationEntryPoint.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmApplicationEntryPoint.cs index 16da134bf5518..a93b502908f18 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmApplicationEntryPoint.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmApplicationEntryPoint.cs @@ -22,7 +22,6 @@ public abstract class WasmApplicationEntryPoint public async Task Run() { - var testRunner = new ThreadlessXunitTestRunner(); var filters = new XunitFilters(); foreach (var trait in ExcludedTraits) ParseEqualSeparatedArgument(filters.ExcludedTraits, trait); @@ -31,12 +30,12 @@ public async Task Run() foreach (var cl in IncludedClasses) filters.IncludedClasses.Add(cl); foreach (var me in IncludedMethods) filters.IncludedMethods.Add(me); - var result = await testRunner.Run(TestAssembly, printXml: true, filters); + var result = await ThreadlessXunitTestRunner.Run(TestAssembly, printXml: true, filters); return result; } - private void ParseEqualSeparatedArgument(Dictionary> targetDictionary, string argument) + private static void ParseEqualSeparatedArgument(Dictionary> targetDictionary, string argument) { var parts = argument.Split('='); if (parts.Length != 2 || string.IsNullOrEmpty(parts[0]) || string.IsNullOrEmpty(parts[1])) diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitFilter.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitFilter.cs index 40731436da728..e36aec85d65e3 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitFilter.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitFilter.cs @@ -127,6 +127,8 @@ private bool ApplyTraitFilter(ITestCase testCase, Func? reportFilter { return log(Exclude); } + + return log(!Exclude); } return values.Any(value => value.Equals(SelectorValue, StringComparison.InvariantCultureIgnoreCase)) ? @@ -242,7 +244,7 @@ private bool ReportFilteredTest(ITestCase testCase, bool excluded, Action? log = null) + private static bool ReportFilteredAssembly(TestAssemblyInfo assemblyInfo, bool excluded, Action? log = null) { if (log == null) { diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitTestRunner.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitTestRunner.cs index affda41ec6a4a..e79c243161239 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitTestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitTestRunner.cs @@ -34,7 +34,7 @@ internal class XUnitTestRunner : TestRunner public int? MaxParallelThreads { get; set; } private XElement _assembliesElement; - private XUnitFiltersCollection _filters = new XUnitFiltersCollection(); + private XUnitFiltersCollection _filters = new(); public AppDomainSupport AppDomainSupport { get; set; } = AppDomainSupport.Denied; protected override string ResultsFileName { get; set; } = "TestResults.xUnit.xml"; @@ -727,7 +727,9 @@ private void LogFailureInformation(IFailureInformation info, Action log private Action EnsureLogger(Action log) => log ?? OnInfo; - private void LogTestMethodDetails(IMethodInfo method, Action log = null, StringBuilder sb = null) +#pragma warning disable IDE0060 // Remove unused parameter + private static void LogTestMethodDetails(IMethodInfo method, Action log = null, StringBuilder sb = null) +#pragma warning restore IDE0060 // Remove unused parameter { // log = EnsureLogger(log); // log ($" Test method name: {method.Type.Name}.{method.Name}"); @@ -804,7 +806,7 @@ private void LogSourceInformation(ISourceInformation source, Action log sb?.AppendLine(); } - private string GetAssemblyInfo(ITestAssembly assembly) + private static string GetAssemblyInfo(ITestAssembly assembly) { string name = assembly?.Assembly?.Name?.Trim(); if (string.IsNullOrEmpty(name)) diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Hardware/HardwareDeviceLoader.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Hardware/HardwareDeviceLoader.cs index 420b7d81c7cce..fa872c3729ea7 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Hardware/HardwareDeviceLoader.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Hardware/HardwareDeviceLoader.cs @@ -156,7 +156,7 @@ public async Task FindDevice(RunMode runMode, ILog log, bool in IEnumerable compatibleDevices = ConnectedDevices.Where(v => deviceClasses.Contains(v.DeviceClass) && v.IsUsableForDebugging != false); IHardwareDevice device; - if (compatibleDevices.Count() == 0) + if (!compatibleDevices.Any()) { throw new NoDeviceFoundException($"Could not find any applicable devices with device class(es): {string.Join(", ", deviceClasses)}"); } @@ -185,14 +185,15 @@ public async Task FindCompanionDevice(ILog log, IHardwareDevice await LoadDevices(log, false, false); var companion = ConnectedDevices.Where((v) => v.DeviceIdentifier == device.CompanionIdentifier); - if (companion.Count() == 0) + var count = companion.Count(); + if (count == 0) { throw new Exception($"Could not find the companion device for '{device.Name}'"); } - if (companion.Count() > 1) + if (count > 1) { - log.WriteLine("Found {0} companion devices for {1}?!?", companion.Count(), device.Name); + log.WriteLine("Found {0} companion devices for {1}?!?", count, device.Name); } return companion.First(); diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/SimpleListener.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/SimpleListener.cs index cdf6a8bfc1047..904ce7d603b62 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/SimpleListener.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/SimpleListener.cs @@ -103,7 +103,11 @@ public void Cancel() } } - public virtual void Dispose() => TestLog.Dispose(); + public virtual void Dispose() + { + TestLog.Dispose(); + GC.SuppressFinalize(this); + } } } diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/TcpTunnel.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/TcpTunnel.cs index 4672fdd533a14..577f6fcaf9855 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/TcpTunnel.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/TcpTunnel.cs @@ -110,6 +110,10 @@ public async Task Close() await _tcpTunnelExecutionTask; } - public async ValueTask DisposeAsync() => await Close(); + public async ValueTask DisposeAsync() + { + await Close(); + GC.SuppressFinalize(this); + } } } diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/TunnelBore.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/TunnelBore.cs index e8a36e6857389..e681b1cee112b 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/TunnelBore.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Listeners/TunnelBore.cs @@ -73,6 +73,7 @@ public async ValueTask DisposeAsync() await tunnel.DisposeAsync(); // alls close already } } + GC.SuppressFinalize(this); } } } diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/AppInstallMonitorLog.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/AppInstallMonitorLog.cs index 8f494bca3d12f..f8e52f1409c0f 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/AppInstallMonitorLog.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/AppInstallMonitorLog.cs @@ -55,6 +55,7 @@ public override void Dispose() { _copyTo.Dispose(); _cancellationSource.Dispose(); + GC.SuppressFinalize(this); } private void ResetTimer() => _cancellationSource.CancelAfter(TimeSpan.FromMinutes(1)); diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/CaptureLog.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/CaptureLog.cs index 36a487c274228..1522224449309 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/CaptureLog.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/CaptureLog.cs @@ -187,6 +187,7 @@ public override StreamReader GetReader() public override void Dispose() { + GC.SuppressFinalize(this); } } } diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/LogFile.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/LogFile.cs index 58cce05eebe8b..bd9a585a4ee9b 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/LogFile.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/LogFile.cs @@ -86,6 +86,7 @@ public override void Dispose() } _disposed = true; + GC.SuppressFinalize(this); } } } diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/Logs.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/Logs.cs index f063dd4f926bf..f8f0fa0262ac2 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/Logs.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Logging/Logs.cs @@ -87,6 +87,7 @@ public void Dispose() { log.Dispose(); } + GC.SuppressFinalize(this); } } } diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Microsoft.DotNet.XHarness.iOS.Shared.csproj b/src/Microsoft.DotNet.XHarness.iOS.Shared/Microsoft.DotNet.XHarness.iOS.Shared.csproj index 10d577cc47463..617d0bdecaa36 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Microsoft.DotNet.XHarness.iOS.Shared.csproj +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Microsoft.DotNet.XHarness.iOS.Shared.csproj @@ -2,10 +2,11 @@ true - netstandard2.0;netcoreapp3.1 + netstandard2.0;netstandard2.1 8.0 + disable - + $(NoWarn);8600;8601;8602;8603;8604 diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Utilities/Extensions.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Utilities/Extensions.cs index 0304987dd9742..c351c4e87e943 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Utilities/Extensions.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Utilities/Extensions.cs @@ -23,7 +23,7 @@ public static class Extensions TestTarget.Simulator_tvOS => "tvos-simulator", TestTarget.Simulator_watchOS => "watchos-simulator", TestTarget.MacCatalyst => "maccatalyst", - _ => throw new ArgumentOutOfRangeException() + _ => throw new ArgumentOutOfRangeException(nameof(target)) }; public static string AsString(this TestTargetOs targetOs) => @@ -42,7 +42,7 @@ public static string AsString(this TestTargetOs targetOs) => "maccatalyst" => TestTarget.MacCatalyst, null => TestTarget.None, "" => TestTarget.None, - _ => throw new ArgumentOutOfRangeException() + _ => throw new ArgumentOutOfRangeException(nameof(target)) }; public static TestTargetOs ParseAsAppRunnerTargetOs(this string targetName) @@ -67,14 +67,14 @@ public static TestTargetOs ParseAsAppRunnerTargetOs(this string targetName) { "com.apple.widget-extension" => Extension.TodayExtension, "com.apple.watchkit" => Extension.WatchKit2, - _ => throw new ArgumentOutOfRangeException() + _ => throw new ArgumentOutOfRangeException(nameof(identifier)) }; public static string AsNSExtensionPointIdentifier(this Extension extension) => extension switch { Extension.TodayExtension => "com.apple.widget-extension", Extension.WatchKit2 => "com.apple.watchkit", - _ => throw new ArgumentOutOfRangeException() + _ => throw new ArgumentOutOfRangeException(nameof(extension)) }; public static void DoNotAwait(this Task task) diff --git a/src/Microsoft.DotNet.XHarness.iOS.Shared/Utilities/ProjectFileExtensions.cs b/src/Microsoft.DotNet.XHarness.iOS.Shared/Utilities/ProjectFileExtensions.cs index b56b30a581878..30fcd067b44fa 100644 --- a/src/Microsoft.DotNet.XHarness.iOS.Shared/Utilities/ProjectFileExtensions.cs +++ b/src/Microsoft.DotNet.XHarness.iOS.Shared/Utilities/ProjectFileExtensions.cs @@ -1212,10 +1212,12 @@ public static void ResolveAllPaths(this XmlDocument csproj, string project_path, { "MtouchExtraArgs", }; +#pragma warning disable IDE0059 // Unnecessary assignment of a value Func? convert = null; +#pragma warning restore IDE0059 // Unnecessary assignment of a value convert = (input) => { - if (input.IndexOf(';') >= 0) + if (input.Contains(';')) { var split = input.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (var i = 0; i < split.Length; i++) diff --git a/tests/Microsoft.DotNet.XHarness.Android.Tests/AdbRunnerTests.cs b/tests/Microsoft.DotNet.XHarness.Android.Tests/AdbRunnerTests.cs index 5fc61aa5f3e95..714427c682c94 100644 --- a/tests/Microsoft.DotNet.XHarness.Android.Tests/AdbRunnerTests.cs +++ b/tests/Microsoft.DotNet.XHarness.Android.Tests/AdbRunnerTests.cs @@ -48,7 +48,11 @@ public AdbRunnerTests() It.IsAny())).Returns((string p, string a, TimeSpan t) => CallFakeProcessManager(p, a, t)); } - public void Dispose() => Directory.Delete(s_scratchAndOutputPath, true); + public void Dispose() + { + Directory.Delete(s_scratchAndOutputPath, true); + GC.SuppressFinalize(this); + } #region Tests @@ -227,7 +231,7 @@ public void RunInstrumentation(string instrumentationName) #region Helper Functions // Generates a list of fake devices, one per supported architecture so we can test AdbRunner's parsing of the output. // As with most of these tests, if adb.exe changes, this will break (we are locked into specific version) - private Dictionary, int> InitializeFakeDeviceList() + private static Dictionary, int> InitializeFakeDeviceList() { var r = new Random(); var values = new Dictionary, int> diff --git a/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppInstallerTests.cs b/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppInstallerTests.cs index 30c06da791fdf..4f524b0cf2111 100644 --- a/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppInstallerTests.cs +++ b/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppInstallerTests.cs @@ -57,7 +57,11 @@ public AppInstallerTests() extension: null); } - public void Dispose() => Directory.Delete(s_appPath, true); + public void Dispose() + { + Directory.Delete(s_appPath, true); + GC.SuppressFinalize(this); + } [Fact] public async Task InstallToSimulatorTest() diff --git a/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppRunnerTests.cs b/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppRunnerTests.cs index 9d6682bacdc75..bf2e9a6235460 100644 --- a/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppRunnerTests.cs +++ b/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppRunnerTests.cs @@ -101,7 +101,11 @@ public AppRunnerTests() Directory.CreateDirectory(s_outputPath); } - public void Dispose() => Directory.Delete(s_outputPath, true); + public void Dispose() + { + Directory.Delete(s_outputPath, true); + GC.SuppressFinalize(this); + } [Fact] public async Task RunOnSimulatorWithNoAvailableSimulatorTest() diff --git a/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppTesterTests.cs b/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppTesterTests.cs index 1446100ead6b9..08602d7152694 100644 --- a/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppTesterTests.cs +++ b/tests/Microsoft.DotNet.XHarness.Apple.Tests/AppTesterTests.cs @@ -138,7 +138,11 @@ public AppTesterTests() Directory.CreateDirectory(s_outputPath); } - public void Dispose() => Directory.Delete(s_outputPath, true); + public void Dispose() + { + Directory.Delete(s_outputPath, true); + GC.SuppressFinalize(this); + } [Theory] [InlineData(false)] diff --git a/tests/Microsoft.DotNet.XHarness.Apple.Tests/ErrorKnowledgeBaseTests.cs b/tests/Microsoft.DotNet.XHarness.Apple.Tests/ErrorKnowledgeBaseTests.cs index 008490b350086..8e9f1401387a9 100644 --- a/tests/Microsoft.DotNet.XHarness.Apple.Tests/ErrorKnowledgeBaseTests.cs +++ b/tests/Microsoft.DotNet.XHarness.Apple.Tests/ErrorKnowledgeBaseTests.cs @@ -21,6 +21,7 @@ public void Dispose() { File.Delete(_logPath); } + GC.SuppressFinalize(this); } [Fact] diff --git a/tests/Microsoft.DotNet.XHarness.Apple.Tests/ExitCodeDetectorTests.cs b/tests/Microsoft.DotNet.XHarness.Apple.Tests/ExitCodeDetectorTests.cs index 5ba4fa7f46857..41b3e4a939380 100644 --- a/tests/Microsoft.DotNet.XHarness.Apple.Tests/ExitCodeDetectorTests.cs +++ b/tests/Microsoft.DotNet.XHarness.Apple.Tests/ExitCodeDetectorTests.cs @@ -11,7 +11,7 @@ namespace Microsoft.DotNet.XHarness.Apple.Tests { public class ExitCodeDetectorTests : IDisposable { - private string _tempFilename = null; + private readonly string _tempFilename = null; [Fact] public void ExitCodeIsDetectedTest() @@ -152,6 +152,7 @@ public void Dispose() { File.Delete(_tempFilename); } + GC.SuppressFinalize(this); } private static IFileBackedLog GetLogMock(string[] loglines) diff --git a/tests/Microsoft.DotNet.XHarness.Common.Tests/Logging/ConsoleLogTest.cs b/tests/Microsoft.DotNet.XHarness.Common.Tests/Logging/ConsoleLogTest.cs index e01fa21cf1695..ab00e93007910 100644 --- a/tests/Microsoft.DotNet.XHarness.Common.Tests/Logging/ConsoleLogTest.cs +++ b/tests/Microsoft.DotNet.XHarness.Common.Tests/Logging/ConsoleLogTest.cs @@ -49,6 +49,7 @@ public void Dispose() _log.Dispose(); Console.SetOut(_sdoutWriter); // get back to write to the console File.Delete(_testFile); + GC.SuppressFinalize(this); } } } diff --git a/tests/Microsoft.DotNet.XHarness.TestRunners.Tests/NUnit/NUnit3XmlOutputWriterTests.cs b/tests/Microsoft.DotNet.XHarness.TestRunners.Tests/NUnit/NUnit3XmlOutputWriterTests.cs index ab16ea0f79fb8..1e59434932999 100644 --- a/tests/Microsoft.DotNet.XHarness.TestRunners.Tests/NUnit/NUnit3XmlOutputWriterTests.cs +++ b/tests/Microsoft.DotNet.XHarness.TestRunners.Tests/NUnit/NUnit3XmlOutputWriterTests.cs @@ -91,6 +91,10 @@ public void SeveralTetRunTest() Assert.Equal(1, enviroment.Count); } - public void Dispose() => File.Delete(_tempPath); + public void Dispose() + { + File.Delete(_tempPath); + GC.SuppressFinalize(this); + } } } diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/AppBundleInformationParserTests.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/AppBundleInformationParserTests.cs index 38897c2b2728e..6d820c4051bbb 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/AppBundleInformationParserTests.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/AppBundleInformationParserTests.cs @@ -33,6 +33,7 @@ public void Dispose() { Directory.Delete(s_appPath, true); Directory.Delete(s_appPath2, true); + GC.SuppressFinalize(this); } [Fact] diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/CrashSnapshotReporterTests.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/CrashSnapshotReporterTests.cs index 8721f9aaad7e6..aae026d41f954 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/CrashSnapshotReporterTests.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/CrashSnapshotReporterTests.cs @@ -45,7 +45,11 @@ public CrashReportSnapshotTests() File.WriteAllText(Path.Combine(_symbolicatePath, "symbolicatecrash"), ""); } - public void Dispose() => Directory.Delete(_tempXcodeRoot, true); + public void Dispose() + { + Directory.Delete(_tempXcodeRoot, true); + GC.SuppressFinalize(this); + } [Fact] public async Task DeviceCaptureTest() diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Listeners/SimpleFileListenerTest.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Listeners/SimpleFileListenerTest.cs index bef8d65066564..0a491f53f4a95 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Listeners/SimpleFileListenerTest.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Listeners/SimpleFileListenerTest.cs @@ -31,6 +31,7 @@ public void Dispose() { File.Delete(_path); } + GC.SuppressFinalize(this); } [Fact] diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Listeners/SimpleListenerFactoryTest.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Listeners/SimpleListenerFactoryTest.cs index a92e5ff5357df..b997c8eea477b 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Listeners/SimpleListenerFactoryTest.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Listeners/SimpleListenerFactoryTest.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using Microsoft.DotNet.XHarness.Common.Logging; using Microsoft.DotNet.XHarness.iOS.Shared.Listeners; using Moq; @@ -21,7 +22,10 @@ public SimpleListenerFactoryTest() } [Fact] - public void ConstructorAllowsNullTunnelBore() => new SimpleListenerFactory(null); // if it throws, test fails ;) + public void ConstructorAllowsNullTunnelBore() + { + _ = new SimpleListenerFactory(null); // if it throws, test fails ;) + } [Fact] public void CreateNotWatchListener() diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/CaptureLogTest.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/CaptureLogTest.cs index fff14dfa7029a..09b96e7455fa1 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/CaptureLogTest.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/CaptureLogTest.cs @@ -28,6 +28,7 @@ public void Dispose() { File.Delete(_filePath); } + GC.SuppressFinalize(this); } [Fact] diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/LogFileTest.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/LogFileTest.cs index 617fd88c3d3f1..0de17f7421947 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/LogFileTest.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/LogFileTest.cs @@ -26,6 +26,7 @@ public void Dispose() { File.Delete(_path); } + GC.SuppressFinalize(this); } [Fact] diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/LogsTest.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/LogsTest.cs index 24d72d7174e6f..e4fc9f322f540 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/LogsTest.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Logging/LogsTest.cs @@ -31,6 +31,7 @@ public void Dispose() { Directory.Delete(_directory, true); } + GC.SuppressFinalize(this); } [Fact] diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/TestReporterTests.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/TestReporterTests.cs index 577c487d492f3..3f8ede06318b9 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/TestReporterTests.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/TestReporterTests.cs @@ -62,6 +62,7 @@ public void Dispose() { Directory.Delete(_logsDirectory, true); } + GC.SuppressFinalize(this); } private Stream GetRunLogSample() diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Utilities/ProjectFileExtensionsTests.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Utilities/ProjectFileExtensionsTests.cs index e41b3b69842a3..09a0c87e3f5e9 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Utilities/ProjectFileExtensionsTests.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/Utilities/ProjectFileExtensionsTests.cs @@ -17,7 +17,7 @@ private static XmlDocument CreateDoc(string xml) return doc; } - private XmlDocument GetMSBuildProject(string snippet) + private static XmlDocument GetMSBuildProject(string snippet) { return CreateDoc($@" diff --git a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/XmlResultParserTests.cs b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/XmlResultParserTests.cs index 4ba68a7bfe6b4..b9f64e7229a2d 100644 --- a/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/XmlResultParserTests.cs +++ b/tests/Microsoft.DotNet.XHarness.iOS.Shared.Tests/XmlResultParserTests.cs @@ -18,7 +18,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared.Tests { public class XmlResultParserTests { - private static readonly Dictionary> s_validationMap = new Dictionary> + private static readonly Dictionary> s_validationMap = new() { [XmlResultJargon.NUnitV2] = ValidateNUnitV2Failure, [XmlResultJargon.NUnitV3] = ValidateNUnitV3Failure,