diff --git a/test/Common/Program.cs b/test/Common/Program.cs index 226c95f28371..e1cd32e1c617 100644 --- a/test/Common/Program.cs +++ b/test/Common/Program.cs @@ -10,7 +10,7 @@ partial class Program public static int Main(string[] args) { var testCommandLine = TestCommandLine.HandleCommandLine(args); - var newArgs = testCommandLine.RemainingArgs.ToList(); + List newArgs = testCommandLine.RemainingArgs?.ToList() ?? new List(); // Help argument needs to be the first one to xunit, so don't insert assembly location in that case if (testCommandLine.ShouldShowHelp) diff --git a/test/HelixTasks/CreateLocalHelixTestLayout.cs b/test/HelixTasks/CreateLocalHelixTestLayout.cs index 8b81992258af..ebdc35745f64 100644 --- a/test/HelixTasks/CreateLocalHelixTestLayout.cs +++ b/test/HelixTasks/CreateLocalHelixTestLayout.cs @@ -8,18 +8,23 @@ namespace Microsoft.DotNet.SdkCustomHelix.Sdk public sealed class CreateLocalHelixTestLayout : Build.Utilities.Task { [Required] - public ITaskItem[] HelixCorrelationPayload { get; set; } + public ITaskItem[]? HelixCorrelationPayload { get; set; } [Required] - public string TestOutputDirectory { get; set; } + public string? TestOutputDirectory { get; set; } public override bool Execute() { + if (HelixCorrelationPayload is null) + { + return false; + }; + foreach (var payload in HelixCorrelationPayload) { var copyfrom = new DirectoryInfo(payload.GetMetadata("PayloadDirectory")); var relativeDestinationPathOnHelix = payload.GetMetadata("Destination"); - var destination = new DirectoryInfo(Path.Combine(TestOutputDirectory, relativeDestinationPathOnHelix)); + var destination = new DirectoryInfo(Path.Combine(TestOutputDirectory ?? string.Empty, relativeDestinationPathOnHelix)); if (Directory.Exists(destination.FullName)) { diff --git a/test/HelixTasks/HelixTasks.csproj b/test/HelixTasks/HelixTasks.csproj index 02350e724ec7..ca4e7c73653b 100644 --- a/test/HelixTasks/HelixTasks.csproj +++ b/test/HelixTasks/HelixTasks.csproj @@ -5,6 +5,7 @@ net8.0 true Microsoft.DotNet.SDK.Build.Helix + enable diff --git a/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs b/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs index f54f6c7beb04..2d838d172a72 100644 --- a/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs +++ b/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs @@ -22,7 +22,7 @@ public class SDKCustomCreateXUnitWorkItemsWithTestExclusion : Build.Utilities.Ta /// The two required parameters will be automatically created if XUnitProject.Identity is set to the path of the XUnit csproj file /// [Required] - public ITaskItem[] XUnitProjects { get; set; } + public ITaskItem[]? XUnitProjects { get; set; } /// /// The path to the dotnet executable on the Helix agent. Defaults to "dotnet" @@ -40,15 +40,15 @@ public class SDKCustomCreateXUnitWorkItemsWithTestExclusion : Build.Utilities.Ta /// Optional timeout for all created workitems /// Defaults to 300s /// - public string XUnitWorkItemTimeout { get; set; } + public string? XUnitWorkItemTimeout { get; set; } - public string XUnitArguments { get; set; } + public string? XUnitArguments { get; set; } /// /// An array of ITaskItems of type HelixWorkItem /// [Output] - public ITaskItem[] XUnitWorkItems { get; set; } + public ITaskItem[]? XUnitWorkItems { get; set; } /// /// The main method of this MSBuild task which calls the asynchronous execution method and @@ -71,8 +71,13 @@ public override bool Execute() /// private async Task ExecuteAsync() { + if(XUnitProjects is null) + { + return; + } + XUnitWorkItems = (await Task.WhenAll(XUnitProjects.Select(PrepareWorkItem))) - .SelectMany(i => i) + .SelectMany(i => i ?? new()) .Where(wi => wi != null) .ToArray(); return; @@ -83,7 +88,7 @@ private async Task ExecuteAsync() /// /// The non-relative path to the publish directory. /// An ITaskItem instance representing the prepared HelixWorkItem. - private async Task> PrepareWorkItem(ITaskItem xunitProject) + private async Task?> PrepareWorkItem(ITaskItem xunitProject) { // Forces this task to run asynchronously await Task.Yield(); @@ -164,12 +169,12 @@ private async Task> PrepareWorkItem(ITaskItem xunitProject) Log.LogMessage($"Creating work item with properties Identity: {assemblyName}, PayloadDirectory: {publishDirectory}, Command: {command}"); partitionedWorkItem.Add(new Microsoft.Build.Utilities.TaskItem(assemblyPartitionInfo.DisplayName + testIdentityDifferentiator, new Dictionary() - { - { "Identity", assemblyPartitionInfo.DisplayName + testIdentityDifferentiator}, - { "PayloadDirectory", publishDirectory }, - { "Command", command }, - { "Timeout", timeout.ToString() }, - })); + { + { "Identity", assemblyPartitionInfo.DisplayName + testIdentityDifferentiator}, + { "PayloadDirectory", publishDirectory }, + { "Command", command }, + { "Timeout", timeout.ToString() }, + })); } return partitionedWorkItem; diff --git a/test/HelixTasks/TarGzFileCreateFromDirectory.cs b/test/HelixTasks/TarGzFileCreateFromDirectory.cs index 96a905cb041d..8629f92e6b23 100644 --- a/test/HelixTasks/TarGzFileCreateFromDirectory.cs +++ b/test/HelixTasks/TarGzFileCreateFromDirectory.cs @@ -12,13 +12,13 @@ public sealed class TarGzFileCreateFromDirectory : ToolTask /// The path to the directory to be archived. /// [Required] - public string SourceDirectory { get; set; } + public string? SourceDirectory { get; set; } /// /// The path of the archive to be created. /// [Required] - public string DestinationArchive { get; set; } + public string? DestinationArchive { get; set; } /// /// Indicates if the destination archive should be overwritten if it already exists. @@ -33,7 +33,7 @@ public sealed class TarGzFileCreateFromDirectory : ToolTask /// /// An item group of regular expressions for content to exclude from the archive. /// - public ITaskItem[] ExcludePatterns { get; set; } + public ITaskItem[]? ExcludePatterns { get; set; } public bool IgnoreExitCode { get; set; } @@ -69,16 +69,18 @@ protected override bool ValidateParameters() retVal = false; } } + if (SourceDirectory is not null) + { + SourceDirectory = Path.GetFullPath(SourceDirectory); - SourceDirectory = Path.GetFullPath(SourceDirectory); - - SourceDirectory = SourceDirectory.EndsWith(Path.DirectorySeparatorChar.ToString()) - ? SourceDirectory - : SourceDirectory + Path.DirectorySeparatorChar; + SourceDirectory = SourceDirectory.EndsWith(Path.DirectorySeparatorChar.ToString()) + ? SourceDirectory + : SourceDirectory + Path.DirectorySeparatorChar; + } if (!Directory.Exists(SourceDirectory)) { - Log.LogError($"SourceDirectory '{SourceDirectory} does not exist."); + Log.LogError($"SourceDirectory '{SourceDirectory}' does not exist."); retVal = false; } @@ -113,9 +115,9 @@ protected override string GenerateCommandLineCommands() private string GetSourceSpecification() { - if (IncludeBaseDirectory) + if (SourceDirectory is not null && IncludeBaseDirectory) { - var parentDirectory = Directory.GetParent(SourceDirectory).Parent.FullName; + var parentDirectory = Directory.GetParent(SourceDirectory)?.Parent?.FullName; var sourceDirectoryName = Path.GetFileName(Path.GetDirectoryName(SourceDirectory)); diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs index 3a69dece7787..5ae1169c459d 100644 --- a/test/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs +++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs @@ -341,16 +341,16 @@ public async Task EndToEnd_NoAPI_ProjectType(string projectType, bool addPackage { File.Copy(Path.Combine(TestContext.Current.TestExecutionDirectory, "NuGet.config"), Path.Combine(newProjectDir.FullName, "NuGet.config")); - (string packagePath, string packageVersion) = ToolsetUtils.GetContainersPackagePath(); + (string? packagePath, string? packageVersion) = ToolsetUtils.GetContainersPackagePath(); - new DotnetCommand(_testOutput, "nuget", "add", "source", Path.GetDirectoryName(packagePath), "--name", "local-temp") + new DotnetCommand(_testOutput, "nuget", "add", "source", Path.GetDirectoryName(packagePath) ?? string.Empty, "--name", "local-temp") .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName) .WithWorkingDirectory(newProjectDir.FullName) .Execute() .Should().Pass(); // Add package to the project - new DotnetCommand(_testOutput, "add", "package", "Microsoft.NET.Build.Containers", "-f", ToolsetInfo.CurrentTargetFramework, "-v", packageVersion) + new DotnetCommand(_testOutput, "add", "package", "Microsoft.NET.Build.Containers", "-f", ToolsetInfo.CurrentTargetFramework, "-v", packageVersion ?? string.Empty) .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName) .WithWorkingDirectory(newProjectDir.FullName) .Execute() @@ -509,16 +509,16 @@ public void EndToEnd_NoAPI_Console() File.Copy(Path.Combine(TestContext.Current.TestExecutionDirectory, "NuGet.config"), Path.Combine(newProjectDir.FullName, "NuGet.config")); - (string packagePath, string packageVersion) = ToolsetUtils.GetContainersPackagePath(); + (string? packagePath, string? packageVersion) = ToolsetUtils.GetContainersPackagePath(); - new DotnetCommand(_testOutput, "nuget", "add", "source", Path.GetDirectoryName(packagePath), "--name", "local-temp") + new DotnetCommand(_testOutput, "nuget", "add", "source", Path.GetDirectoryName(packagePath) ?? string.Empty, "--name", "local-temp") .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName) .WithWorkingDirectory(newProjectDir.FullName) .Execute() .Should().Pass(); // Add package to the project - new DotnetCommand(_testOutput, "add", "package", "Microsoft.NET.Build.Containers", "-f", _oldFramework , "-v", packageVersion) + new DotnetCommand(_testOutput, "add", "package", "Microsoft.NET.Build.Containers", "-f", _oldFramework , "-v", packageVersion ?? string.Empty) .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName) .WithWorkingDirectory(newProjectDir.FullName) .Execute() diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/PackageTests.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/PackageTests.cs index 92b767a3990a..3aa57a3a7670 100644 --- a/test/Microsoft.NET.Build.Containers.IntegrationTests/PackageTests.cs +++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/PackageTests.cs @@ -131,8 +131,8 @@ public void PackageContentTest() $"tasks/{netTFM}/Valleysoft.DockerCredsProvider.dll" }; - (string packageFilePath, string packageVersion) = ToolsetUtils.GetContainersPackagePath(); - using ZipArchive archive = new(File.OpenRead(packageFilePath), ZipArchiveMode.Read, false); + (string? packageFilePath, string? packageVersion) = ToolsetUtils.GetContainersPackagePath(); + using ZipArchive archive = new(File.OpenRead(packageFilePath ?? string.Empty), ZipArchiveMode.Read, false); IEnumerable actualEntries = archive.Entries .Select(e => e.FullName) diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/ProjectInitializer.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/ProjectInitializer.cs index 58a42fbedae4..89f1f16f2b4c 100644 --- a/test/Microsoft.NET.Build.Containers.IntegrationTests/ProjectInitializer.cs +++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/ProjectInitializer.cs @@ -10,7 +10,7 @@ namespace Microsoft.NET.Build.Containers.IntegrationTests; public sealed class ProjectInitializer { - private static readonly string _combinedTargetsLocation; + private static readonly string? _combinedTargetsLocation; static ProjectInitializer() { diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/ToolsetUtils.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/ToolsetUtils.cs index 41c9d703d415..58fda7c074e7 100644 --- a/test/Microsoft.NET.Build.Containers.IntegrationTests/ToolsetUtils.cs +++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/ToolsetUtils.cs @@ -20,18 +20,18 @@ internal static string GetRuntimeGraphFilePath() /// Gets path to built Microsoft.NET.Build.Containers.*.nupkg prepared for tests. /// /// - internal static (string PackagePath, string PackageVersion) GetContainersPackagePath() + internal static (string? PackagePath, string? PackageVersion) GetContainersPackagePath() { string packageDir = Path.Combine(TestContext.Current.TestExecutionDirectory, "Container", "package"); //until the package is stabilized, the package version matches TestContext.Current.ToolsetUnderTest.SdkVersion //after the package is stabilized, the package version doesn't have -prefix (-dev, -ci) anymore //so one of those is expected - string[] expectedPackageVersions = new[] { TestContext.Current.ToolsetUnderTest.SdkVersion, TestContext.Current.ToolsetUnderTest.SdkVersion.Split('-')[0] }; + string?[] expectedPackageVersions = new[] { TestContext.Current.ToolsetUnderTest?.SdkVersion, TestContext.Current.ToolsetUnderTest?.SdkVersion?.Split('-')[0] }; - foreach (string expectedVersion in expectedPackageVersions) + foreach (string? expectedVersion in expectedPackageVersions) { - string fullFileName = Path.Combine(packageDir, $"Microsoft.NET.Build.Containers.{expectedVersion}.nupkg"); + string? fullFileName = Path.Combine(packageDir, $"Microsoft.NET.Build.Containers.{expectedVersion}.nupkg"); if (File.Exists(fullFileName)) { return (fullFileName, expectedVersion); diff --git a/test/Microsoft.NET.TestFramework/AspNetSdkTest.cs b/test/Microsoft.NET.TestFramework/AspNetSdkTest.cs index 08a5b1afdb0a..41a4819463e1 100644 --- a/test/Microsoft.NET.TestFramework/AspNetSdkTest.cs +++ b/test/Microsoft.NET.TestFramework/AspNetSdkTest.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; @@ -11,7 +12,7 @@ namespace Microsoft.NET.TestFramework [Trait("AspNetCore", "Integration")] public abstract class AspNetSdkTest : SdkTest { - public readonly string DefaultTfm; + public readonly string? DefaultTfm; #if !GENERATE_MSBUILD_LOGS public static bool GenerateMSbuildLogs = true; @@ -25,27 +26,27 @@ protected AspNetSdkTest(ITestOutputHelper log) : base(log) { var assembly = Assembly.GetCallingAssembly(); var testAssemblyMetadata = assembly.GetCustomAttributes(); - DefaultTfm = testAssemblyMetadata.SingleOrDefault(a => a.Key == "AspNetTestTfm").Value; + DefaultTfm = testAssemblyMetadata.SingleOrDefault(a => a.Key == "AspNetTestTfm")?.Value; } public TestAsset CreateAspNetSdkTestAsset( string testAsset, [CallerMemberName] string callerName = "", string subdirectory = "", - string overrideTfm = null, - string identifier = null) + string? overrideTfm = null, + string? identifier = null) { var projectDirectory = _testAssetsManager .CopyTestAsset(testAsset, callingMethod: callerName, testAssetSubdirectory: subdirectory, identifier: identifier) .WithSource() .WithProjectChanges(project => { - var ns = project.Root.Name.Namespace; + var ns = project.Root?.Name.Namespace; var targetFramework = project.Descendants() .SingleOrDefault(e => e.Name.LocalName == "TargetFramework"); if (targetFramework?.Value == "$(AspNetTestTfm)") { - targetFramework.Value = overrideTfm ?? DefaultTfm; + targetFramework.Value = overrideTfm ?? DefaultTfm ?? string.Empty; targetFramework.AddAfterSelf(new XElement("StaticWebAssetsFingerprintContent", "false")); } var targetFrameworks = project.Descendants() @@ -67,15 +68,15 @@ public TestAsset CreateMultitargetAspNetSdkTestAsset( string testAsset, [CallerMemberName] string callerName = "", string subdirectory = "", - string overrideTfm = null, - string identifier = null) + string? overrideTfm = null, + string? identifier = null) { var projectDirectory = _testAssetsManager .CopyTestAsset(testAsset, callingMethod: callerName, testAssetSubdirectory: subdirectory, identifier: identifier) .WithSource() .WithProjectChanges(project => { - var ns = project.Root.Name.Namespace; + var ns = project.Root?.Name.Namespace; var targetFramework = project.Descendants() .Single(e => e.Name.LocalName == "TargetFrameworks"); targetFramework.Value = targetFramework.Value.Replace("$(AspNetTestTfm)", overrideTfm ?? DefaultTfm); @@ -83,7 +84,7 @@ public TestAsset CreateMultitargetAspNetSdkTestAsset( return projectDirectory; } - protected virtual RestoreCommand CreateRestoreCommand(TestAsset asset, string relativePathToProject = null) + protected virtual RestoreCommand CreateRestoreCommand(TestAsset asset, string? relativePathToProject = null) { var restore = new RestoreCommand(asset, relativePathToProject); restore.WithWorkingDirectory(asset.TestRoot); @@ -91,7 +92,7 @@ protected virtual RestoreCommand CreateRestoreCommand(TestAsset asset, string re return restore; } - protected virtual BuildCommand CreateBuildCommand(TestAsset asset, string relativePathToProject = null) + protected virtual BuildCommand CreateBuildCommand(TestAsset asset, string? relativePathToProject = null) { var build = new BuildCommand(asset, relativePathToProject); build.WithWorkingDirectory(asset.TestRoot); @@ -100,7 +101,7 @@ protected virtual BuildCommand CreateBuildCommand(TestAsset asset, string relati return build; } - protected virtual RebuildCommand CreateRebuildCommand(TestAsset asset, string relativePathToProject = null) + protected virtual RebuildCommand CreateRebuildCommand(TestAsset asset, string? relativePathToProject = null) { var rebuild = new RebuildCommand(Log, asset.Path, relativePathToProject); rebuild.WithWorkingDirectory(asset.TestRoot); @@ -109,7 +110,7 @@ protected virtual RebuildCommand CreateRebuildCommand(TestAsset asset, string re return rebuild; } - protected virtual PackCommand CreatePackCommand(TestAsset asset, string relativePathToProject = null) + protected virtual PackCommand CreatePackCommand(TestAsset asset, string? relativePathToProject = null) { var pack = new PackCommand(asset, relativePathToProject); pack.WithWorkingDirectory(asset.TestRoot); @@ -118,7 +119,7 @@ protected virtual PackCommand CreatePackCommand(TestAsset asset, string relative return pack; } - protected virtual PublishCommand CreatePublishCommand(TestAsset asset, string relativePathToProject = null) + protected virtual PublishCommand CreatePublishCommand(TestAsset asset, string? relativePathToProject = null) { var publish = new PublishCommand(asset, relativePathToProject); publish.WithWorkingDirectory(asset.TestRoot); @@ -134,7 +135,7 @@ protected virtual CommandResult ExecuteCommand(TestCommand command, params strin if (_generateMSbuildLogs) { var i = 0; - for (i = 0; File.Exists(Path.Combine(command.WorkingDirectory, $"msbuild{i}.binlog")) && i < 20; i++) { } + for (i = 0; command.WorkingDirectory is not null && File.Exists(Path.Combine(command.WorkingDirectory, $"msbuild{i}.binlog")) && i < 20; i++) { } var log = $"msbuild{i}.binlog"; return command.Execute([$"/bl:{log}", .. arguments]); @@ -152,7 +153,7 @@ protected virtual CommandResult ExecuteCommandWithoutRestore(MSBuildCommand comm if (_generateMSbuildLogs) { var i = 0; - for (i = 0; File.Exists(Path.Combine(command.WorkingDirectory, $"msbuild{i}.binlog")) && i < 20; i++) { } + for (i = 0; command.WorkingDirectory is not null && File.Exists(Path.Combine(command.WorkingDirectory, $"msbuild{i}.binlog")) && i < 20; i++) { } var log = $"msbuild{i}.binlog"; return command.ExecuteWithoutRestore([$"/bl:{log}", .. arguments]); } @@ -184,6 +185,6 @@ private void ApplyDefaults(MSBuildCommand command) } } - protected virtual string GetNuGetCachePath() => null; + protected virtual string? GetNuGetCachePath() => null; } } diff --git a/test/Microsoft.NET.TestFramework/Assertions/CommandResultAssertions.cs b/test/Microsoft.NET.TestFramework/Assertions/CommandResultAssertions.cs index add580802130..a7220a60eb89 100644 --- a/test/Microsoft.NET.TestFramework/Assertions/CommandResultAssertions.cs +++ b/test/Microsoft.NET.TestFramework/Assertions/CommandResultAssertions.cs @@ -47,28 +47,28 @@ public AndConstraint HaveStdOut() public AndConstraint HaveStdOut(string expectedOutput) { - Execute.Assertion.ForCondition(_commandResult.StdOut.Equals(expectedOutput, StringComparison.Ordinal)) + Execute.Assertion.ForCondition(_commandResult.StdOut is not null &&_commandResult.StdOut.Equals(expectedOutput, StringComparison.Ordinal)) .FailWith(AppendDiagnosticsTo($"Command did not output with Expected Output. Expected: {expectedOutput}")); return new AndConstraint(this); } public AndConstraint HaveStdOutContaining(string pattern) { - Execute.Assertion.ForCondition(_commandResult.StdOut.Contains(pattern)) + Execute.Assertion.ForCondition(_commandResult.StdOut is not null && _commandResult.StdOut.Contains(pattern)) .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result: {pattern}{Environment.NewLine}")); return new AndConstraint(this); } - public AndConstraint HaveStdOutContaining(Func predicate, string description = "") + public AndConstraint HaveStdOutContaining(Func predicate, string description = "") { Execute.Assertion.ForCondition(predicate(_commandResult.StdOut)) .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result: {description} {Environment.NewLine}")); return new AndConstraint(this); } - public AndConstraint NotHaveStdOutContaining(string pattern, string[] ignoredPatterns = null) + public AndConstraint NotHaveStdOutContaining(string pattern, string[]? ignoredPatterns = null) { - string filteredStdOut = _commandResult.StdOut; + string filteredStdOut = _commandResult.StdOut ?? string.Empty; if (ignoredPatterns != null && ignoredPatterns.Length > 0) { foreach (var ignoredPattern in ignoredPatterns) @@ -88,7 +88,7 @@ public AndConstraint NotHaveStdOutContaining(string pat public AndConstraint HaveStdOutContainingIgnoreSpaces(string pattern) { - string commandResultNoSpaces = _commandResult.StdOut.Replace(" ", ""); + string commandResultNoSpaces = _commandResult.StdOut?.Replace(" ", "") ?? string.Empty; Execute.Assertion .ForCondition(commandResultNoSpaces.Contains(pattern)) @@ -99,21 +99,21 @@ public AndConstraint HaveStdOutContainingIgnoreSpaces(s public AndConstraint HaveStdOutContainingIgnoreCase(string pattern) { - Execute.Assertion.ForCondition(_commandResult.StdOut.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0) + Execute.Assertion.ForCondition(_commandResult.StdOut is not null && _commandResult.StdOut.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0) .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result (ignoring case): {pattern}{Environment.NewLine}")); return new AndConstraint(this); } public AndConstraint HaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None) { - Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdOut, pattern, options).Success) + Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdOut ?? string.Empty, pattern, options).Success) .FailWith(AppendDiagnosticsTo($"Matching the command output failed. Pattern: {pattern}{Environment.NewLine}")); return new AndConstraint(this); } public AndConstraint NotHaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None) { - Execute.Assertion.ForCondition(!Regex.Match(_commandResult.StdOut, pattern, options).Success) + Execute.Assertion.ForCondition(!Regex.Match(_commandResult.StdOut ?? string.Empty, pattern, options).Success) .FailWith(AppendDiagnosticsTo($"The command output matched a pattern it should not have. Pattern: {pattern}{Environment.NewLine}")); return new AndConstraint(this); } @@ -127,22 +127,22 @@ public AndConstraint HaveStdErr() public AndConstraint HaveStdErr(string expectedOutput) { - Execute.Assertion.ForCondition(_commandResult.StdErr.Equals(expectedOutput, StringComparison.Ordinal)) + Execute.Assertion.ForCondition(_commandResult.StdErr is not null && _commandResult.StdErr.Equals(expectedOutput, StringComparison.Ordinal)) .FailWith(AppendDiagnosticsTo($"Command did not output the expected output to StdErr.{Environment.NewLine}Expected: {expectedOutput}{Environment.NewLine}Actual: {_commandResult.StdErr}")); return new AndConstraint(this); } public AndConstraint HaveStdErrContaining(string pattern) { - Execute.Assertion.ForCondition(_commandResult.StdErr.Contains(pattern)) + Execute.Assertion.ForCondition(_commandResult.StdErr is not null && _commandResult.StdErr.Contains(pattern)) .FailWith(AppendDiagnosticsTo($"The command error output did not contain expected result: {pattern}{Environment.NewLine}")); return new AndConstraint(this); } public AndConstraint HaveStdErrContainingOnce(string pattern) { - var lines = _commandResult.StdErr.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - var matchingLines = lines.Where(line => line.Contains(pattern)).Count(); + var lines = _commandResult.StdErr?.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + var matchingLines = lines?.Where(line => line.Contains(pattern)).Count(); Execute.Assertion.ForCondition(matchingLines == 0) .FailWith(AppendDiagnosticsTo($"The command error output did not contain expected result: {pattern}{Environment.NewLine}")); Execute.Assertion.ForCondition(matchingLines != 1) @@ -152,14 +152,14 @@ public AndConstraint HaveStdErrContainingOnce(string pa public AndConstraint NotHaveStdErrContaining(string pattern) { - Execute.Assertion.ForCondition(!_commandResult.StdErr.Contains(pattern)) + Execute.Assertion.ForCondition(_commandResult.StdErr is not null && !_commandResult.StdErr.Contains(pattern)) .FailWith(AppendDiagnosticsTo($"The command error output contained a result it should not have contained: {pattern}{Environment.NewLine}")); return new AndConstraint(this); } public AndConstraint HaveStdErrMatching(string pattern, RegexOptions options = RegexOptions.None) { - Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdErr, pattern, options).Success) + Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdErr ?? string.Empty, pattern, options).Success) .FailWith(AppendDiagnosticsTo($"Matching the command error output failed. Pattern: {pattern}{Environment.NewLine}")); return new AndConstraint(this); } @@ -222,7 +222,7 @@ public AndConstraint NuPkgContainsPatterns(string nupkg foreach (var pattern in filePatterns) { var directory = Path.GetDirectoryName(pattern); - var path = Path.Combine(unzipped, directory); + var path = Path.Combine(unzipped, directory ?? string.Empty); var searchPattern = Path.GetFileName(pattern); var condition = Directory.GetFiles(path, searchPattern).Length < 1; @@ -240,7 +240,7 @@ public AndConstraint NuPkgDoesNotContainPatterns(string foreach (var pattern in filePatterns) { var directory = Path.GetDirectoryName(pattern); - var path = Path.Combine(unzipped, directory); + var path = Path.Combine(unzipped, directory ?? string.Empty); var searchPattern = Path.GetFileName(pattern); var condition = Directory.Exists(path) && Directory.GetFiles(path, searchPattern).Length > 0; diff --git a/test/Microsoft.NET.TestFramework/Assertions/DirectoryInfoAssertions.cs b/test/Microsoft.NET.TestFramework/Assertions/DirectoryInfoAssertions.cs index a9982658f6f0..af759b019d41 100644 --- a/test/Microsoft.NET.TestFramework/Assertions/DirectoryInfoAssertions.cs +++ b/test/Microsoft.NET.TestFramework/Assertions/DirectoryInfoAssertions.cs @@ -99,7 +99,7 @@ public AndConstraint HaveDirectory(string expectedDir) Execute.Assertion.ForCondition(dir != null) .FailWith("Expected directory {0} cannot be found inside directory {1}.", expectedDir, _dirInfo.FullName); - return new AndConstraint(new DirectoryInfoAssertions(dir)); + return new AndConstraint(new DirectoryInfoAssertions(dir ?? new DirectoryInfo(string.Empty))); } public AndConstraint OnlyHaveFiles(IEnumerable expectedFiles, SearchOption searchOption = SearchOption.AllDirectories) diff --git a/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionFactAttribute.cs b/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionFactAttribute.cs index 583255c87145..ae359363546e 100644 --- a/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionFactAttribute.cs +++ b/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionFactAttribute.cs @@ -8,7 +8,7 @@ public class RequiresMSBuildVersionFactAttribute : FactAttribute /// /// Can be used to document the reason a test needs a specific version of MSBuild /// - public string Reason { get; set; } + public string? Reason { get; set; } public RequiresMSBuildVersionFactAttribute(string version) { diff --git a/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionTheoryAttribute.cs b/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionTheoryAttribute.cs index 690a2e45b964..86bc24729b77 100644 --- a/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionTheoryAttribute.cs +++ b/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionTheoryAttribute.cs @@ -8,7 +8,7 @@ public class RequiresMSBuildVersionTheoryAttribute : TheoryAttribute /// /// Can be used to document the reason a test needs a specific version of MSBuild /// - public string Reason { get; set; } + public string? Reason { get; set; } public RequiresMSBuildVersionTheoryAttribute(string version) { @@ -17,12 +17,12 @@ public RequiresMSBuildVersionTheoryAttribute(string version) public static void CheckForRequiredMSBuildVersion(FactAttribute attribute, string version) { - if (!Version.TryParse(TestContext.Current.ToolsetUnderTest.MSBuildVersion, out Version msbuildVersion)) + if (!Version.TryParse(TestContext.Current.ToolsetUnderTest.MSBuildVersion, out Version? msbuildVersion)) { attribute.Skip = $"Failed to determine the version of MSBuild ({TestContext.Current.ToolsetUnderTest.MSBuildVersion})."; return; } - if (!Version.TryParse(version, out Version requiredVersion)) + if (!Version.TryParse(version, out Version? requiredVersion)) { attribute.Skip = $"Failed to determine the version required by this test ({version})."; return; diff --git a/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionFactAttribute.cs b/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionFactAttribute.cs index 8e3b6430fe51..73121c780841 100644 --- a/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionFactAttribute.cs +++ b/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionFactAttribute.cs @@ -8,7 +8,7 @@ public class WindowsOnlyRequiresMSBuildVersionFactAttribute : FactAttribute /// /// Gets or sets the reason for potentially skipping the test if conditions are not met. /// - public string Reason { get; set; } + public string? Reason { get; set; } public WindowsOnlyRequiresMSBuildVersionFactAttribute(string version) { diff --git a/test/Microsoft.NET.TestFramework/Commands/AddReferenceCommand.cs b/test/Microsoft.NET.TestFramework/Commands/AddReferenceCommand.cs index 3a3fef587f64..65347841c7e0 100644 --- a/test/Microsoft.NET.TestFramework/Commands/AddReferenceCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/AddReferenceCommand.cs @@ -7,7 +7,7 @@ namespace Microsoft.NET.TestFramework.Commands { public class AddReferenceCommand : DotnetCommand { - private string _projectName = null; + private string? _projectName = null; public AddReferenceCommand(ITestOutputHelper log, params string[] args) : base(log, args) { diff --git a/test/Microsoft.NET.TestFramework/Commands/BuildCommand.cs b/test/Microsoft.NET.TestFramework/Commands/BuildCommand.cs index 2c884087235f..598288455c08 100644 --- a/test/Microsoft.NET.TestFramework/Commands/BuildCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/BuildCommand.cs @@ -9,12 +9,12 @@ public sealed class BuildCommand : MSBuildCommand { // Encourage use of the other overload, which is generally simpler to use [EditorBrowsable(EditorBrowsableState.Never)] - public BuildCommand(ITestOutputHelper log, string projectRootPath, string relativePathToProject = null) + public BuildCommand(ITestOutputHelper log, string projectRootPath, string? relativePathToProject = null) : base(log, "Build", projectRootPath, relativePathToProject) { } - public BuildCommand(TestAsset testAsset, string relativePathToProject = null) + public BuildCommand(TestAsset testAsset, string? relativePathToProject = null) : base(testAsset, "Build", relativePathToProject) { } diff --git a/test/Microsoft.NET.TestFramework/Commands/CleanCommand.cs b/test/Microsoft.NET.TestFramework/Commands/CleanCommand.cs index 94a00850f95a..ed3514ebd51a 100644 --- a/test/Microsoft.NET.TestFramework/Commands/CleanCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/CleanCommand.cs @@ -5,12 +5,12 @@ namespace Microsoft.NET.TestFramework.Commands { public sealed class CleanCommand : MSBuildCommand { - public CleanCommand(ITestOutputHelper log, string projectPath, string relativePathToProject = null) + public CleanCommand(ITestOutputHelper log, string projectPath, string? relativePathToProject = null) : base(log, "Clean", projectPath, relativePathToProject) { } - public CleanCommand(TestAsset testAsset, string relativePathToProject = null) + public CleanCommand(TestAsset testAsset, string? relativePathToProject = null) : base(testAsset, "Clean", relativePathToProject) { } diff --git a/test/Microsoft.NET.TestFramework/Commands/ComposeStoreCommand.cs b/test/Microsoft.NET.TestFramework/Commands/ComposeStoreCommand.cs index 61db5a4d7d5e..bbeaf4b22896 100644 --- a/test/Microsoft.NET.TestFramework/Commands/ComposeStoreCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/ComposeStoreCommand.cs @@ -14,12 +14,12 @@ public sealed class ComposeStoreCommand : MSBuildCommand { private const string PublishSubfolderName = "packages"; - public ComposeStoreCommand(ITestOutputHelper log, string projectPath, string relativePathToProject = null) + public ComposeStoreCommand(ITestOutputHelper log, string projectPath, string? relativePathToProject = null) : base(log, "ComposeStore", projectPath, relativePathToProject) { } - public override DirectoryInfo GetOutputDirectory(string targetFramework = "netcoreapp1.0", string configuration = "Debug", string runtimeIdentifier = "", string platformIdentifier = "") + public override DirectoryInfo GetOutputDirectory(string? targetFramework = "netcoreapp1.0", string? configuration = "Debug", string? runtimeIdentifier = "", string? platformIdentifier = "") { string output = Path.Combine(ProjectRootPath, "bin", BuildRelativeOutputPath(targetFramework, configuration, runtimeIdentifier, platformIdentifier)); return new DirectoryInfo(output); @@ -30,14 +30,15 @@ public string GetPublishedAppPath(string appName) return Path.Combine(GetOutputDirectory().FullName, $"{appName}.dll"); } - private string BuildRelativeOutputPath(string targetFramework, string configuration, string runtimeIdentifier, string platformIdentifier) + private string BuildRelativeOutputPath(string? targetFramework, string? configuration, string? runtimeIdentifier, string? platformIdentifier) { - if (runtimeIdentifier.Length == 0) + if (runtimeIdentifier?.Length == 0) { runtimeIdentifier = RuntimeInformation.RuntimeIdentifier; } - string arch = runtimeIdentifier.Substring(runtimeIdentifier.LastIndexOf("-") + 1); - return Path.Combine(platformIdentifier, configuration, arch, targetFramework, PublishSubfolderName); + + string arch = runtimeIdentifier?.Substring(runtimeIdentifier.LastIndexOf("-") + 1) ?? string.Empty; + return Path.Combine(platformIdentifier ?? string.Empty, configuration ?? string.Empty, arch, targetFramework ?? string.Empty, PublishSubfolderName); } } } diff --git a/test/Microsoft.NET.TestFramework/Commands/DotnetBuildCommand.cs b/test/Microsoft.NET.TestFramework/Commands/DotnetBuildCommand.cs index 42a4b9dab46c..8c5cce77583d 100644 --- a/test/Microsoft.NET.TestFramework/Commands/DotnetBuildCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/DotnetBuildCommand.cs @@ -13,7 +13,7 @@ public DotnetBuildCommand(ITestOutputHelper log, params string[] args) : base(lo public DotnetBuildCommand(TestAsset testAsset, params string[] args) : this(testAsset.Log, args) { - if (testAsset.TestProject != null) + if (testAsset.TestProject != null && testAsset.TestProject.Name is not null) { WorkingDirectory = Path.Combine(testAsset.TestRoot, testAsset.TestProject.Name); } diff --git a/test/Microsoft.NET.TestFramework/Commands/DotnetPublishCommand.cs b/test/Microsoft.NET.TestFramework/Commands/DotnetPublishCommand.cs index ad88c37be58e..3d97bfa509a7 100644 --- a/test/Microsoft.NET.TestFramework/Commands/DotnetPublishCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/DotnetPublishCommand.cs @@ -5,7 +5,7 @@ namespace Microsoft.NET.TestFramework.Commands { public class DotnetPublishCommand : DotnetCommand { - private string _runtime; + private string? _runtime; public DotnetPublishCommand(ITestOutputHelper log, params string[] args) : base(log) { diff --git a/test/Microsoft.NET.TestFramework/Commands/GetValuesCommand.cs b/test/Microsoft.NET.TestFramework/Commands/GetValuesCommand.cs index 7288f7a5bc54..956c6eea16e4 100644 --- a/test/Microsoft.NET.TestFramework/Commands/GetValuesCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/GetValuesCommand.cs @@ -22,7 +22,7 @@ public enum ValueType public string TargetName { get; set; } = "WriteValuesToFile"; - public string Configuration { get; set; } + public string? Configuration { get; set; } public List MetadataNames { get; set; } = new List(); public Dictionary Properties { get; } = new Dictionary(); @@ -43,10 +43,10 @@ public GetValuesCommand(ITestOutputHelper log, string projectPath, string target public GetValuesCommand(TestAsset testAsset, string valueName, ValueType valueType = ValueType.Property, - string targetFramework = null) + string? targetFramework = null) : base(testAsset, "WriteValuesToFile", relativePathToProject: null) { - _targetFramework = targetFramework ?? OutputPathCalculator.FromProject(ProjectFile, testAsset).TargetFramework; + _targetFramework = targetFramework ?? OutputPathCalculator.FromProject(ProjectFile, testAsset).TargetFramework ?? string.Empty; _valueName = valueName; _valueType = valueType; @@ -67,6 +67,11 @@ protected override SdkCommandSpec CreateCommand(IEnumerable args) var project = XDocument.Load(ProjectFile); + if(project.Root is null) + { + throw new InvalidOperationException($"The project file '{ProjectFile}' does not have a root element."); + } + var ns = project.Root.Name.Namespace; string linesAttribute; @@ -102,12 +107,12 @@ protected override SdkCommandSpec CreateCommand(IEnumerable args) new XAttribute("Name", TargetName), ShouldCompile ? new XAttribute("DependsOnTargets", DependsOnTargets) : null); - customAfterDirectoryBuildTargets.Root.Add(target); + customAfterDirectoryBuildTargets.Root?.Add(target); if (Properties.Count != 0) { propertyGroup = new XElement(ns + "PropertyGroup"); - customAfterDirectoryBuildTargets.Root.Add(propertyGroup); + customAfterDirectoryBuildTargets.Root?.Add(propertyGroup); foreach (var pair in Properties) { diff --git a/test/Microsoft.NET.TestFramework/Commands/ListPackageCommand.cs b/test/Microsoft.NET.TestFramework/Commands/ListPackageCommand.cs index 888b8e98fcb1..cf0a6717daf2 100644 --- a/test/Microsoft.NET.TestFramework/Commands/ListPackageCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/ListPackageCommand.cs @@ -7,7 +7,7 @@ namespace Microsoft.NET.TestFramework.Commands { public class ListPackageCommand : DotnetCommand { - private string _projectName = null; + private string? _projectName = null; public ListPackageCommand(ITestOutputHelper log, params string[] args) : base(log, args) { diff --git a/test/Microsoft.NET.TestFramework/Commands/ListReferenceCommand.cs b/test/Microsoft.NET.TestFramework/Commands/ListReferenceCommand.cs index 11e4d0c9b894..5414b6ea08bd 100644 --- a/test/Microsoft.NET.TestFramework/Commands/ListReferenceCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/ListReferenceCommand.cs @@ -7,7 +7,7 @@ namespace Microsoft.NET.TestFramework.Commands { public class ListReferenceCommand : DotnetCommand { - private string _projectName = null; + private string? _projectName = null; public ListReferenceCommand(ITestOutputHelper log, params string[] args) : base(log, args) { diff --git a/test/Microsoft.NET.TestFramework/Commands/MSBuildCommand.cs b/test/Microsoft.NET.TestFramework/Commands/MSBuildCommand.cs index 73f3416ea8f8..9ccfb366f631 100644 --- a/test/Microsoft.NET.TestFramework/Commands/MSBuildCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/MSBuildCommand.cs @@ -15,11 +15,11 @@ public class MSBuildCommand : TestCommand public string ProjectFile { get; } - public TestAsset TestAsset { get; } + public TestAsset? TestAsset { get; } public string FullPathProjectFile => Path.Combine(ProjectRootPath, ProjectFile); - public MSBuildCommand(ITestOutputHelper log, string target, string projectRootPath, string relativePathToProject = null) + public MSBuildCommand(ITestOutputHelper log, string target, string projectRootPath, string? relativePathToProject = null) : base(log) { Target = target; @@ -29,13 +29,13 @@ public MSBuildCommand(ITestOutputHelper log, string target, string projectRootPa ProjectFile = FindProjectFile(ref _projectRootPath, relativePathToProject); } - public MSBuildCommand(TestAsset testAsset, string target, string relativePathToProject = null) + public MSBuildCommand(TestAsset testAsset, string target, string? relativePathToProject = null) : this(testAsset.Log, target, testAsset.TestRoot, relativePathToProject ?? testAsset.TestProject?.Name) { TestAsset = testAsset; } - internal static string FindProjectFile(ref string projectRootPath, string relativePathToProject) + internal static string FindProjectFile(ref string projectRootPath, string? relativePathToProject) { if (File.Exists(projectRootPath) && string.IsNullOrEmpty(relativePathToProject)) { @@ -68,7 +68,7 @@ internal static string FindProjectFile(ref string projectRootPath, string relati return buildProjectFiles[0]; } - public virtual DirectoryInfo GetOutputDirectory(string targetFramework = null, string configuration = "Debug", string runtimeIdentifier = null, string platform = null) + public virtual DirectoryInfo GetOutputDirectory(string? targetFramework = null, string configuration = "Debug", string? runtimeIdentifier = null, string? platform = null) { if (TestAsset != null) { @@ -84,7 +84,7 @@ public virtual DirectoryInfo GetOutputDirectory(string targetFramework = null, s return new DirectoryInfo(output); } - public virtual DirectoryInfo GetIntermediateDirectory(string targetFramework = null, string configuration = "Debug", string runtimeIdentifier = null) + public virtual DirectoryInfo GetIntermediateDirectory(string? targetFramework = null, string configuration = "Debug", string? runtimeIdentifier = null) { if (TestAsset != null) { diff --git a/test/Microsoft.NET.TestFramework/Commands/NuGetExeRestoreCommand.cs b/test/Microsoft.NET.TestFramework/Commands/NuGetExeRestoreCommand.cs index 0d6e8515e1b3..a31545b142ab 100644 --- a/test/Microsoft.NET.TestFramework/Commands/NuGetExeRestoreCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/NuGetExeRestoreCommand.cs @@ -10,13 +10,13 @@ public class NuGetExeRestoreCommand : TestCommand public string ProjectFile { get; } - public string NuGetExeVersion { get; set; } + public string? NuGetExeVersion { get; set; } public string FullPathProjectFile => Path.Combine(ProjectRootPath, ProjectFile); - public string PackagesDirectory { get; set; } + public string? PackagesDirectory { get; set; } - public NuGetExeRestoreCommand(ITestOutputHelper log, string projectRootPath, string relativePathToProject = null) : base(log) + public NuGetExeRestoreCommand(ITestOutputHelper log, string projectRootPath, string? relativePathToProject = null) : base(log) { _projectRootPath = projectRootPath; ProjectFile = MSBuildCommand.FindProjectFile(ref _projectRootPath, relativePathToProject); @@ -31,7 +31,7 @@ protected override SdkCommandSpec CreateCommand(IEnumerable args) newArgs.Add(FullPathProjectFile); newArgs.Add("-PackagesDirectory"); - newArgs.Add(PackagesDirectory ?? TestContext.Current.NuGetCachePath); + newArgs.Add(PackagesDirectory ?? TestContext.Current.NuGetCachePath ?? string.Empty); newArgs.AddRange(args); @@ -43,12 +43,12 @@ protected override SdkCommandSpec CreateCommand(IEnumerable args) var nugetExePath = TestContext.Current.NuGetExePath; if (!string.IsNullOrEmpty(NuGetExeVersion)) { - nugetExePath = Path.Combine(Path.GetDirectoryName(nugetExePath), NuGetExeVersion, "nuget.exe"); + nugetExePath = Path.Combine(Path.GetDirectoryName(nugetExePath) ?? string.Empty, NuGetExeVersion, "nuget.exe"); } if (!File.Exists(nugetExePath)) { - string directory = Path.GetDirectoryName(nugetExePath); + string directory = Path.GetDirectoryName(nugetExePath) ?? string.Empty; if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); diff --git a/test/Microsoft.NET.TestFramework/Commands/PackCommand.cs b/test/Microsoft.NET.TestFramework/Commands/PackCommand.cs index d2944f953b93..5ea180ba8e01 100644 --- a/test/Microsoft.NET.TestFramework/Commands/PackCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/PackCommand.cs @@ -5,19 +5,19 @@ namespace Microsoft.NET.TestFramework.Commands { public sealed class PackCommand : MSBuildCommand { - public PackCommand(ITestOutputHelper log, string projectPath, string relativePathToProject = null) + public PackCommand(ITestOutputHelper log, string projectPath, string? relativePathToProject = null) : base(log, "Pack", projectPath, relativePathToProject) { } - public PackCommand(TestAsset testAsset, string relativePathToProject = null) + public PackCommand(TestAsset testAsset, string? relativePathToProject = null) : base(testAsset, "Pack", relativePathToProject) { } - public string GetIntermediateNuspecPath(string packageId = null, string configuration = "Debug", string packageVersion = "1.0.0") + public string GetIntermediateNuspecPath(string? packageId = null, string configuration = "Debug", string packageVersion = "1.0.0") { if (packageId == null) { @@ -27,7 +27,7 @@ public string GetIntermediateNuspecPath(string packageId = null, string configur return Path.Combine(GetBaseIntermediateDirectory().FullName, configuration, $"{packageId}.{packageVersion}.nuspec"); } - public string GetNuGetPackage(string packageId = null, string configuration = "Debug", string packageVersion = "1.0.0") + public string GetNuGetPackage(string? packageId = null, string configuration = "Debug", string packageVersion = "1.0.0") { if (packageId == null) { diff --git a/test/Microsoft.NET.TestFramework/Commands/PublishCommand.cs b/test/Microsoft.NET.TestFramework/Commands/PublishCommand.cs index b46caf82e96d..d03d788fb37d 100644 --- a/test/Microsoft.NET.TestFramework/Commands/PublishCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/PublishCommand.cs @@ -16,13 +16,13 @@ public PublishCommand(ITestOutputHelper log, string projectPath) { } - public PublishCommand(TestAsset testAsset, string relativePathToProject = null) + public PublishCommand(TestAsset testAsset, string? relativePathToProject = null) : base(testAsset, "Publish", relativePathToProject) { } - public override DirectoryInfo GetOutputDirectory(string targetFramework = null, string configuration = "Debug", string runtimeIdentifier = "", string platformIdentifier = "") + public override DirectoryInfo GetOutputDirectory(string? targetFramework = null, string configuration = "Debug", string? runtimeIdentifier = "", string? platformIdentifier = "") { if (TestAsset != null) { diff --git a/test/Microsoft.NET.TestFramework/Commands/RebuildCommand.cs b/test/Microsoft.NET.TestFramework/Commands/RebuildCommand.cs index 4d820b5845a2..0d8aa5964997 100644 --- a/test/Microsoft.NET.TestFramework/Commands/RebuildCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/RebuildCommand.cs @@ -5,7 +5,7 @@ namespace Microsoft.NET.TestFramework.Commands { public sealed class RebuildCommand : MSBuildCommand { - public RebuildCommand(ITestOutputHelper log, string projectPath, string relativePathToProject = null) + public RebuildCommand(ITestOutputHelper log, string projectPath, string? relativePathToProject = null) : base(log, "Rebuild", projectPath, relativePathToProject) { } diff --git a/test/Microsoft.NET.TestFramework/Commands/RemoveReferenceCommand.cs b/test/Microsoft.NET.TestFramework/Commands/RemoveReferenceCommand.cs index 4147cf08de94..2017398215de 100644 --- a/test/Microsoft.NET.TestFramework/Commands/RemoveReferenceCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/RemoveReferenceCommand.cs @@ -7,7 +7,7 @@ namespace Microsoft.NET.TestFramework.Commands { public class RemoveReferenceCommand : DotnetCommand { - private string _projectName = null; + private string? _projectName = null; public RemoveReferenceCommand(ITestOutputHelper log, params string[] args) : base(log, args) { diff --git a/test/Microsoft.NET.TestFramework/Commands/RestoreCommand.cs b/test/Microsoft.NET.TestFramework/Commands/RestoreCommand.cs index 137bd5996c5f..8230a3706222 100644 --- a/test/Microsoft.NET.TestFramework/Commands/RestoreCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/RestoreCommand.cs @@ -9,12 +9,12 @@ public sealed class RestoreCommand : MSBuildCommand { // Encourage use of the other overload, which is generally simpler to use [EditorBrowsable(EditorBrowsableState.Never)] - public RestoreCommand(ITestOutputHelper log, string projectPath, string relativePathToProject = null) + public RestoreCommand(ITestOutputHelper log, string projectPath, string? relativePathToProject = null) : base(log, "Restore", projectPath, relativePathToProject) { } - public RestoreCommand(TestAsset testAsset, string relativePathToProject = null) + public RestoreCommand(TestAsset testAsset, string? relativePathToProject = null) : base(testAsset, "Restore", relativePathToProject) { } diff --git a/test/Microsoft.NET.TestFramework/Commands/SdkCommandSpec.cs b/test/Microsoft.NET.TestFramework/Commands/SdkCommandSpec.cs index a3d47498f1e6..40db520c2ccc 100644 --- a/test/Microsoft.NET.TestFramework/Commands/SdkCommandSpec.cs +++ b/test/Microsoft.NET.TestFramework/Commands/SdkCommandSpec.cs @@ -8,14 +8,14 @@ namespace Microsoft.NET.TestFramework.Commands { public class SdkCommandSpec { - public string FileName { get; set; } + public string? FileName { get; set; } public List Arguments { get; set; } = new List(); public Dictionary Environment { get; set; } = new Dictionary(); public List EnvironmentToRemove { get; } = new List(); - public string WorkingDirectory { get; set; } + public string? WorkingDirectory { get; set; } private string EscapeArgs() { diff --git a/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs b/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs index 55b8c0181e83..d46175d4e229 100644 --- a/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs +++ b/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs @@ -14,15 +14,15 @@ public abstract class TestCommand public ITestOutputHelper Log { get; } - public string WorkingDirectory { get; set; } + public string? WorkingDirectory { get; set; } public List Arguments { get; set; } = new List(); public List EnvironmentToRemove { get; } = new List(); // These only work via Execute(), not when using GetProcessStartInfo() - public Action CommandOutputHandler { get; set; } - public Action ProcessStartedHandler { get; set; } + public Action? CommandOutputHandler { get; set; } + public Action? ProcessStartedHandler { get; set; } protected TestCommand(ITestOutputHelper log) { diff --git a/test/Microsoft.NET.TestFramework/ConflictResolutionAssets.cs b/test/Microsoft.NET.TestFramework/ConflictResolutionAssets.cs index 5e17bb7f0971..50820e00bf83 100644 --- a/test/Microsoft.NET.TestFramework/ConflictResolutionAssets.cs +++ b/test/Microsoft.NET.TestFramework/ConflictResolutionAssets.cs @@ -61,7 +61,7 @@ public static IEnumerable> ConflictResolutionDependencies foreach (var dependency in netStandardDependencies.Elements("dependency")) { - yield return Tuple.Create(dependency.Attribute("id").Value, dependency.Attribute("version").Value); + yield return Tuple.Create(dependency.Attribute("id")?.Value ?? string.Empty, dependency.Attribute("version")?.Value ?? string.Empty); } yield return Tuple.Create("System.Diagnostics.TraceSource", "4.0.0"); diff --git a/test/Microsoft.NET.TestFramework/EnvironmentInfo.cs b/test/Microsoft.NET.TestFramework/EnvironmentInfo.cs index 813943ca1bd1..a1ef8b832be7 100644 --- a/test/Microsoft.NET.TestFramework/EnvironmentInfo.cs +++ b/test/Microsoft.NET.TestFramework/EnvironmentInfo.cs @@ -19,7 +19,7 @@ public static string ExecutableExtension } } - public static string GetCompatibleRid(string targetFramework = null) + public static string GetCompatibleRid(string? targetFramework = null) { string rid = RuntimeInformation.RuntimeIdentifier; @@ -62,7 +62,7 @@ public static string GetCompatibleRid(string targetFramework = null) // able to run on the current OS public static bool SupportsTargetFramework(string targetFramework) { - NuGetFramework nugetFramework = null; + NuGetFramework? nugetFramework = null; try { nugetFramework = NuGetFramework.Parse(targetFramework); @@ -101,7 +101,7 @@ public static bool SupportsTargetFramework(string targetFramework) return false; } } - else if (Version.TryParse(versionString, out Version osVersion)) + else if (Version.TryParse(versionString, out Version? osVersion)) { if (osId.Equals("fedora", StringComparison.OrdinalIgnoreCase)) { diff --git a/test/Microsoft.NET.TestFramework/FileConstants.cs b/test/Microsoft.NET.TestFramework/FileConstants.cs index 37ac9b06e66d..54902a4e0b5d 100644 --- a/test/Microsoft.NET.TestFramework/FileConstants.cs +++ b/test/Microsoft.NET.TestFramework/FileConstants.cs @@ -9,7 +9,7 @@ public static class FileConstants public static readonly string DynamicLibSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll" : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? ".dylib" : ".so"; - public static readonly string UserProfileFolder = Environment.GetEnvironmentVariable( + public static readonly string? UserProfileFolder = Environment.GetEnvironmentVariable( RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "USERPROFILE" : "HOME"); } diff --git a/test/Microsoft.NET.TestFramework/InMemoryLoggerProvider.cs b/test/Microsoft.NET.TestFramework/InMemoryLoggerProvider.cs index 890613392f1b..e97c2ed7e68e 100644 --- a/test/Microsoft.NET.TestFramework/InMemoryLoggerProvider.cs +++ b/test/Microsoft.NET.TestFramework/InMemoryLoggerProvider.cs @@ -1,10 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#pragma warning disable IDE0240 -#nullable enable -#pragma warning restore IDE0240 - using Microsoft.Extensions.Logging; namespace Microsoft.NET.TestFramework diff --git a/test/Microsoft.NET.TestFramework/Microsoft.NET.TestFramework.csproj b/test/Microsoft.NET.TestFramework/Microsoft.NET.TestFramework.csproj index 181ea7cfd6b5..5d3d106f4d23 100644 --- a/test/Microsoft.NET.TestFramework/Microsoft.NET.TestFramework.csproj +++ b/test/Microsoft.NET.TestFramework/Microsoft.NET.TestFramework.csproj @@ -4,6 +4,7 @@ false + enable diff --git a/test/Microsoft.NET.TestFramework/Mock/FileSystemMockBuilder.cs b/test/Microsoft.NET.TestFramework/Mock/FileSystemMockBuilder.cs index 2648c0b6bf8e..944ce7dc8d34 100644 --- a/test/Microsoft.NET.TestFramework/Mock/FileSystemMockBuilder.cs +++ b/test/Microsoft.NET.TestFramework/Mock/FileSystemMockBuilder.cs @@ -11,9 +11,9 @@ namespace Microsoft.Extensions.DependencyModel.Tests public class FileSystemMockBuilder { private readonly List _actions = new(); - private MockFileSystemModel _mockFileSystemModel; - public string TemporaryFolder { get; set; } - public string WorkingDirectory { get; set; } + private MockFileSystemModel? _mockFileSystemModel; + public string? TemporaryFolder { get; set; } + public string? WorkingDirectory { get; set; } internal static IFileSystem Empty { get; } = Create().Build(); @@ -24,18 +24,18 @@ public static FileSystemMockBuilder Create() public FileSystemMockBuilder AddFile(string name, string content = "") { - _actions.Add(() => _mockFileSystemModel.CreateDirectory(Path.GetDirectoryName(name))); - _actions.Add(() => _mockFileSystemModel.CreateFile(name, content)); + _actions.Add(() => _mockFileSystemModel?.CreateDirectory(Path.GetDirectoryName(name) ?? string.Empty)); + _actions.Add(() => _mockFileSystemModel?.CreateFile(name, content)); return this; } public FileSystemMockBuilder AddFiles(string basePath, params string[] files) { - _actions.Add(() => _mockFileSystemModel.CreateDirectory(basePath)); + _actions.Add(() => _mockFileSystemModel?.CreateDirectory(basePath)); foreach (string file in files) { - _actions.Add(() => _mockFileSystemModel.CreateFile(Path.Combine(basePath, file), "")); + _actions.Add(() => _mockFileSystemModel?.CreateFile(Path.Combine(basePath, file), "")); } return this; @@ -67,9 +67,9 @@ internal IFileSystem Build() private class MockFileSystemModel { - public MockFileSystemModel(string temporaryFolder, - FileSystemRoot files = null, - string fileSystemMockWorkingDirectory = null) + public MockFileSystemModel(string? temporaryFolder, + FileSystemRoot? files = null, + string? fileSystemMockWorkingDirectory = null) { if (fileSystemMockWorkingDirectory == null) { @@ -125,7 +125,7 @@ public void CreateDirectory(string path) { PathModel pathModel = CreateFullPathModel(path); - if (!Files.Volume.TryGetValue(pathModel.Volume, out DirectoryNode current)) + if (!Files.Volume.TryGetValue(pathModel.Volume, out DirectoryNode? current)) { current = new DirectoryNode(); current = Files.Volume.GetOrAdd(pathModel.Volume, current); @@ -209,18 +209,18 @@ public void CreateFile(string path, string content) throw new FileNotFoundException($"Could not find file '{path}'"); } - public IEnumerable EnumerateDirectory( + public IEnumerable? EnumerateDirectory( string path, Func, IEnumerable> predicate) { DirectoryNode current = GetParentOfDirectoryNode(path); PathModel pathModel = new(path); - DirectoryNode directoryNode = current.Subs[pathModel.FileOrDirectoryName()] as DirectoryNode; + DirectoryNode? directoryNode = current.Subs[pathModel.FileOrDirectoryName()] as DirectoryNode; Debug.Assert(directoryNode != null, nameof(directoryNode) + " != null"); - return predicate(directoryNode.Subs); + return predicate(directoryNode?.Subs ?? new()); } public DirectoryNode GetParentOfDirectoryNode(string path) @@ -503,7 +503,7 @@ public void Delete(string path) // facade private class DirectoryMock : IDirectory { - private readonly MockFileSystemModel _files; + private readonly MockFileSystemModel? _files; public DirectoryMock(MockFileSystemModel files) { @@ -517,7 +517,7 @@ public bool Exists(string path) { if (path == null) throw new ArgumentNullException(nameof(path)); - if (_files.TryGetNodeParent(path, out DirectoryNode current)) + if (_files is not null && _files.TryGetNodeParent(path, out DirectoryNode current)) { PathModel pathModel = new(path); @@ -530,47 +530,47 @@ public bool Exists(string path) public ITemporaryDirectory CreateTemporaryDirectory() { - TemporaryDirectoryMock temporaryDirectoryMock = new(_files.TemporaryFolder); + TemporaryDirectoryMock temporaryDirectoryMock = new(_files?.TemporaryFolder); CreateDirectory(temporaryDirectoryMock.DirectoryPath); return temporaryDirectoryMock; } - public IEnumerable EnumerateDirectories(string path) + public IEnumerable? EnumerateDirectories(string path) { if (path == null) throw new ArgumentNullException(nameof(path)); - return _files.EnumerateDirectory(path, + return _files?.EnumerateDirectory(path, subs => subs.Where(s => s.Value is DirectoryNode) .Select(s => Path.Combine(path, s.Key))); } - public IEnumerable EnumerateFiles(string path) + public IEnumerable? EnumerateFiles(string path) { if (path == null) throw new ArgumentNullException(nameof(path)); - return _files.EnumerateDirectory(path, + return _files?.EnumerateDirectory(path, subs => subs.Where(s => s.Value is FileNode) .Select(s => Path.Combine(path, s.Key))); } - public IEnumerable EnumerateFileSystemEntries(string path) + public IEnumerable? EnumerateFileSystemEntries(string path) { if (path == null) throw new ArgumentNullException(nameof(path)); - return _files.EnumerateDirectory(path, + return _files?.EnumerateDirectory(path, subs => subs.Select(s => Path.Combine(path, s.Key))); } - public string GetCurrentDirectory() + public string? GetCurrentDirectory() { - return _files.WorkingDirectory; + return _files?.WorkingDirectory; } - public void CreateDirectory(string path) + public void CreateDirectory(string? path) { if (path == null) throw new ArgumentNullException(nameof(path)); - _files.CreateDirectory(path); + _files?.CreateDirectory(path); } public string CreateTemporarySubdirectory() @@ -582,20 +582,20 @@ public void Delete(string path, bool recursive) { if (path == null) throw new ArgumentNullException(nameof(path)); - DirectoryNode parentOfPath = _files.GetParentOfDirectoryNode(path); + DirectoryNode? parentOfPath = _files?.GetParentOfDirectoryNode(path); PathModel pathModel = new(path); if (recursive) { - parentOfPath.Subs.TryRemove(pathModel.FileOrDirectoryName(), out _); + parentOfPath?.Subs.TryRemove(pathModel.FileOrDirectoryName(), out _); } else { - if (EnumerateFiles(path).Any()) + if (EnumerateFiles(path)?.Any() ?? false) { throw new IOException("Directory not empty"); } - parentOfPath.Subs.TryRemove(pathModel.FileOrDirectoryName(), out _); + parentOfPath?.Subs.TryRemove(pathModel.FileOrDirectoryName(), out _); } } @@ -611,14 +611,14 @@ public void Move(string source, string destination) throw new ArgumentNullException(nameof(destination)); } - DirectoryNode sourceParent - = _files.GetParentOfDirectoryNode(source); + DirectoryNode? sourceParent + = _files?.GetParentOfDirectoryNode(source); PathModel parentPathModel = new(source); - IFileSystemTreeNode sourceNode = sourceParent.Subs[parentPathModel.FileOrDirectoryName()]; + IFileSystemTreeNode? sourceNode = sourceParent?.Subs[parentPathModel.FileOrDirectoryName()]; - if (_files.TryGetNodeParent(destination, out DirectoryNode current) && current != null) + if (_files is not null && _files.TryGetNodeParent(destination, out DirectoryNode current) && current != null) { PathModel destinationPathModel = new(destination); @@ -632,9 +632,11 @@ DirectoryNode sourceParent throw new IOException($"Cannot create {destination} because a file or" + " directory with the same name already exists"); } - - sourceNode = current.Subs.GetOrAdd(destinationPathModel.FileOrDirectoryName(), sourceNode); - sourceParent.Subs.TryRemove(parentPathModel.FileOrDirectoryName(), out _); + if(sourceNode is not null) + { + sourceNode = current.Subs.GetOrAdd(destinationPathModel.FileOrDirectoryName(), sourceNode); + } + sourceParent?.Subs.TryRemove(parentPathModel.FileOrDirectoryName(), out _); } else { @@ -671,14 +673,14 @@ public FileNode(string content) private class TemporaryDirectoryMock : ITemporaryDirectoryMock { - public TemporaryDirectoryMock(string temporaryDirectory) + public TemporaryDirectoryMock(string? temporaryDirectory) { DirectoryPath = temporaryDirectory; } public bool DisposedTemporaryDirectory { get; private set; } - public string DirectoryPath { get; } + public string? DirectoryPath { get; } public void Dispose() { diff --git a/test/Microsoft.NET.TestFramework/NuGetTestLogger.cs b/test/Microsoft.NET.TestFramework/NuGetTestLogger.cs index 66c86fef5405..7a08d1ab1f2c 100644 --- a/test/Microsoft.NET.TestFramework/NuGetTestLogger.cs +++ b/test/Microsoft.NET.TestFramework/NuGetTestLogger.cs @@ -8,7 +8,7 @@ namespace Microsoft.NET.TestFramework { public class NuGetTestLogger : ILogger { - private readonly ITestOutputHelper _output; + private readonly ITestOutputHelper? _output; public NuGetTestLogger() { @@ -95,7 +95,7 @@ private void DumpMessage(string level, string data) public void Clear() { - string msg; + string? msg; while (Messages.TryDequeue(out msg)) { // do nothing diff --git a/test/Microsoft.NET.TestFramework/NuGetTransientErrorDetector.cs b/test/Microsoft.NET.TestFramework/NuGetTransientErrorDetector.cs index 444a353636fe..d87b966eb9e0 100644 --- a/test/Microsoft.NET.TestFramework/NuGetTransientErrorDetector.cs +++ b/test/Microsoft.NET.TestFramework/NuGetTransientErrorDetector.cs @@ -13,9 +13,9 @@ public static class NuGetTransientErrorDetector "An error occurred while sending the request" }; - public static bool IsTransientError(string errorMessage) + public static bool IsTransientError(string? errorMessage) { - return errorMessage.Contains("NuGet.targets") && _errorSubstrings.Any(errorMessage.Contains); + return errorMessage is not null && errorMessage.Contains("NuGet.targets") && _errorSubstrings.Any(errorMessage.Contains); } } } diff --git a/test/Microsoft.NET.TestFramework/OutputPathCalculator.cs b/test/Microsoft.NET.TestFramework/OutputPathCalculator.cs index 18fd2d8c9cfa..a01f24a4d349 100644 --- a/test/Microsoft.NET.TestFramework/OutputPathCalculator.cs +++ b/test/Microsoft.NET.TestFramework/OutputPathCalculator.cs @@ -5,25 +5,25 @@ namespace Microsoft.NET.TestFramework { public class OutputPathCalculator { - public string ProjectPath { get; set; } + public string? ProjectPath { get; set; } public bool UseArtifactsOutput { get; set; } public bool IncludeProjectNameInArtifactsPaths { get; set; } - public string ArtifactsPath { get; set; } - public string TargetFramework { get; set; } - public string TargetFrameworks { get; set; } + public string? ArtifactsPath { get; set; } + public string? TargetFramework { get; set; } + public string? TargetFrameworks { get; set; } - public string RuntimeIdentifier { get; set; } + public string? RuntimeIdentifier { get; set; } public bool IsSdkProject { get; set; } = true; public static OutputPathCalculator FromProject(string projectPath, TestAsset testAsset) { - return FromProject(projectPath, testAsset?.TestProject); + return FromProject(projectPath, testAsset.TestProject); } - public static OutputPathCalculator FromProject(string projectPath, TestProject testProject = null) + public static OutputPathCalculator FromProject(string? projectPath, TestProject? testProject = null) { - string originalProjectPath = projectPath; + string? originalProjectPath = projectPath; if (!File.Exists(projectPath) && Directory.Exists(projectPath)) { @@ -31,7 +31,7 @@ public static OutputPathCalculator FromProject(string projectPath, TestProject t } // Support passing in the root test path and looking in subfolder specified by testProject - if (projectPath == null && testProject != null) + if (projectPath == null && testProject != null && testProject.Name is not null && originalProjectPath is not null) { projectPath = Path.Combine(originalProjectPath, testProject.Name); @@ -70,21 +70,27 @@ public static OutputPathCalculator FromProject(string projectPath, TestProject t if (calculator.IncludeProjectNameInArtifactsPaths) { - string directoryBuildPropsFile = GetDirectoryBuildPropsPath(projectPath); + string? directoryBuildPropsFile = GetDirectoryBuildPropsPath(projectPath); if (directoryBuildPropsFile == null) { throw new InvalidOperationException("Couldn't find Directory.Build.props for test project " + projectPath); } - calculator.ArtifactsPath = Path.Combine(Path.GetDirectoryName(directoryBuildPropsFile), "artifacts"); + calculator.ArtifactsPath = Path.Combine(Path.GetDirectoryName(directoryBuildPropsFile) ?? string.Empty, "artifacts"); } else { - calculator.ArtifactsPath = Path.Combine(Path.GetDirectoryName(projectPath), "artifacts"); + calculator.ArtifactsPath = Path.Combine(Path.GetDirectoryName(projectPath) ?? string.Empty, "artifacts"); } } else { var project = XDocument.Load(projectPath); + + if (project.Root is null) + { + throw new InvalidOperationException($"The project file '{projectPath}' does not have a root element."); + } + var ns = project.Root.Name.Namespace; var useArtifactsOutputElement = project.Root.Elements(ns + "PropertyGroup").Elements(ns + "UseArtifactsOutput").FirstOrDefault(); @@ -94,7 +100,7 @@ public static OutputPathCalculator FromProject(string projectPath, TestProject t if (calculator.UseArtifactsOutput) { calculator.IncludeProjectNameInArtifactsPaths = false; - calculator.ArtifactsPath = Path.Combine(Path.GetDirectoryName(projectPath), "artifacts"); + calculator.ArtifactsPath = Path.Combine(Path.GetDirectoryName(projectPath) ?? string.Empty, "artifacts"); } } @@ -120,6 +126,10 @@ public static OutputPathCalculator FromProject(string projectPath, TestProject t if (directoryBuildPropsFile != null) { var dbp = XDocument.Load(directoryBuildPropsFile); + if (dbp.Root is null) + { + throw new InvalidOperationException($"The project file '{directoryBuildPropsFile}' does not have a root element."); + } var dbpns = dbp.Root.Name.Namespace; var dbpUsesArtifacts = dbp.Root.Elements(dbpns + "PropertyGroup").Elements(dbpns + "UseArtifactsOutput").FirstOrDefault(); @@ -130,7 +140,7 @@ public static OutputPathCalculator FromProject(string projectPath, TestProject t if (calculator.UseArtifactsOutput) { calculator.IncludeProjectNameInArtifactsPaths = true; - calculator.ArtifactsPath = Path.Combine(Path.GetDirectoryName(directoryBuildPropsFile), "artifacts"); + calculator.ArtifactsPath = Path.Combine(Path.GetDirectoryName(directoryBuildPropsFile) ?? string.Empty, "artifacts"); } } } @@ -139,9 +149,9 @@ public static OutputPathCalculator FromProject(string projectPath, TestProject t return calculator; } - private static string GetDirectoryBuildPropsPath(string projectPath) + private static string? GetDirectoryBuildPropsPath(string projectPath) { - string folder = Path.GetDirectoryName(projectPath); + string? folder = Path.GetDirectoryName(projectPath); while (folder != null) { string directoryBuildPropsFile = Path.Combine(folder, "Directory.Build.props"); @@ -159,7 +169,7 @@ public bool IsMultiTargeted() return !string.IsNullOrEmpty(TargetFrameworks); } - public string GetOutputDirectory(string targetFramework = null, string configuration = "Debug", string runtimeIdentifier = "", string platform = "") + public string GetOutputDirectory(string? targetFramework = null, string configuration = "Debug", string? runtimeIdentifier = "", string? platform = "") { if (UseArtifactsOutput) { @@ -179,11 +189,11 @@ public string GetOutputDirectory(string targetFramework = null, string configura if (IncludeProjectNameInArtifactsPaths) { - return Path.Combine(ArtifactsPath, "bin", Path.GetFileNameWithoutExtension(ProjectPath), pivot); + return Path.Combine(ArtifactsPath ?? string.Empty, "bin", Path.GetFileNameWithoutExtension(ProjectPath) ?? string.Empty, pivot); } else { - return Path.Combine(ArtifactsPath, "bin", pivot); + return Path.Combine(ArtifactsPath ?? string.Empty, "bin", pivot); } } else @@ -195,18 +205,18 @@ public string GetOutputDirectory(string targetFramework = null, string configura if (IsSdkProject) { - string output = Path.Combine(Path.GetDirectoryName(ProjectPath), "bin", platform, configuration, targetFramework, runtimeIdentifier); + string output = Path.Combine(Path.GetDirectoryName(ProjectPath) ?? string.Empty, "bin", platform, configuration, targetFramework, runtimeIdentifier); return output; } else { - string output = Path.Combine(Path.GetDirectoryName(ProjectPath), "bin", platform, configuration); + string output = Path.Combine(Path.GetDirectoryName(ProjectPath) ?? string.Empty, "bin", platform, configuration); return output; } } } - public string GetPublishDirectory(string targetFramework = null, string configuration = "Debug", string runtimeIdentifier = "", string platform = "") + public string GetPublishDirectory(string? targetFramework = null, string configuration = "Debug", string? runtimeIdentifier = "", string? platform = "") { if (UseArtifactsOutput) { @@ -226,11 +236,11 @@ public string GetPublishDirectory(string targetFramework = null, string configur if (IncludeProjectNameInArtifactsPaths) { - return Path.Combine(ArtifactsPath, "publish", Path.GetFileNameWithoutExtension(ProjectPath), pivot); + return Path.Combine(ArtifactsPath ?? string.Empty, "publish", Path.GetFileNameWithoutExtension(ProjectPath) ?? string.Empty, pivot); } else { - return Path.Combine(ArtifactsPath, "publish", pivot); + return Path.Combine(ArtifactsPath ?? string.Empty, "publish", pivot); } } else @@ -240,12 +250,12 @@ public string GetPublishDirectory(string targetFramework = null, string configur runtimeIdentifier ??= RuntimeIdentifier ?? string.Empty; platform ??= string.Empty; - string output = Path.Combine(Path.GetDirectoryName(ProjectPath), "bin", platform, configuration, targetFramework, runtimeIdentifier, "publish"); + string output = Path.Combine(Path.GetDirectoryName(ProjectPath) ?? string.Empty, "bin", platform, configuration, targetFramework, runtimeIdentifier, "publish"); return output; } } - public string GetIntermediateDirectory(string targetFramework = null, string configuration = "Debug", string runtimeIdentifier = "") + public string GetIntermediateDirectory(string? targetFramework = null, string configuration = "Debug", string? runtimeIdentifier = "") { if (UseArtifactsOutput) { @@ -265,11 +275,11 @@ public string GetIntermediateDirectory(string targetFramework = null, string con if (IncludeProjectNameInArtifactsPaths) { - return Path.Combine(ArtifactsPath, "obj", Path.GetFileNameWithoutExtension(ProjectPath), pivot); + return Path.Combine(ArtifactsPath ?? string.Empty, "obj", Path.GetFileNameWithoutExtension(ProjectPath) ?? string.Empty, pivot); } else { - return Path.Combine(ArtifactsPath, "obj", pivot); + return Path.Combine(ArtifactsPath ?? string.Empty, "obj", pivot); } } @@ -278,7 +288,7 @@ public string GetIntermediateDirectory(string targetFramework = null, string con configuration = configuration ?? string.Empty; runtimeIdentifier = runtimeIdentifier ?? RuntimeIdentifier ?? string.Empty; - string output = Path.Combine(Path.GetDirectoryName(ProjectPath), "obj", configuration, targetFramework, runtimeIdentifier); + string output = Path.Combine(Path.GetDirectoryName(ProjectPath) ?? string.Empty, "obj", configuration, targetFramework, runtimeIdentifier); return output; } @@ -286,11 +296,11 @@ public string GetPackageDirectory(string configuration = "Debug") { if (UseArtifactsOutput) { - return Path.Combine(ArtifactsPath, "package", configuration.ToLowerInvariant()); + return Path.Combine(ArtifactsPath ?? string.Empty, "package", configuration.ToLowerInvariant()); } else { - return Path.Combine(Path.GetDirectoryName(ProjectPath), "bin", configuration); + return Path.Combine(Path.GetDirectoryName(ProjectPath) ?? string.Empty, "bin", configuration); } } } diff --git a/test/Microsoft.NET.TestFramework/ProjectConstruction/TestProject.cs b/test/Microsoft.NET.TestFramework/ProjectConstruction/TestProject.cs index 0299e803f6c4..0c329ae25b30 100644 --- a/test/Microsoft.NET.TestFramework/ProjectConstruction/TestProject.cs +++ b/test/Microsoft.NET.TestFramework/ProjectConstruction/TestProject.cs @@ -9,7 +9,7 @@ namespace Microsoft.NET.TestFramework.ProjectConstruction { public class TestProject { - public TestProject([CallerMemberName] string name = null) + public TestProject([CallerMemberName] string? name = null) { if (name != null) { @@ -21,7 +21,7 @@ public TestProject([CallerMemberName] string name = null) /// A name for the test project that's used to isolate it from a test's root folder by appending it to the root test path. /// By default, it is the unhashed name of the function that instantiated the TestProject object. /// - public string Name { get; set; } + public string? Name { get; set; } public bool IsSdkProject { get; set; } = true; @@ -33,7 +33,7 @@ public TestProject([CallerMemberName] string name = null) public bool IsWinExe { get; set; } - public string ProjectSdk { get; set; } + public string? ProjectSdk { get; set; } /// /// Applies to SDK-style projects. If the value has only one target framework (ie no semicolons), the value will be used @@ -41,21 +41,21 @@ public TestProject([CallerMemberName] string name = null) /// public string TargetFrameworks { get; set; } = ToolsetInfo.CurrentTargetFramework; - public string RuntimeFrameworkVersion { get; set; } + public string? RuntimeFrameworkVersion { get; set; } - public string RuntimeIdentifier { get; set; } + public string? RuntimeIdentifier { get; set; } // Set to either true, false, or empty string "". The empty string does not undefine SelfContained, it just doesn't specify it. public string SelfContained { get; set; } = ""; // TargetFrameworkVersion applies to non-SDK projects - public string TargetFrameworkVersion { get; set; } + public string? TargetFrameworkVersion { get; set; } - public string TargetFrameworkProfile { get; set; } + public string? TargetFrameworkProfile { get; set; } public bool UseArtifactsOutput { get; set; } - public List ReferencedProjects { get; } = new List(); + public List ReferencedProjects { get; } = new List(); public List References { get; } = new List(); @@ -127,7 +127,7 @@ public bool BuildsOnNonWindows internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, string targetExtension = ".csproj") { - string targetFolder = Path.Combine(targetTestAsset.Path, Name); + string targetFolder = Path.Combine(targetTestAsset.Path, Name ?? string.Empty); Directory.CreateDirectory(targetFolder); string targetProjectPath = Path.Combine(targetFolder, Name + targetExtension); @@ -144,7 +144,7 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, } // Copy any additional files from template - foreach (var file in Directory.GetFiles(Path.GetDirectoryName(sourceProject))) + foreach (var file in Directory.GetFiles(Path.GetDirectoryName(sourceProject) ?? string.Empty)) { if (file != sourceProject) { @@ -154,26 +154,31 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, var projectXml = XDocument.Load(sourceProject); + if (projectXml.Root is null) + { + throw new InvalidOperationException($"The project file '{sourceProject}' does not have a root element."); + } var ns = projectXml.Root.Name.Namespace; - if (ProjectSdk != null) + var sdkAttribute = projectXml.Root.Attribute("Sdk"); + if (sdkAttribute is not null && ProjectSdk != null) { - projectXml.Root.Attribute("Sdk").Value = ProjectSdk; + sdkAttribute.Value = ProjectSdk; } - var propertyGroup = projectXml.Root.Elements(ns + "PropertyGroup").First(); + var propertyGroup = projectXml.Root?.Elements(ns + "PropertyGroup").First(); - var packageReferenceItemGroup = projectXml.Root.Elements(ns + "ItemGroup") + var packageReferenceItemGroup = projectXml.Root?.Elements(ns + "ItemGroup") .FirstOrDefault(itemGroup => itemGroup.Elements(ns + "PackageReference").Count() > 0); if (packageReferenceItemGroup == null) { - packageReferenceItemGroup = projectXml.Root.Elements(ns + "ItemGroup") + packageReferenceItemGroup = projectXml.Root?.Elements(ns + "ItemGroup") .FirstOrDefault(); } if (packageReferenceItemGroup == null) { packageReferenceItemGroup = new XElement(ns + "ItemGroup"); - projectXml.Root.Add(packageReferenceItemGroup); + projectXml.Root?.Add(packageReferenceItemGroup); } foreach (TestPackageReference packageReference in PackageReferences) @@ -213,52 +218,58 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, { if (TargetFrameworks.Contains(";")) { - propertyGroup.Add(new XElement(ns + "TargetFrameworks", TargetFrameworks)); + propertyGroup?.Add(new XElement(ns + "TargetFrameworks", TargetFrameworks)); } else { - propertyGroup.Add(new XElement(ns + "TargetFramework", TargetFrameworks)); + propertyGroup?.Add(new XElement(ns + "TargetFramework", TargetFrameworks)); } if (!string.IsNullOrEmpty(RuntimeFrameworkVersion)) { - propertyGroup.Add(new XElement(ns + "RuntimeFrameworkVersion", RuntimeFrameworkVersion)); + propertyGroup?.Add(new XElement(ns + "RuntimeFrameworkVersion", RuntimeFrameworkVersion)); } if (!string.IsNullOrEmpty(RuntimeIdentifier)) { - propertyGroup.Add(new XElement(ns + "RuntimeIdentifier", RuntimeIdentifier)); + propertyGroup?.Add(new XElement(ns + "RuntimeIdentifier", RuntimeIdentifier)); } } else { if (!string.IsNullOrEmpty(TargetFrameworkProfile)) { - propertyGroup.Add(new XElement(ns + "TargetFrameworkProfile", TargetFrameworkProfile)); + propertyGroup?.Add(new XElement(ns + "TargetFrameworkProfile", TargetFrameworkProfile)); // To construct an accurate PCL project file, we must modify the import of the CSharp targets; // building/testing the SDK requires a VSDev command prompt which sets 'VSINSTALLDIR' - var importGroup = projectXml.Root.Elements(ns + "Import").Last(); - importGroup.Attribute("Project").Value = "$(VSINSTALLDIR)\\MSBuild\\Microsoft\\Portable\\$(TargetFrameworkVersion)\\Microsoft.Portable.CSharp.targets"; + var importGroup = projectXml.Root?.Elements(ns + "Import").Last(); + if(importGroup?.Attribute("Project") is not null) + { + importGroup.Attribute("Project")!.Value = "$(VSINSTALLDIR)\\MSBuild\\Microsoft\\Portable\\$(TargetFrameworkVersion)\\Microsoft.Portable.CSharp.targets"; + } } - propertyGroup.Element(ns + "TargetFrameworkVersion").SetValue(TargetFrameworkVersion); + if(TargetFrameworkVersion is not null) + { + propertyGroup?.Element(ns + "TargetFrameworkVersion")?.SetValue(TargetFrameworkVersion); + } } foreach (var additionalProperty in AdditionalProperties) { - propertyGroup.Add(new XElement(ns + additionalProperty.Key, additionalProperty.Value)); + propertyGroup?.Add(new XElement(ns + additionalProperty.Key, additionalProperty.Value)); } if (AdditionalItems.Any()) { foreach (var additionalItem in AdditionalItems) { - var additionalItemGroup = projectXml.Root.Elements(ns + "ItemGroup").FirstOrDefault(); + var additionalItemGroup = projectXml.Root?.Elements(ns + "ItemGroup").FirstOrDefault(); if (additionalItemGroup == null) { additionalItemGroup = new XElement(ns + "ItemGroup"); - projectXml.Root.Add(packageReferenceItemGroup); + projectXml.Root?.Add(packageReferenceItemGroup); } var item = new XElement(ns + additionalItem.Key); foreach (var attribute in additionalItem.Value) @@ -269,21 +280,21 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, if (IsExe && !IsWinExe) { - propertyGroup.Element(ns + "OutputType").SetValue("Exe"); + propertyGroup?.Element(ns + "OutputType")?.SetValue("Exe"); } else if (IsWinExe) { - propertyGroup.Element(ns + "OutputType").SetValue("WinExe"); + propertyGroup?.Element(ns + "OutputType")?.SetValue("WinExe"); } if (SelfContained != "") { - propertyGroup.Add(new XElement(ns + "SelfContained", string.Equals(SelfContained, "true", StringComparison.OrdinalIgnoreCase) ? "true" : "false")); + propertyGroup?.Add(new XElement(ns + "SelfContained", string.Equals(SelfContained, "true", StringComparison.OrdinalIgnoreCase) ? "true" : "false")); } if (ReferencedProjects.Any()) { - var projectReferenceItemGroup = projectXml.Root.Elements(ns + "ItemGroup") + var projectReferenceItemGroup = projectXml.Root?.Elements(ns + "ItemGroup") .FirstOrDefault(itemGroup => itemGroup.Elements(ns + "ProjectReference").Count() > 0); if (projectReferenceItemGroup == null) { @@ -293,13 +304,13 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, foreach (var referencedProject in ReferencedProjects) { projectReferenceItemGroup.Add(new XElement(ns + "ProjectReference", - new XAttribute("Include", $"../{referencedProject.Name}/{referencedProject.Name}.csproj"))); + new XAttribute("Include", $"../{referencedProject?.Name}/{referencedProject?.Name}.csproj"))); } } if (References.Any()) { - var referenceItemGroup = projectXml.Root.Elements(ns + "ItemGroup") + var referenceItemGroup = projectXml.Root?.Elements(ns + "ItemGroup") .FirstOrDefault(itemGroup => itemGroup.Elements(ns + "Reference").Count() > 0); if (referenceItemGroup == null) { @@ -317,7 +328,7 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, if (FrameworkReferences.Any()) { var frameworkReferenceItemGroup = new XElement(ns + "ItemGroup"); - projectXml.Root.Add(frameworkReferenceItemGroup); + projectXml.Root?.Add(frameworkReferenceItemGroup); foreach (var frameworkReference in FrameworkReferences) { frameworkReferenceItemGroup.Add(new XElement(ns + "FrameworkReference", @@ -343,7 +354,7 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, } target.Add(copyElement); - projectXml.Root.Add(target); + projectXml.Root?.Add(target); } } @@ -355,10 +366,10 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, if (PropertiesToRecord.Any()) { var customAfterDirectoryBuildTargetsPath = new FileInfo(Path.Combine(targetFolder, "obj", "Custom.After.Directory.Build.targets")); - customAfterDirectoryBuildTargetsPath.Directory.Create(); + customAfterDirectoryBuildTargetsPath.Directory?.Create(); - propertyGroup.Add(new XElement(ns + "CustomAfterDirectoryBuildTargets", $"$(CustomAfterDirectoryBuildTargets);{customAfterDirectoryBuildTargetsPath.FullName}")); - propertyGroup.Add(new XElement(ns + "CustomAfterMicrosoftCommonCrossTargetingTargets", $"$(CustomAfterMicrosoftCommonCrossTargetingTargets);{customAfterDirectoryBuildTargetsPath.FullName}")); + propertyGroup?.Add(new XElement(ns + "CustomAfterDirectoryBuildTargets", $"$(CustomAfterDirectoryBuildTargets);{customAfterDirectoryBuildTargetsPath.FullName}")); + propertyGroup?.Add(new XElement(ns + "CustomAfterMicrosoftCommonCrossTargetingTargets", $"$(CustomAfterMicrosoftCommonCrossTargetingTargets);{customAfterDirectoryBuildTargetsPath.FullName}")); var customAfterDirectoryBuildTargets = new XDocument(new XElement(ns + "Project")); @@ -366,7 +377,7 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder, new XAttribute("Name", "WritePropertyValues"), new XAttribute("BeforeTargets", "AfterBuild")); - customAfterDirectoryBuildTargets.Root.Add(target); + customAfterDirectoryBuildTargets.Root?.Add(target); var itemGroup = new XElement(ns + "ItemGroup"); target.Add(itemGroup); @@ -409,7 +420,7 @@ static void Main(string[] args) foreach (var dependency in ReferencedProjects) { - string safeDependencyName = dependency.Name.Replace('.', '_'); + string? safeDependencyName = dependency?.Name?.Replace('.', '_'); source += $" Console.WriteLine({safeDependencyName}.{safeDependencyName}Class.Name);" + Environment.NewLine; source += $" Console.WriteLine({safeDependencyName}.{safeDependencyName}Class.List);" + Environment.NewLine; @@ -424,7 +435,7 @@ static void Main(string[] args) } { - string safeThisName = Name.Replace('.', '_'); + string? safeThisName = Name?.Replace('.', '_'); string source = $@"using System; using System.Collections.Generic; @@ -438,7 +449,7 @@ public class {safeThisName}Class "; foreach (var dependency in ReferencedProjects) { - string safeDependencyName = dependency.Name.Replace('.', '_'); + string? safeDependencyName = dependency?.Name?.Replace('.', '_'); source += $" public string {safeDependencyName}Name {{ get {{ return {safeDependencyName}.{safeDependencyName}Class.Name; }} }}" + Environment.NewLine; source += $" public List {safeDependencyName}List {{ get {{ return {safeDependencyName}.{safeDependencyName}Class.List; }} }}" + Environment.NewLine; @@ -486,11 +497,11 @@ public void RecordProperties(params string[] propertyNames) /// A dictionary of property keys to property value strings, case sensitive. /// Only properties added to the member will be observed. /// - public Dictionary GetPropertyValues(string testRoot, string targetFramework = null, string configuration = "Debug") + public Dictionary GetPropertyValues(string testRoot, string? targetFramework = null, string configuration = "Debug") { var propertyValues = new Dictionary(); - string intermediateOutputPath = Path.Combine(testRoot, Name, "obj", configuration, targetFramework ?? TargetFrameworks); + string intermediateOutputPath = Path.Combine(testRoot, Name ?? string.Empty, "obj", configuration, targetFramework ?? TargetFrameworks); foreach (var line in File.ReadAllLines(Path.Combine(intermediateOutputPath, "PropertyValues.txt"))) { @@ -514,10 +525,10 @@ public static bool ReferenceAssembliesAreInstalled(TargetDotNetFrameworkVersion private OutputPathCalculator GetOutputPathCalculator(string testRoot) { - return OutputPathCalculator.FromProject(Path.Combine(testRoot, Name, Name + ".csproj"), this); + return OutputPathCalculator.FromProject(Path.Combine(testRoot, Name ?? string.Empty, Name + ".csproj"), this); } - public string GetOutputDirectory(string testRoot, string targetFramework = null, string configuration = "Debug", string runtimeIdentifier = "") + public string GetOutputDirectory(string testRoot, string? targetFramework = null, string configuration = "Debug", string runtimeIdentifier = "") { return GetOutputPathCalculator(testRoot) .GetOutputDirectory(targetFramework, configuration, runtimeIdentifier); diff --git a/test/Microsoft.NET.TestFramework/SdkTest.cs b/test/Microsoft.NET.TestFramework/SdkTest.cs index 57403ba29a0d..c508ec7ba4a8 100644 --- a/test/Microsoft.NET.TestFramework/SdkTest.cs +++ b/test/Microsoft.NET.TestFramework/SdkTest.cs @@ -7,7 +7,7 @@ public abstract class SdkTest { protected TestAssetsManager _testAssetsManager; - protected bool UsingFullFrameworkMSBuild => TestContext.Current.ToolsetUnderTest.ShouldUseFullFrameworkMSBuild; + protected bool? UsingFullFrameworkMSBuild => TestContext.Current.ToolsetUnderTest?.ShouldUseFullFrameworkMSBuild; protected ITestOutputHelper Log { get; } diff --git a/test/Microsoft.NET.TestFramework/TestAsset.cs b/test/Microsoft.NET.TestFramework/TestAsset.cs index b9f9f935da48..b26334ad21a6 100644 --- a/test/Microsoft.NET.TestFramework/TestAsset.cs +++ b/test/Microsoft.NET.TestFramework/TestAsset.cs @@ -9,9 +9,9 @@ namespace Microsoft.NET.TestFramework /// public class TestAsset : TestDirectory { - private readonly string _testAssetRoot; + private readonly string? _testAssetRoot; - private List _projectFiles; + private List? _projectFiles; public string TestRoot => Path; @@ -25,15 +25,15 @@ public class TestAsset : TestDirectory public ITestOutputHelper Log { get; } // The TestProject from which this asset was created, if any - public TestProject TestProject { get; set; } + public TestProject? TestProject { get; set; } - internal TestAsset(string testDestination, string sdkVersion, ITestOutputHelper log) : base(testDestination, sdkVersion) + internal TestAsset(string testDestination, string? sdkVersion, ITestOutputHelper log) : base(testDestination, sdkVersion) { Log = log; Name = new DirectoryInfo(testDestination).Name; } - internal TestAsset(string testAssetRoot, string testDestination, string sdkVersion, ITestOutputHelper log) : base(testDestination, sdkVersion) + internal TestAsset(string testAssetRoot, string testDestination, string? sdkVersion, ITestOutputHelper log) : base(testDestination, sdkVersion) { if (string.IsNullOrEmpty(testAssetRoot)) { @@ -64,15 +64,15 @@ public TestAsset WithSource() { _projectFiles = new List(); - var sourceDirs = Directory.GetDirectories(_testAssetRoot, "*", SearchOption.AllDirectories) + var sourceDirs = Directory.GetDirectories(_testAssetRoot ?? string.Empty, "*", SearchOption.AllDirectories) .Where(dir => !IsBinOrObjFolder(dir)); foreach (string sourceDir in sourceDirs) { - Directory.CreateDirectory(sourceDir.Replace(_testAssetRoot, Path)); + Directory.CreateDirectory(sourceDir.Replace(_testAssetRoot ?? string.Empty, Path)); } - var sourceFiles = Directory.GetFiles(_testAssetRoot, "*.*", SearchOption.AllDirectories) + var sourceFiles = Directory.GetFiles(_testAssetRoot ?? string.Empty, "*.*", SearchOption.AllDirectories) .Where(file => { return !IsInBinOrObjFolder(file); @@ -80,7 +80,7 @@ public TestAsset WithSource() foreach (string srcFile in sourceFiles) { - string destFile = srcFile.Replace(_testAssetRoot, Path); + string destFile = srcFile.Replace(_testAssetRoot ?? string.Empty, Path); if (System.IO.Path.GetFileName(srcFile).EndsWith("proj") || System.IO.Path.GetFileName(srcFile).EndsWith("xml")) { @@ -115,10 +115,13 @@ public TestAsset UpdateProjProperty(string propertyName, string variableName, st return WithProjectChanges( p => { - var ns = p.Root.Name.Namespace; - var getNode = p.Root.Elements(ns + "PropertyGroup").Elements(ns + propertyName).FirstOrDefault(); - getNode ??= p.Root.Elements(ns + "PropertyGroup").Elements(ns + $"{propertyName}s").FirstOrDefault(); - getNode?.SetValue(getNode?.Value.Replace(variableName, targetValue)); + if (p.Root is not null) + { + var ns = p.Root.Name.Namespace; + var getNode = p.Root.Elements(ns + "PropertyGroup").Elements(ns + propertyName).FirstOrDefault(); + getNode ??= p.Root.Elements(ns + "PropertyGroup").Elements(ns + $"{propertyName}s").FirstOrDefault(); + getNode?.SetValue(getNode?.Value.Replace(variableName, targetValue) ?? string.Empty); + } }); } @@ -128,21 +131,29 @@ public TestAsset ReplacePackageVersionVariable(string targetName, string targetV return WithProjectChanges(project => { - var ns = project.Root.Name.Namespace; - foreach (var PropertyName in PropertyNames) + if (project.Root is not null) { - var packageReferencesToUpdate = - project.Root.Descendants(ns + PropertyName) - .Where(p => p.Attribute("Version") != null && p.Attribute("Version").Value.Equals($"$({targetName})", StringComparison.OrdinalIgnoreCase)); - foreach (var packageReference in packageReferencesToUpdate) + var ns = project.Root.Name.Namespace; + foreach (var PropertyName in PropertyNames) { - packageReference.Attribute("Version").Value = targetValue; + var packageReferencesToUpdate = + project.Root.Descendants(ns + PropertyName) + .Select(p => p.Attribute("Version")) + .Where(va => va is not null && va.Value.Equals($"$({targetName})", StringComparison.OrdinalIgnoreCase)); + foreach (var versionAttribute in packageReferencesToUpdate) + { + if(versionAttribute is not null) + { + versionAttribute.Value = targetValue; + } + } } } + }); } - public TestAsset WithTargetFramework(string targetFramework, string projectName = null) + public TestAsset WithTargetFramework(string targetFramework, string? projectName = null) { if (targetFramework == null) { @@ -151,13 +162,16 @@ public TestAsset WithTargetFramework(string targetFramework, string projectName return WithProjectChanges( p => { - var ns = p.Root.Name.Namespace; - p.Root.Elements(ns + "PropertyGroup").Elements(ns + "TargetFramework").Single().SetValue(targetFramework); + if (p.Root is not null) + { + var ns = p.Root.Name.Namespace; + p.Root.Elements(ns + "PropertyGroup").Elements(ns + "TargetFramework").Single().SetValue(targetFramework); + } }, projectName); } - public TestAsset WithTargetFrameworks(string targetFrameworks, string projectName = null) + public TestAsset WithTargetFrameworks(string targetFrameworks, string? projectName = null) { if (targetFrameworks == null) { @@ -166,16 +180,19 @@ public TestAsset WithTargetFrameworks(string targetFrameworks, string projectNam return WithProjectChanges( p => { - var ns = p.Root.Name.Namespace; - var propertyGroup = p.Root.Elements(ns + "PropertyGroup").First(); - propertyGroup.Elements(ns + "TargetFramework").SingleOrDefault()?.Remove(); - propertyGroup.Elements(ns + "TargetFrameworks").SingleOrDefault()?.Remove(); - propertyGroup.Add(new XElement(ns + "TargetFrameworks", targetFrameworks)); + if (p.Root is not null) + { + var ns = p.Root.Name.Namespace; + var propertyGroup = p.Root.Elements(ns + "PropertyGroup").First(); + propertyGroup.Elements(ns + "TargetFramework").SingleOrDefault()?.Remove(); + propertyGroup.Elements(ns + "TargetFrameworks").SingleOrDefault()?.Remove(); + propertyGroup.Add(new XElement(ns + "TargetFrameworks", targetFrameworks)); + } }, projectName); } - public TestAsset WithTargetFrameworkOrFrameworks(string targetFrameworkOrFrameworks, bool multitarget, string projectName = null) + public TestAsset WithTargetFrameworkOrFrameworks(string targetFrameworkOrFrameworks, bool multitarget, string? projectName = null) { if (multitarget) { @@ -187,18 +204,21 @@ public TestAsset WithTargetFrameworkOrFrameworks(string targetFrameworkOrFramewo } } - private TestAsset WithProjectChanges(Action actionOnProject, string projectName = null) + private TestAsset WithProjectChanges(Action actionOnProject, string? projectName = null) { return WithProjectChanges((path, project) => { if (!string.IsNullOrEmpty(projectName)) { - if (!projectName.Equals(System.IO.Path.GetFileNameWithoutExtension(path), StringComparison.OrdinalIgnoreCase)) + if (projectName is not null && !projectName.Equals(System.IO.Path.GetFileNameWithoutExtension(path), StringComparison.OrdinalIgnoreCase)) { return; } } - + if (project.Root is null) + { + throw new InvalidOperationException($"The project file '{projectName}' does not have a root element."); + } var ns = project.Root.Name.Namespace; actionOnProject(project); }); @@ -215,7 +235,7 @@ public TestAsset WithProjectChanges(Action xmlAction) { FindProjectFiles(); } - foreach (var projectFile in _projectFiles) + foreach (var projectFile in _projectFiles ?? new()) { var project = XDocument.Load(projectFile); diff --git a/test/Microsoft.NET.TestFramework/TestAssetsManager.cs b/test/Microsoft.NET.TestFramework/TestAssetsManager.cs index a0b44dd6a35b..7d7c78c9a5fa 100644 --- a/test/Microsoft.NET.TestFramework/TestAssetsManager.cs +++ b/test/Microsoft.NET.TestFramework/TestAssetsManager.cs @@ -30,10 +30,10 @@ public TestAssetsManager(ITestOutputHelper log) public TestAsset CopyTestAsset( string testProjectName, [CallerMemberName] string callingMethod = "", - [CallerFilePath] string callerFilePath = null, - string identifier = "", + [CallerFilePath] string? callerFilePath = null, + string? identifier = "", string testAssetSubdirectory = "", - string testDestinationDirectory = null, + string? testDestinationDirectory = null, bool allowCopyIfPresent = false) { var testProjectDirectory = GetAndValidateTestProjectDirectory(testProjectName, testAssetSubdirectory); @@ -110,7 +110,7 @@ public TestAsset CreateTestProjects( foreach (var testProject in testProjects) { - new DotnetCommand(Log, "sln", "add", testProject.Name) + new DotnetCommand(Log, "sln", "add", testProject.Name ?? string.Empty) .WithWorkingDirectory(testDestinationDirectory) .Execute() .Should() @@ -140,7 +140,10 @@ private TestAsset CreateTestProjectsInDirectory( foreach (var referencedProject in project.ReferencedProjects) { - projectStack.Push(referencedProject); + if(referencedProject is not null) + { + projectStack.Push(referencedProject); + } } } } @@ -148,7 +151,7 @@ private TestAsset CreateTestProjectsInDirectory( return testAsset; } - public TestDirectory CreateTestDirectory([CallerMemberName] string testName = null, string identifier = null) + public TestDirectory CreateTestDirectory([CallerMemberName] string? testName = null, string? identifier = null) { string dir = GetTestDestinationDirectoryPath(testName, testName, identifier ?? string.Empty); return new TestDirectory(dir, TestContext.Current.SdkVersion); @@ -171,12 +174,12 @@ public string GetAndValidateTestProjectDirectory(string testProjectName, string } public static string GetTestDestinationDirectoryPath( - string testProjectName, - string callingMethodAndFileName, - string identifier, + string? testProjectName, + string? callingMethodAndFileName, + string? identifier, bool allowCopyIfPresent = false) { - string baseDirectory = TestContext.Current.TestExecutionDirectory; + string? baseDirectory = TestContext.Current.TestExecutionDirectory; var directoryName = new StringBuilder(callingMethodAndFileName).Append(identifier); if (testProjectName != callingMethodAndFileName) diff --git a/test/Microsoft.NET.TestFramework/TestCommandLine.cs b/test/Microsoft.NET.TestFramework/TestCommandLine.cs index 2519a063e819..ab94559bb7aa 100644 --- a/test/Microsoft.NET.TestFramework/TestCommandLine.cs +++ b/test/Microsoft.NET.TestFramework/TestCommandLine.cs @@ -7,27 +7,27 @@ namespace Microsoft.NET.TestFramework { public class TestCommandLine { - public List RemainingArgs { get; private set; } + public List? RemainingArgs { get; private set; } public bool UseFullFrameworkMSBuild { get; private set; } - public string FullFrameworkMSBuildPath { get; private set; } + public string? FullFrameworkMSBuildPath { get; private set; } - public string DotnetHostPath { get; private set; } + public string? DotnetHostPath { get; private set; } - public string SDKRepoPath { get; private set; } + public string? SDKRepoPath { get; private set; } - public string SDKRepoConfiguration { get; private set; } + public string? SDKRepoConfiguration { get; private set; } public bool NoRepoInference { get; private set; } public bool ShouldShowHelp { get; private set; } - public string SdkVersion { get; private set; } + public string? SdkVersion { get; private set; } - public string TestExecutionDirectory { get; set; } + public string? TestExecutionDirectory { get; set; } - public string MsbuildAdditionalSdkResolverFolder { get; set; } + public string? MsbuildAdditionalSdkResolverFolder { get; set; } public List<(string name, string value)> EnvironmentVariables { get; set; } = []; @@ -121,7 +121,7 @@ public static TestCommandLine Parse(string[] args) if (string.IsNullOrEmpty(ret.FullFrameworkMSBuildPath)) { // Run tests on full framework MSBuild if environment variable is set pointing to it - string msbuildPath = Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_MSBUILD_PATH"); + string? msbuildPath = Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_MSBUILD_PATH"); if (!string.IsNullOrEmpty(msbuildPath)) { ret.FullFrameworkMSBuildPath = msbuildPath; @@ -151,29 +151,32 @@ public List GetXunitArgsFromTestConfig() foreach (var testConfigFile in TestConfigFiles) { var testConfig = XDocument.Load(testConfigFile); - foreach (var item in testConfig.Root.Elements()) + if (testConfig.Root is not null) { - if (item.Name.LocalName.Equals("TestList", StringComparison.OrdinalIgnoreCase)) + foreach (var item in testConfig.Root.Elements()) { - testLists.Add(TestList.Parse(item)); - } - else if (item.Name.LocalName.Equals("SkippedTests", StringComparison.OrdinalIgnoreCase)) - { - var skippedGroup = TestList.Parse(item); - testsToSkip.AddRange(skippedGroup.TestSpecifiers); - } - else - { - if (bool.TryParse(item.Attribute("Skip")?.Value ?? string.Empty, out bool shouldSkip) && - shouldSkip) + if (item.Name.LocalName.Equals("TestList", StringComparison.OrdinalIgnoreCase)) + { + testLists.Add(TestList.Parse(item)); + } + else if (item.Name.LocalName.Equals("SkippedTests", StringComparison.OrdinalIgnoreCase)) + { + var skippedGroup = TestList.Parse(item); + testsToSkip.AddRange(skippedGroup.TestSpecifiers); + } + else { - testsToSkip.Add(TestSpecifier.Parse(item)); + if (bool.TryParse(item.Attribute("Skip")?.Value ?? string.Empty, out bool shouldSkip) && + shouldSkip) + { + testsToSkip.Add(TestSpecifier.Parse(item)); + } } } } } - foreach (var testList in testLists.Where(g => TestListsToRun.Contains(g.Name))) + foreach (var testList in testLists.Where(g => TestListsToRun.Contains(g.Name ?? string.Empty))) { foreach (var testSpec in testList.TestSpecifiers) { @@ -193,7 +196,7 @@ public List GetXunitArgsFromTestConfig() { throw new ArgumentException("Unrecognized test specifier type: " + testSpec.Type); } - ret.Add(testSpec.Specifier); + ret.Add(testSpec.Specifier ?? string.Empty); } } @@ -215,7 +218,7 @@ public List GetXunitArgsFromTestConfig() { throw new ArgumentException("Unrecognized test specifier type: " + testSpec.Type); } - ret.Add(testSpec.Specifier); + ret.Add(testSpec.Specifier ?? string.Empty); } return ret; @@ -223,7 +226,7 @@ public List GetXunitArgsFromTestConfig() private class TestList { - public string Name { get; set; } + public string? Name { get; set; } public List TestSpecifiers { get; set; } = new List(); @@ -253,7 +256,7 @@ public enum TestSpecifierType } public TestSpecifierType Type { get; set; } - public string Specifier { get; set; } + public string? Specifier { get; set; } public static TestSpecifier Parse(XElement element) { @@ -273,7 +276,7 @@ public static TestSpecifier Parse(XElement element) throw new XmlException("Unrecognized node: " + element.Name); } - spec.Specifier = element.Attribute("Name").Value; + spec.Specifier = element.Attribute("Name")?.Value; return spec; } diff --git a/test/Microsoft.NET.TestFramework/TestContext.cs b/test/Microsoft.NET.TestFramework/TestContext.cs index 1aed029fa612..682412fc0b7a 100644 --- a/test/Microsoft.NET.TestFramework/TestContext.cs +++ b/test/Microsoft.NET.TestFramework/TestContext.cs @@ -9,27 +9,75 @@ namespace Microsoft.NET.TestFramework public class TestContext { // Generally the folder the test DLL is in - public string TestExecutionDirectory { get; set; } + private string? _testExecutionDirectory; - public string TestAssetsDirectory { get; set; } + public string TestExecutionDirectory + { + get + { + if (_testExecutionDirectory == null) + { + throw new InvalidOperationException("TestExecutionDirectory should never be null."); + } + return _testExecutionDirectory; + } + set + { + _testExecutionDirectory = value; + } + } + + private string? _testAssetsDirectory; + + public string TestAssetsDirectory + { + get + { + if (_testAssetsDirectory == null) + { + throw new InvalidOperationException("TestAssetsDirectory should never be null."); + } + return _testAssetsDirectory; + } + set + { + _testAssetsDirectory = value; + } + } - public string TestPackages { get; set; } + public string? TestPackages { get; set; } // For tests which want the global packages folder isolated in the repo, but // can share it with other tests - public string TestGlobalPackagesFolder { get; set; } + public string? TestGlobalPackagesFolder { get; set; } - public string NuGetCachePath { get; set; } + public string? NuGetCachePath { get; set; } - public string NuGetFallbackFolder { get; set; } + public string? NuGetFallbackFolder { get; set; } - public string NuGetExePath { get; set; } + public string? NuGetExePath { get; set; } - public string SdkVersion { get; set; } + public string? SdkVersion { get; set; } - public ToolsetInfo ToolsetUnderTest { get; set; } + private ToolsetInfo? _toolsetUnderTest; - private static TestContext _current; + public ToolsetInfo ToolsetUnderTest + { + get + { + if (_toolsetUnderTest == null) + { + throw new InvalidOperationException("ToolsetUnderTest should never be null."); + } + return _toolsetUnderTest; + } + set + { + _toolsetUnderTest = value; + } + } + + private static TestContext? _current; public static TestContext Current { @@ -41,7 +89,7 @@ public static TestContext Current // (ie when using test explorer or another runner) Initialize(TestCommandLine.Parse(Array.Empty())); } - return _current; + return _current ?? throw new InvalidOperationException("TestContext.Current should never be null."); } set { @@ -67,7 +115,10 @@ public void AddTestEnvironmentVariables(IDictionary environment) environment["DOTNET_MULTILEVEL_LOOKUP"] = "0"; // Set NUGET_PACKAGES environment variable to match value from build.ps1 - environment["NUGET_PACKAGES"] = NuGetCachePath; + if(NuGetCachePath is not null) + { + environment["NUGET_PACKAGES"] = NuGetCachePath; + } environment["GenerateResourceMSBuildArchitecture"] = "CurrentArchitecture"; environment["GenerateResourceMSBuildRuntime"] = "CurrentRuntime"; @@ -110,15 +161,18 @@ public static void Initialize(TestCommandLine commandLine) // This allows testing most of the "tests as global tool" behavior by setting an environment // variable instead of packing the test, and installing it as a global tool. runAsTool = true; - - testContext.TestAssetsDirectory = FindFolderInTree(Path.Combine("test", "TestAssets"), AppContext.BaseDirectory); + string? FindFolder = FindFolderInTree(Path.Combine("test", "TestAssets"), AppContext.BaseDirectory); + if (FindFolder is not null) + { + testContext.TestAssetsDirectory = FindFolder; + } } - else if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_ASSETS_DIRECTORY"))) + else if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_ASSETS_DIRECTORY")) && Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_ASSETS_DIRECTORY") is not null) { - testContext.TestAssetsDirectory = Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_ASSETS_DIRECTORY"); + testContext.TestAssetsDirectory = Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_ASSETS_DIRECTORY")!; } - string repoRoot = null; + string? repoRoot = null; #if DEBUG string repoConfiguration = "Debug"; #else @@ -134,13 +188,13 @@ public static void Initialize(TestCommandLine commandLine) repoRoot = GetRepoRoot(); } - if (!string.IsNullOrEmpty(commandLine.TestExecutionDirectory)) + if (!string.IsNullOrEmpty(commandLine.TestExecutionDirectory) && commandLine.TestExecutionDirectory is not null) { testContext.TestExecutionDirectory = commandLine.TestExecutionDirectory; } else if (Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_EXECUTION_DIRECTORY") != null) { - testContext.TestExecutionDirectory = Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_EXECUTION_DIRECTORY"); + testContext.TestExecutionDirectory = Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_EXECUTION_DIRECTORY")!; } else if (runAsTool) { @@ -148,14 +202,21 @@ public static void Initialize(TestCommandLine commandLine) } else { - testContext.TestExecutionDirectory = (Path.Combine(FindFolderInTree("artifacts", AppContext.BaseDirectory), "tmp", repoConfiguration)); - - testContext.TestAssetsDirectory = FindFolderInTree(Path.Combine("test", "TestAssets"), AppContext.BaseDirectory); + string? FindFolder1 = FindFolderInTree("artifacts", AppContext.BaseDirectory); + string? FindFolder2 = FindFolderInTree(Path.Combine("test", "TestAssets"), AppContext.BaseDirectory); + if (FindFolder1 is not null) + { + testContext.TestExecutionDirectory = Path.Combine(FindFolder1, "tmp", repoConfiguration); + } + if (FindFolder2 is not null) + { + testContext.TestAssetsDirectory = FindFolder2; + } } Directory.CreateDirectory(testContext.TestExecutionDirectory); - string artifactsDir = Environment.GetEnvironmentVariable("DOTNET_SDK_ARTIFACTS_DIR"); + string? artifactsDir = Environment.GetEnvironmentVariable("DOTNET_SDK_ARTIFACTS_DIR"); if (string.IsNullOrEmpty(artifactsDir) && !string.IsNullOrEmpty(repoRoot)) { artifactsDir = Path.Combine(repoRoot, "artifacts"); @@ -170,7 +231,7 @@ public static void Initialize(TestCommandLine commandLine) testContext.TestGlobalPackagesFolder = Path.Combine(testContext.TestExecutionDirectory, ".nuget", "packages"); } - if (repoRoot != null) + if (repoRoot != null && artifactsDir is not null) { testContext.NuGetFallbackFolder = Path.Combine(artifactsDir, ".nuget", "NuGetFallbackFolder"); testContext.NuGetExePath = Path.Combine(artifactsDir, ".nuget", $"nuget{Constants.ExeSuffix}"); @@ -232,9 +293,9 @@ public static void Initialize(TestCommandLine commandLine) #endif } - public static string GetRepoRoot() + public static string? GetRepoRoot() { - string directory = AppContext.BaseDirectory; + string? directory = AppContext.BaseDirectory; while (directory is not null) { @@ -253,7 +314,7 @@ public static string GetRepoRoot() } private static string FindOrCreateFolderInTree(string relativePath, string startPath) { - string ret = FindFolderInTree(relativePath, startPath, throwIfNotFound: false); + string? ret = FindFolderInTree(relativePath, startPath, throwIfNotFound: false); if (ret != null) { return ret; @@ -262,7 +323,7 @@ private static string FindOrCreateFolderInTree(string relativePath, string start Directory.CreateDirectory(ret); return ret; } - private static string FindFolderInTree(string relativePath, string startPath, bool throwIfNotFound = true) + private static string? FindFolderInTree(string relativePath, string startPath, bool throwIfNotFound = true) { string currentPath = startPath; while (true) @@ -293,7 +354,7 @@ public void WriteGlobalJson(string path) WriteGlobalJson(path, SdkVersion); } - public static void WriteGlobalJson(string path, string sdkVersion) + public static void WriteGlobalJson(string path, string? sdkVersion) { if (!string.IsNullOrEmpty(sdkVersion)) { diff --git a/test/Microsoft.NET.TestFramework/TestDirectory.cs b/test/Microsoft.NET.TestFramework/TestDirectory.cs index 543e415c84eb..5ec95f511bcb 100644 --- a/test/Microsoft.NET.TestFramework/TestDirectory.cs +++ b/test/Microsoft.NET.TestFramework/TestDirectory.cs @@ -5,7 +5,7 @@ namespace Microsoft.NET.TestFramework { public class TestDirectory { - internal TestDirectory(string path, string sdkVersion) + internal TestDirectory(string path, string? sdkVersion) { if (string.IsNullOrEmpty(path)) { @@ -24,7 +24,7 @@ public static TestDirectory Create(string path) public string Path { get; private set; } - private static void EnsureExistsAndEmpty(string path, string sdkVersion) + private static void EnsureExistsAndEmpty(string path, string? sdkVersion) { if (Directory.Exists(path)) { diff --git a/test/Microsoft.NET.TestFramework/TestLoggerFactory.cs b/test/Microsoft.NET.TestFramework/TestLoggerFactory.cs index 8c48f1cd58e9..0995a260e6cf 100644 --- a/test/Microsoft.NET.TestFramework/TestLoggerFactory.cs +++ b/test/Microsoft.NET.TestFramework/TestLoggerFactory.cs @@ -1,10 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#pragma warning disable IDE0240 -#nullable enable -#pragma warning restore IDE0240 - using Microsoft.Extensions.Logging; namespace Microsoft.NET.TestFramework diff --git a/test/Microsoft.NET.TestFramework/TestPackageReference.cs b/test/Microsoft.NET.TestFramework/TestPackageReference.cs index f58a57ba3991..073b76ce3dfe 100644 --- a/test/Microsoft.NET.TestFramework/TestPackageReference.cs +++ b/test/Microsoft.NET.TestFramework/TestPackageReference.cs @@ -5,7 +5,7 @@ namespace Microsoft.NET.TestFramework { public class TestPackageReference { - public TestPackageReference(string id, string version = null, string nupkgPath = null, string privateAssets = null, string aliases = null, bool updatePackageReference = false, string publish = null) + public TestPackageReference(string id, string? version = null, string? nupkgPath = null, string? privateAssets = null, string? aliases = null, bool updatePackageReference = false, string? publish = null) { ID = id; Version = version; @@ -17,15 +17,15 @@ public TestPackageReference(string id, string version = null, string nupkgPath = } public string ID { get; private set; } - public string Version { get; private set; } - public string NupkgPath { get; private set; } - public string PrivateAssets { get; private set; } - public string Aliases { get; private set; } - public string Publish { get; private set; } + public string? Version { get; private set; } + public string? NupkgPath { get; private set; } + public string? PrivateAssets { get; private set; } + public string? Aliases { get; private set; } + public string? Publish { get; private set; } public bool UpdatePackageReference { get; private set; } public bool NuGetPackageExists() { - return File.Exists(Path.Combine(NupkgPath, string.Concat(ID + "." + Version + ".nupkg"))); + return File.Exists(Path.Combine(NupkgPath ?? string.Empty, string.Concat(ID + "." + Version + ".nupkg"))); } } } diff --git a/test/Microsoft.NET.TestFramework/ToolsetInfo.cs b/test/Microsoft.NET.TestFramework/ToolsetInfo.cs index c12b13ac4fb5..52a9165ad6c2 100644 --- a/test/Microsoft.NET.TestFramework/ToolsetInfo.cs +++ b/test/Microsoft.NET.TestFramework/ToolsetInfo.cs @@ -21,7 +21,7 @@ public class ToolsetInfo public string DotNetRoot { get; } public string DotNetHostPath { get; } - private string _sdkVersion; + private string? _sdkVersion; public string SdkVersion { get @@ -32,12 +32,12 @@ public string SdkVersion // for the TestContext to finish being initialize InitSdkVersion(); } - return _sdkVersion; + return _sdkVersion ?? throw new InvalidOperationException("SdkVersion should never be null."); ; } } - private string _msbuildVersion; - public string MSBuildVersion + private string? _msbuildVersion; + public string? MSBuildVersion { get { @@ -58,15 +58,15 @@ public string MSBuildVersion Lazy _sdksPath; public string SdksPath => _sdksPath.Value; - public string CliHomePath { get; set; } + public string? CliHomePath { get; set; } - public string MicrosoftNETBuildExtensionsPathOverride { get; set; } + public string? MicrosoftNETBuildExtensionsPathOverride { get; set; } public bool ShouldUseFullFrameworkMSBuild => !string.IsNullOrEmpty(FullFrameworkMSBuildPath); - public string FullFrameworkMSBuildPath { get; set; } + public string? FullFrameworkMSBuildPath { get; set; } - public string SdkResolverPath { get; set; } + public string? SdkResolverPath { get; set; } public ToolsetInfo(string dotNetRoot) { @@ -83,7 +83,7 @@ private void InitSdkVersion() // If using full framework MSBuild, then running a command tries to get the SdkVersion in order to set the // DOTNET_MSBUILD_SDK_RESOLVER_SDKS_DIR environment variable. So turn that off when getting the SDK version // in order to avoid stack overflow - string oldFullFrameworkMSBuildPath = FullFrameworkMSBuildPath; + string? oldFullFrameworkMSBuildPath = FullFrameworkMSBuildPath; try { FullFrameworkMSBuildPath = null; @@ -100,7 +100,7 @@ private void InitSdkVersion() throw new Exception("Failed to get dotnet version" + Environment.NewLine + logger.ToString()); } - _sdkVersion = result.StdOut.Trim(); + _sdkVersion = result.StdOut?.Trim(); } finally { @@ -123,10 +123,10 @@ private void InitMSBuildVersion() throw new Exception("Failed to get msbuild version" + Environment.NewLine + logger.ToString()); } - _msbuildVersion = result.StdOut.Split().Last(); + _msbuildVersion = result.StdOut?.Split().Last(); } - public string GetMicrosoftNETBuildExtensionsPath() + public string? GetMicrosoftNETBuildExtensionsPath() { if (!string.IsNullOrEmpty(MicrosoftNETBuildExtensionsPathOverride)) { @@ -136,9 +136,13 @@ public string GetMicrosoftNETBuildExtensionsPath() { if (ShouldUseFullFrameworkMSBuild) { + string? msbuildRoot = null; var msbuildBinPath = Path.GetDirectoryName(FullFrameworkMSBuildPath); - var msbuildRoot = Directory.GetParent(msbuildBinPath).Parent.FullName; - return Path.Combine(msbuildRoot, @"Microsoft\Microsoft.NET.Build.Extensions"); + if(msbuildBinPath is not null) + { + msbuildRoot = Directory.GetParent(msbuildBinPath)?.Parent?.FullName; + } + return Path.Combine(msbuildRoot ?? string.Empty, @"Microsoft\Microsoft.NET.Build.Extensions"); } else { @@ -154,7 +158,10 @@ public void AddTestEnvironmentVariables(IDictionary environment) string sdksPath = Path.Combine(DotNetRoot, "sdk", SdkVersion, "Sdks"); // Use stage 2 MSBuild SDK resolver - environment["MSBUILDADDITIONALSDKRESOLVERSFOLDER"] = SdkResolverPath; + if(SdkResolverPath is not null) + { + environment["MSBUILDADDITIONALSDKRESOLVERSFOLDER"] = SdkResolverPath; + } // Avoid using stage 0 dotnet install dir environment["DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR"] = ""; @@ -165,7 +172,10 @@ public void AddTestEnvironmentVariables(IDictionary environment) if (!string.IsNullOrEmpty(MicrosoftNETBuildExtensionsPathOverride)) { var microsoftNETBuildExtensionsPath = GetMicrosoftNETBuildExtensionsPath(); - environment["MicrosoftNETBuildExtensionsTargets"] = Path.Combine(microsoftNETBuildExtensionsPath, "Microsoft.NET.Build.Extensions.targets"); + if (microsoftNETBuildExtensionsPath is not null) + { + environment["MicrosoftNETBuildExtensionsTargets"] = Path.Combine(microsoftNETBuildExtensionsPath, "Microsoft.NET.Build.Extensions.targets"); + } if (UsingFullMSBuildWithoutExtensionsTargets()) { @@ -218,7 +228,7 @@ private SdkCommandSpec CreateCommand(params string[] args) ret.Arguments = args.ToList(); // Don't propagate DOTNET_HOST_PATH to the msbuild process, to match behavior // when running desktop msbuild outside of the test harness. - ret.Environment["DOTNET_HOST_PATH"] = null; + ret.Environment["DOTNET_HOST_PATH"] = string.Empty; } else { @@ -234,17 +244,17 @@ private SdkCommandSpec CreateCommand(params string[] args) return ret; } - private static string GetDotnetHostPath(string dotnetRoot) - => Path.Combine(dotnetRoot, "dotnet" + Constants.ExeSuffix); + private static string GetDotnetHostPath(string? dotnetRoot) + => Path.Combine(dotnetRoot ?? string.Empty, "dotnet" + Constants.ExeSuffix); - public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, string configuration, TestCommandLine commandLine) + public static ToolsetInfo Create(string? repoRoot, string? repoArtifactsDir, string configuration, TestCommandLine commandLine) { repoRoot = commandLine.SDKRepoPath ?? repoRoot; configuration = commandLine.SDKRepoConfiguration ?? configuration; - string dotnetInstallDirFromEnvironment = Environment.GetEnvironmentVariable("DOTNET_INSTALL_DIR"); + string? dotnetInstallDirFromEnvironment = Environment.GetEnvironmentVariable("DOTNET_INSTALL_DIR"); - string dotnetRoot; + string? dotnetRoot; string hostNotFoundReason; if (!string.IsNullOrEmpty(commandLine.DotnetHostPath)) @@ -252,7 +262,7 @@ public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, strin dotnetRoot = Path.GetDirectoryName(commandLine.DotnetHostPath); hostNotFoundReason = "Command line argument -dotnetPath is incorrect."; } - else if (repoRoot != null) + else if (repoRoot != null && repoArtifactsDir is not null) { dotnetRoot = Path.Combine(repoArtifactsDir, "bin", "redist", configuration, "dotnet"); hostNotFoundReason = "Is 'redist.csproj' built?"; @@ -264,7 +274,7 @@ public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, strin } else { - if (TryResolveCommand("dotnet", out string pathToDotnet)) + if (TryResolveCommand("dotnet", out string? pathToDotnet)) { dotnetRoot = Path.GetDirectoryName(pathToDotnet); } @@ -276,7 +286,7 @@ public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, strin } var dotnetHost = GetDotnetHostPath(dotnetRoot); - if (!File.Exists(dotnetHost)) + if (dotnetRoot is null || !File.Exists(dotnetHost)) { throw new FileNotFoundException($"Host '{dotnetHost}' not found. {hostNotFoundReason}"); } @@ -289,7 +299,7 @@ public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, strin } else if (commandLine.UseFullFrameworkMSBuild) { - if (TryResolveCommand("MSBuild", out string pathToMSBuild)) + if (TryResolveCommand("MSBuild", out string? pathToMSBuild)) { ret.FullFrameworkMSBuildPath = pathToMSBuild; } @@ -304,7 +314,7 @@ public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, strin { ret.MicrosoftNETBuildExtensionsPathOverride = Path.GetDirectoryName(microsoftNETBuildExtensionsTargetsFromEnvironment); } - else if (repoRoot != null && ret.ShouldUseFullFrameworkMSBuild) + else if (repoRoot != null && ret.ShouldUseFullFrameworkMSBuild && repoArtifactsDir is not null) { // Find path to Microsoft.NET.Build.Extensions for full framework string sdksPath = Path.Combine(repoArtifactsDir, "bin", configuration, "Sdks"); @@ -314,7 +324,7 @@ public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, strin if (ret.ShouldUseFullFrameworkMSBuild) { - if (repoRoot != null) + if (repoRoot != null && repoArtifactsDir is not null) { // Find path to MSBuildSdkResolver for full framework ret.SdkResolverPath = Path.Combine(repoArtifactsDir, "bin", "Microsoft.DotNet.MSBuildSdkResolver", configuration, "net472", "SdkResolvers"); @@ -325,7 +335,7 @@ public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, strin } else if (Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_MSBUILDSDKRESOLVER_FOLDER") != null) { - ret.SdkResolverPath = Path.Combine(Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_MSBUILDSDKRESOLVER_FOLDER"), configuration, "net472", "SdkResolvers"); + ret.SdkResolverPath = Path.Combine(Environment.GetEnvironmentVariable("DOTNET_SDK_TEST_MSBUILDSDKRESOLVER_FOLDER")!, configuration, "net472", "SdkResolvers"); } else { @@ -333,7 +343,7 @@ public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, strin } } - if (repoRoot != null) + if (repoRoot != null && repoArtifactsDir is not null) { ret.CliHomePath = Path.Combine(repoArtifactsDir, "tmp", configuration); } @@ -347,7 +357,7 @@ public static ToolsetInfo Create(string repoRoot, string repoArtifactsDir, strin /// The command to resolve. /// The full path to the command /// when command can be resolved, otherwise. - public static bool TryResolveCommand(string command, out string fullExePath) + public static bool TryResolveCommand(string command, out string? fullExePath) { fullExePath = null; char pathSplitChar; @@ -356,7 +366,7 @@ public static bool TryResolveCommand(string command, out string fullExePath) { pathSplitChar = ';'; extensions = extensions - .Concat(Environment.GetEnvironmentVariable("PATHEXT").Split(pathSplitChar)) + .Concat(Environment.GetEnvironmentVariable("PATHEXT")?.Split(pathSplitChar) ?? Array.Empty()) .ToArray(); } else @@ -364,8 +374,8 @@ public static bool TryResolveCommand(string command, out string fullExePath) pathSplitChar = ':'; } - var paths = Environment.GetEnvironmentVariable("PATH").Split(pathSplitChar); - string result = extensions.SelectMany(ext => paths.Select(p => Path.Combine(p, command + ext))) + var paths = Environment.GetEnvironmentVariable("PATH")?.Split(pathSplitChar); + string? result = extensions.SelectMany(ext => paths?.Select(p => Path.Combine(p, command + ext)) ?? Array.Empty()) .FirstOrDefault(File.Exists); if (result == null) @@ -383,16 +393,16 @@ private bool UsingFullMSBuildWithoutExtensionsTargets() { return false; } - string fullMSBuildDirectory = Path.GetDirectoryName(FullFrameworkMSBuildPath); - string extensionsImportAfterPath = Path.Combine(fullMSBuildDirectory, "..", "Microsoft.Common.targets", "ImportAfter", "Microsoft.NET.Build.Extensions.targets"); + string? fullMSBuildDirectory = Path.GetDirectoryName(FullFrameworkMSBuildPath); + string extensionsImportAfterPath = Path.Combine(fullMSBuildDirectory ?? string.Empty, "..", "Microsoft.Common.targets", "ImportAfter", "Microsoft.NET.Build.Extensions.targets"); return !File.Exists(extensionsImportAfterPath); } internal static IEnumerable<(string versionPropertyName, string version)> GetPackageVersionProperties() => typeof(ToolsetInfo).Assembly .GetCustomAttributes() - .Where(a => a.Key.EndsWith("PackageVersion")) - .Select(a => (a.Key, a.Value)); + .Where(a => a.Key is not null && a.Key.EndsWith("PackageVersion")) + .Select(a => (a.Key ?? string.Empty, a.Value ?? string.Empty)); private static readonly Lazy _NewtonsoftJsonPackageVersion = new Lazy(() => GetPackageVersionProperties().Single(p => p.versionPropertyName == "NewtonsoftJsonPackageVersion").version); diff --git a/test/Microsoft.NET.TestFramework/Utilities/BufferedReporter.cs b/test/Microsoft.NET.TestFramework/Utilities/BufferedReporter.cs index cdcec84f34ce..c54607a9f03f 100644 --- a/test/Microsoft.NET.TestFramework/Utilities/BufferedReporter.cs +++ b/test/Microsoft.NET.TestFramework/Utilities/BufferedReporter.cs @@ -1,10 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#pragma warning disable IDE0240 -#nullable enable -#pragma warning restore IDE0240 - using Microsoft.DotNet.Cli.Utils; namespace Microsoft.NET.TestFramework.Utilities diff --git a/test/Microsoft.NET.TestFramework/Utilities/FileThumbPrint.cs b/test/Microsoft.NET.TestFramework/Utilities/FileThumbPrint.cs index c4732f95f55a..8f188989dce9 100644 --- a/test/Microsoft.NET.TestFramework/Utilities/FileThumbPrint.cs +++ b/test/Microsoft.NET.TestFramework/Utilities/FileThumbPrint.cs @@ -53,11 +53,11 @@ public static List CreateFolderThumbprint(TestAsset testAsset, s return thumbprintLookup; } - public bool Equals(FileThumbPrint other) + public bool Equals(FileThumbPrint? other) { return - string.Equals(Path, other.Path, StringComparison.Ordinal) && - LastWriteTimeUtc == other.LastWriteTimeUtc && + string.Equals(Path, other?.Path, StringComparison.Ordinal) && + LastWriteTimeUtc == other?.LastWriteTimeUtc && string.Equals(Hash, other.Hash, StringComparison.Ordinal); } diff --git a/test/Microsoft.NET.TestFramework/Utilities/PeReaderUtils.cs b/test/Microsoft.NET.TestFramework/Utilities/PeReaderUtils.cs index 9fa32ece5b05..2ae00a9eec78 100644 --- a/test/Microsoft.NET.TestFramework/Utilities/PeReaderUtils.cs +++ b/test/Microsoft.NET.TestFramework/Utilities/PeReaderUtils.cs @@ -13,7 +13,7 @@ public static bool IsCrossgened(this PEReader peReader) const int CROSSGEN_FLAG = 4; bool isCrossgened = false; - if (peReader.HasMetadata) + if (peReader.HasMetadata && peReader.PEHeaders.CorHeader is not null) { // 4 is the magic numbers that is set in the CLR header's flags when crossgened. isCrossgened = ((int)peReader.PEHeaders.CorHeader.Flags & CROSSGEN_FLAG) == CROSSGEN_FLAG; @@ -48,7 +48,7 @@ public static bool IsCetCompatible(string filePath) } } - public static string GetAssemblyAttributeValue(string assemblyPath, string attributeName) + public static string? GetAssemblyAttributeValue(string assemblyPath, string attributeName) { if (!File.Exists(assemblyPath)) { @@ -142,7 +142,7 @@ private static List GetFixedStringArguments(MetadataReader reader, Custo if (signatureTypeCode == SignatureTypeCode.String) { // Custom attribute constructor must take only strings - arguments.Add(valueReader.ReadSerializedString()); + arguments.Add(valueReader.ReadSerializedString() ?? string.Empty); } } diff --git a/test/Microsoft.NET.TestFramework/Utilities/ProjectModification.cs b/test/Microsoft.NET.TestFramework/Utilities/ProjectModification.cs index a16381686348..7e3e9181568e 100644 --- a/test/Microsoft.NET.TestFramework/Utilities/ProjectModification.cs +++ b/test/Microsoft.NET.TestFramework/Utilities/ProjectModification.cs @@ -7,6 +7,10 @@ public static class ProjectModification { public static void AddDisplayMessageToProject(XDocument project, string beforeTargets) { + if (project.Root is null) + { + throw new InvalidOperationException($"The project file '{project}' does not have a root element."); + } XNamespace ns = project.Root.Name.Namespace; XElement target = new(ns + "Target", new XAttribute("Name", "DisplayMessages"), diff --git a/test/Microsoft.NET.TestFramework/XunitLoggerProvider.cs b/test/Microsoft.NET.TestFramework/XunitLoggerProvider.cs index f25771bdc311..080e6be34b03 100644 --- a/test/Microsoft.NET.TestFramework/XunitLoggerProvider.cs +++ b/test/Microsoft.NET.TestFramework/XunitLoggerProvider.cs @@ -1,10 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#pragma warning disable IDE0240 -#nullable enable -#pragma warning restore IDE0240 - using Microsoft.Extensions.Logging; using ILogger = Microsoft.Extensions.Logging.ILogger; using LogLevel = Microsoft.Extensions.Logging.LogLevel; diff --git a/test/Microsoft.Win32.Msi.Manual.Tests/Microsoft.Win32.Msi.Manual.Tests.csproj b/test/Microsoft.Win32.Msi.Manual.Tests/Microsoft.Win32.Msi.Manual.Tests.csproj index 3fcce4907598..96730f505a2d 100644 --- a/test/Microsoft.Win32.Msi.Manual.Tests/Microsoft.Win32.Msi.Manual.Tests.csproj +++ b/test/Microsoft.Win32.Msi.Manual.Tests/Microsoft.Win32.Msi.Manual.Tests.csproj @@ -8,6 +8,7 @@ false false true + enable diff --git a/test/Microsoft.Win32.Msi.Manual.Tests/Program.cs b/test/Microsoft.Win32.Msi.Manual.Tests/Program.cs index d475409f56d8..eaf303a54ae8 100644 --- a/test/Microsoft.Win32.Msi.Manual.Tests/Program.cs +++ b/test/Microsoft.Win32.Msi.Manual.Tests/Program.cs @@ -17,7 +17,7 @@ public class Program int ProgressBarTop; bool ForwardProgress; bool ActionDataEnabled; - string CurrentAction; + string? CurrentAction; bool ProgressDone; int ActionDataStep; @@ -104,7 +104,7 @@ void ClearLine() Console.SetCursorPosition(0, top); } - void OnActionData(object sender, ActionDataEventArgs e) + void OnActionData(object? sender, ActionDataEventArgs e) { if (ActionDataEnabled) { @@ -115,7 +115,7 @@ void OnActionData(object sender, ActionDataEventArgs e) e.Result = DialogResult.IDOK; } - void OnActionStart(object send, ActionStartEventArgs e) + void OnActionStart(object? send, ActionStartEventArgs e) { if (ActionDataEnabled) { @@ -134,7 +134,7 @@ void OnActionStart(object send, ActionStartEventArgs e) e.Result = DialogResult.IDOK; } - void OnProgress(object send, ProgressEventArgs e) + void OnProgress(object? send, ProgressEventArgs e) { e.Result = DialogResult.IDOK; diff --git a/test/dotnet-new.Tests/CommonTemplatesTests.cs b/test/dotnet-new.Tests/CommonTemplatesTests.cs index 2b1941764e5c..27bd96e1cfea 100644 --- a/test/dotnet-new.Tests/CommonTemplatesTests.cs +++ b/test/dotnet-new.Tests/CommonTemplatesTests.cs @@ -61,7 +61,7 @@ public async Task AllCommonItemsCreate(string expectedTemplateName, string templ VerifyCommandOutput = true, VerificationExcludePatterns = new[] { "*/stderr.txt", "*\\stderr.txt" }, SettingsDirectory = _fixture.HomeDirectory, - DotnetExecutablePath = TestContext.Current.ToolsetUnderTest.DotNetHostPath, + DotnetExecutablePath = TestContext.Current.ToolsetUnderTest?.DotNetHostPath, DoNotPrependTemplateNameToScenarioName = true, UniqueFor = expectedTemplateName.Equals("NuGet Config") ? UniqueForOption.OsPlatform : null, } @@ -206,7 +206,7 @@ public async Task AotVariants(string name, string language) DoNotAppendTemplateArgsToScenarioName = true, ScenarioName = language.Replace('#', 's').ToLower(), VerificationExcludePatterns = new[] { "*/stderr.txt", "*\\stderr.txt" }, - DotnetExecutablePath = TestContext.Current.ToolsetUnderTest.DotNetHostPath, + DotnetExecutablePath = TestContext.Current.ToolsetUnderTest?.DotNetHostPath, } .WithCustomEnvironment(environmentUnderTest) .WithCustomScrubbers( @@ -405,7 +405,7 @@ public async Task FeaturesSupport( + '#' + (language == null ? "cs" : language.Replace('#', 's').ToLower()) + (langVersion == null ? "#NoLangVer" : (langVersionUnsupported ? "#UnsuportedLangVer" : null)), VerificationExcludePatterns = new[] { "*/stderr.txt", "*\\stderr.txt" }, - DotnetExecutablePath = TestContext.Current.ToolsetUnderTest.DotNetHostPath, + DotnetExecutablePath = TestContext.Current.ToolsetUnderTest?.DotNetHostPath, } .WithCustomEnvironment(environmentUnderTest) .WithCustomScrubbers( diff --git a/test/dotnet-new.Tests/DotnetClassTemplateTests.cs b/test/dotnet-new.Tests/DotnetClassTemplateTests.cs index 3e2385687284..1d1817c5f359 100644 --- a/test/dotnet-new.Tests/DotnetClassTemplateTests.cs +++ b/test/dotnet-new.Tests/DotnetClassTemplateTests.cs @@ -68,7 +68,7 @@ public async Task DotnetCSharpClassTemplatesTest( "*project.*.*" }, SettingsDirectory = _fixture.HomeDirectory, - DotnetExecutablePath = TestContext.Current.ToolsetUnderTest.DotNetHostPath, + DotnetExecutablePath = TestContext.Current.ToolsetUnderTest?.DotNetHostPath, DoNotAppendTemplateArgsToScenarioName = true, DoNotPrependTemplateNameToScenarioName = true, ScenarioName = folderName, @@ -148,7 +148,7 @@ public async Task DotnetVisualBasicClassTemplatesTest( "*project.*.*" }, SettingsDirectory = _fixture.HomeDirectory, - DotnetExecutablePath = TestContext.Current.ToolsetUnderTest.DotNetHostPath, + DotnetExecutablePath = TestContext.Current.ToolsetUnderTest?.DotNetHostPath, DoNotAppendTemplateArgsToScenarioName = true, DoNotPrependTemplateNameToScenarioName = true, ScenarioName = folderName, diff --git a/test/dotnet-new.Tests/DotnetNewArgumentsTests.cs b/test/dotnet-new.Tests/DotnetNewArgumentsTests.cs index 6f8ae07434be..71dbd7b20e97 100644 --- a/test/dotnet-new.Tests/DotnetNewArgumentsTests.cs +++ b/test/dotnet-new.Tests/DotnetNewArgumentsTests.cs @@ -25,7 +25,7 @@ public void ShowsDetailedOutputOnMissedRequiredParam() .Should() .ExitWith(127) .And.HaveStdErrContaining("Required argument missing for option: '-v'") - .And.HaveStdOutContaining(dotnetNewHelpOutput.StdOut); + .And.HaveStdOutContaining(dotnetNewHelpOutput.StdOut ?? string.Empty); } } } diff --git a/test/dotnet-new.Tests/DotnetNewSearchTests.cs b/test/dotnet-new.Tests/DotnetNewSearchTests.cs index 9596ac84b58a..da8369cab4c7 100644 --- a/test/dotnet-new.Tests/DotnetNewSearchTests.cs +++ b/test/dotnet-new.Tests/DotnetNewSearchTests.cs @@ -97,7 +97,7 @@ public void ExamplePrefersMicrosoftPackage(string testCase) IEnumerable> microsoftPackages = tableOutput.Where(row => row[2] == "Microsoft" && row[3].StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase)); IEnumerable installationCommands = microsoftPackages.Select(package => $"new install {package[3].Split(" /")[0]}").ToList(); - bool ContainsOneOfInstallationCommands(string output) => installationCommands.Any(command => output.Contains(command)); + bool ContainsOneOfInstallationCommands(string? output) => installationCommands.Any(command => output is not null && output.Contains(command)); commandResult.Should().HaveStdOutContaining(ContainsOneOfInstallationCommands, "Checks if the output contains one of the expected installation commands"); } diff --git a/test/dotnet-new.Tests/TemplateEngineSamplesTest.cs b/test/dotnet-new.Tests/TemplateEngineSamplesTest.cs index 4b9b0710a2b5..2783789100df 100644 --- a/test/dotnet-new.Tests/TemplateEngineSamplesTest.cs +++ b/test/dotnet-new.Tests/TemplateEngineSamplesTest.cs @@ -56,7 +56,7 @@ public async Task TemplateEngineSamplesProjectTest( SnapshotsDirectory = "Approvals", SettingsDirectory = _sharedHome.HomeDirectory, DoNotAppendTemplateArgsToScenarioName = true, - DotnetExecutablePath = TestContext.Current.ToolsetUnderTest.DotNetHostPath, + DotnetExecutablePath = TestContext.Current.ToolsetUnderTest?.DotNetHostPath, DoNotPrependCallerMethodNameToScenarioName = true, ScenarioName = $"{folderName.Substring(folderName.IndexOf("-") + 1)}{GetScenarioName(arguments)}" } diff --git a/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs b/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs index d0c23f109cf3..25f4b52c0e71 100644 --- a/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs +++ b/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs @@ -80,7 +80,7 @@ public async Task UpdateAndRudeEdit(TriggerEvent trigger) var program = Program.TryCreate( TestOptions.GetCommandLineOptions(["--verbose", "--non-interactive", "--project", hostProject]), console, - TestOptions.GetEnvironmentOptions(workingDirectory, TestContext.Current.ToolsetUnderTest.DotNetHostPath), + TestOptions.GetEnvironmentOptions(workingDirectory, TestContext.Current.ToolsetUnderTest?.DotNetHostPath), reporter, out var errorCode); @@ -270,7 +270,7 @@ public async Task UpdateAppliedToNewProcesses(bool sharedOutput) var program = Program.TryCreate( TestOptions.GetCommandLineOptions(["--verbose", "--non-interactive", "--project", hostProject]), console, - TestOptions.GetEnvironmentOptions(workingDirectory, TestContext.Current.ToolsetUnderTest.DotNetHostPath), + TestOptions.GetEnvironmentOptions(workingDirectory, TestContext.Current.ToolsetUnderTest?.DotNetHostPath), reporter, out var errorCode); @@ -386,7 +386,7 @@ public async Task HostRestart(UpdateLocation updateLocation) var program = Program.TryCreate( TestOptions.GetCommandLineOptions(["--verbose", "--project", hostProject]), console, - TestOptions.GetEnvironmentOptions(workingDirectory, TestContext.Current.ToolsetUnderTest.DotNetHostPath), + TestOptions.GetEnvironmentOptions(workingDirectory, TestContext.Current.ToolsetUnderTest?.DotNetHostPath), reporter, out var errorCode); diff --git a/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs b/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs index 41b03dbd8876..ca3acea03d11 100644 --- a/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs @@ -422,7 +422,7 @@ private async Task Evaluate(string projectPath) return result; } - private static string GetTestProjectPath(TestAsset target) => Path.Combine(GetTestProjectDirectory(target), target.TestProject.Name + ".csproj"); + private static string GetTestProjectPath(TestAsset target) => Path.Combine(GetTestProjectDirectory(target), target.TestProject?.Name + ".csproj"); private static string WriteFile(TestAsset testAsset, string name, string contents = "") { @@ -443,6 +443,6 @@ private static string WriteFile(TestDirectory testAsset, string name, string con } private static string GetTestProjectDirectory(TestAsset testAsset) - => Path.Combine(testAsset.Path, testAsset.TestProject.Name); + => Path.Combine(testAsset.Path, testAsset.TestProject?.Name ?? string.Empty); } } diff --git a/test/dotnet.Tests/dotnet-new/SdkInfoProviderTests.cs b/test/dotnet.Tests/dotnet-new/SdkInfoProviderTests.cs index c9cf04a4d91c..a63d67dd772c 100644 --- a/test/dotnet.Tests/dotnet-new/SdkInfoProviderTests.cs +++ b/test/dotnet.Tests/dotnet-new/SdkInfoProviderTests.cs @@ -15,7 +15,7 @@ public class SdkInfoProviderTests [Fact] public async Task GetInstalledVersionsAsync_ShouldContainCurrentVersion() { - string dotnetRootUnderTest = TestContext.Current.ToolsetUnderTest.DotNetRoot; + string? dotnetRootUnderTest = TestContext.Current.ToolsetUnderTest?.DotNetRoot; string? pathOrig = Environment.GetEnvironmentVariable("PATH"); Environment.SetEnvironmentVariable("PATH", dotnetRootUnderTest + Path.PathSeparator + pathOrig);