diff --git a/NUnitConsole.sln b/NUnitConsole.sln
index 24c9bd494..61aecb8b9 100644
--- a/NUnitConsole.sln
+++ b/NUnitConsole.sln
@@ -25,6 +25,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
NetCoreTests.nunit = NetCoreTests.nunit
NOTICES.txt = NOTICES.txt
NuGet.config = NuGet.config
+ src\Nullable.props = src\Nullable.props
nunit.ico = nunit.ico
package-tests.cake = package-tests.cake
README.md = README.md
diff --git a/build.cake b/build.cake
index 5dc053fe0..b7c5ccfcc 100644
--- a/build.cake
+++ b/build.cake
@@ -12,7 +12,7 @@ BuildSettings.Initialize(
githubRepository: "nunit-console",
solutionFile: "NUnitConsole.sln",
buildWithMSBuild: true,
- exemptFiles: new[] { "Options.cs", "ProcessUtils.cs", "ProcessUtilsTests.cs" });
+ exemptFiles: new[] { "Options.cs", "ProcessUtils.cs", "ProcessUtilsTests.cs", "CallerArgumentExpressionAttribute.cs" });
//////////////////////////////////////////////////////////////////////
// INDIVIDUAL PACKAGE DEFINITIONS
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 6364dbe24..0561b6fae 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -7,6 +7,7 @@
true
NUnit Software
Copyright (c) 2022 Charlie Poole, Rob Prouse
+ false
@@ -15,4 +16,4 @@
3.99.0.0-VSIDE
-
\ No newline at end of file
+
diff --git a/src/NUnitConsole/nunit4-console.tests/CommandLineTests.cs b/src/NUnitConsole/nunit4-console.tests/CommandLineTests.cs
index 691e6ec86..2a5c3a615 100644
--- a/src/NUnitConsole/nunit4-console.tests/CommandLineTests.cs
+++ b/src/NUnitConsole/nunit4-console.tests/CommandLineTests.cs
@@ -160,7 +160,7 @@ public void CanRecognizeBooleanOptions(string propertyName, string pattern)
string[] prototypes = pattern.Split('|');
PropertyInfo property = GetPropertyInfo(propertyName);
- Assert.That(property.PropertyType, Is.EqualTo(typeof(bool)), "Property '{0}' is wrong type", propertyName);
+ Assert.That(property.PropertyType, Is.EqualTo(typeof(bool)), $"Property '{propertyName}' is wrong type");
foreach (string option in prototypes)
{
@@ -169,22 +169,22 @@ public void CanRecognizeBooleanOptions(string propertyName, string pattern)
if (option.Length == 1)
{
options = ConsoleMocks.Options("-" + option);
- Assert.That((bool)property.GetValue(options, null), Is.EqualTo(true), "Didn't recognize -" + option);
+ Assert.That((bool?)property.GetValue(options, null), Is.EqualTo(true), "Didn't recognize -" + option);
options = ConsoleMocks.Options("-" + option + "+");
- Assert.That((bool)property.GetValue(options, null), Is.EqualTo(true), "Didn't recognize -" + option + "+");
+ Assert.That((bool?)property.GetValue(options, null), Is.EqualTo(true), "Didn't recognize -" + option + "+");
options = ConsoleMocks.Options("-" + option + "-");
- Assert.That((bool)property.GetValue(options, null), Is.EqualTo(false), "Didn't recognize -" + option + "-");
+ Assert.That((bool?)property.GetValue(options, null), Is.EqualTo(false), "Didn't recognize -" + option + "-");
}
else
{
options = ConsoleMocks.Options("--" + option);
- Assert.That((bool)property.GetValue(options, null), Is.EqualTo(true), "Didn't recognize --" + option);
+ Assert.That((bool?)property.GetValue(options, null), Is.EqualTo(true), "Didn't recognize --" + option);
}
options = ConsoleMocks.Options("/" + option);
- Assert.That((bool)property.GetValue(options, null), Is.EqualTo(true), "Didn't recognize /" + option);
+ Assert.That((bool?)property.GetValue(options, null), Is.EqualTo(true), "Didn't recognize /" + option);
}
}
@@ -217,7 +217,7 @@ public void CanRecognizeStringOptions(string propertyName, string pattern, strin
string optionPlusValue = string.Format("--{0}:{1}", option, value);
ConsoleOptions options = ConsoleMocks.Options(optionPlusValue);
Assert.That(options.ErrorMessages.Count, Is.EqualTo(0), "Should be valid: " + optionPlusValue);
- Assert.That((string)property.GetValue(options, null), Is.EqualTo(value), "Didn't recognize " + optionPlusValue);
+ Assert.That((string?)property.GetValue(options, null), Is.EqualTo(value), "Didn't recognize " + optionPlusValue);
}
foreach (string value in badValues)
@@ -242,7 +242,7 @@ public void CanRecognizeLowerCaseOptionValues(string propertyName, string option
string optionPlusValue = string.Format("--{0}:{1}", optionName, lowercaseValue);
ConsoleOptions options = ConsoleMocks.Options(optionPlusValue);
Assert.That(options.ErrorMessages.Count, Is.EqualTo(0), "Should be valid: " + optionPlusValue);
- Assert.That((string)property.GetValue(options, null), Is.EqualTo(canonicalValue), "Didn't recognize " + optionPlusValue);
+ Assert.That((string?)property.GetValue(options, null), Is.EqualTo(canonicalValue), "Didn't recognize " + optionPlusValue);
}
}
@@ -262,7 +262,7 @@ public void CanRecognizeIntOptions(string propertyName, string pattern)
foreach (string option in prototypes)
{
ConsoleOptions options = ConsoleMocks.Options("--" + option + ":42");
- Assert.That((int)property.GetValue(options, null), Is.EqualTo(42), "Didn't recognize --" + option + ":42");
+ Assert.That((int?)property.GetValue(options, null), Is.EqualTo(42), "Didn't recognize --" + option + ":42");
}
}
@@ -750,14 +750,14 @@ private static IFileSystem GetFileSystemContainingFile(string fileName)
private static FieldInfo GetFieldInfo(string fieldName)
{
- FieldInfo field = typeof(ConsoleOptions).GetField(fieldName);
+ FieldInfo? field = typeof(ConsoleOptions).GetField(fieldName);
Assert.That(field, Is.Not.Null, $"The field '{fieldName}' is not defined");
return field;
}
private static PropertyInfo GetPropertyInfo(string propertyName)
{
- PropertyInfo property = typeof(ConsoleOptions).GetProperty(propertyName);
+ PropertyInfo? property = typeof(ConsoleOptions).GetProperty(propertyName);
Assert.That(property, Is.Not.Null, $"The property '{propertyName}' is not defined");
return property;
}
diff --git a/src/NUnitConsole/nunit4-console.tests/ConsoleOutputTests.cs b/src/NUnitConsole/nunit4-console.tests/ConsoleOutputTests.cs
index 2feb6fca0..9dcc2a330 100644
--- a/src/NUnitConsole/nunit4-console.tests/ConsoleOutputTests.cs
+++ b/src/NUnitConsole/nunit4-console.tests/ConsoleOutputTests.cs
@@ -13,7 +13,7 @@ public void OneTimeSetUp()
{
Console.WriteLine("OneTimeSetUp: Console.WriteLine()");
Console.Error.WriteLine("OneTimeSetUp: Console.Error.WriteLine()");
- TestContext.WriteLine("OneTimeSetUp: TestContext.WriteLine()");
+ TestContext.Out.WriteLine("OneTimeSetUp: TestContext.WriteLine()");
}
@@ -22,7 +22,7 @@ public void SetUp()
{
Console.WriteLine("SetUp: Console.WriteLine()");
Console.Error.WriteLine("SetUp: Console.Error.WriteLine()");
- TestContext.WriteLine("SetUp: TestContext.WriteLine()");
+ TestContext.Out.WriteLine("SetUp: TestContext.WriteLine()");
}
[TearDown]
@@ -30,7 +30,7 @@ public void TearDown()
{
Console.WriteLine("TearDown: Console.WriteLine()");
Console.Error.WriteLine("TearDown: Console.Error.WriteLine()");
- TestContext.WriteLine("TearDown: TestContext.WriteLine()");
+ TestContext.Out.WriteLine("TearDown: TestContext.WriteLine()");
}
[OneTimeTearDown]
@@ -38,7 +38,7 @@ public void OneTimeTearDown()
{
Console.WriteLine("OneTimeTearDown: Console.WriteLine()");
Console.Error.WriteLine("OneTimeTearDown: Console.Error.WriteLine()");
- TestContext.WriteLine("OneTimeTearDown: TestContext.WriteLine()");
+ TestContext.Out.WriteLine("OneTimeTearDown: TestContext.WriteLine()");
}
[Test]
@@ -46,13 +46,13 @@ public void Test()
{
Console.WriteLine("Test: Console.WriteLine()");
Console.Error.WriteLine("Test: Console.Error.WriteLine()");
- TestContext.WriteLine("Test: TestContext.WriteLine()");
+ TestContext.Out.WriteLine("Test: TestContext.WriteLine()");
}
[Test]
public void ConsoleEncoding()
{
- TestContext.WriteLine("•ÑÜńĭŧ·");
+ TestContext.Out.WriteLine("•ÑÜńĭŧ·");
}
}
}
diff --git a/src/NUnitConsole/nunit4-console.tests/ConsoleRunnerTests.cs b/src/NUnitConsole/nunit4-console.tests/ConsoleRunnerTests.cs
index 01c080344..e49dd7d8d 100644
--- a/src/NUnitConsole/nunit4-console.tests/ConsoleRunnerTests.cs
+++ b/src/NUnitConsole/nunit4-console.tests/ConsoleRunnerTests.cs
@@ -28,6 +28,13 @@ public void SetUp()
_testEngine.Services.GetService().Returns(_resultService);
}
+ [TearDown]
+ public void TearDown()
+ {
+ (_resultService as IDisposable)?.Dispose();
+ _testEngine.Dispose();
+ }
+
[Test]
public void ThrowsNUnitEngineExceptionWhenTestResultsAreNotWriteable()
{
@@ -62,7 +69,7 @@ public string[] Formats
}
}
- public IResultWriter GetResultWriter(string format, object[] args)
+ public IResultWriter GetResultWriter(string format, params object?[]? args)
{
return new FakeResultWriter(this);
}
diff --git a/src/NUnitConsole/nunit4-console.tests/ExtendedTextWrapperTests.cs b/src/NUnitConsole/nunit4-console.tests/ExtendedTextWrapperTests.cs
index 67b3e1b3f..7d4cec81c 100644
--- a/src/NUnitConsole/nunit4-console.tests/ExtendedTextWrapperTests.cs
+++ b/src/NUnitConsole/nunit4-console.tests/ExtendedTextWrapperTests.cs
@@ -25,6 +25,12 @@ public void SetUp()
writer = new ExtendedTextWrapper(new StringWriter(sb));
}
+ [TearDown]
+ public void TearDown()
+ {
+ writer.Dispose();
+ }
+
[Test]
public void Write()
{
diff --git a/src/NUnitConsole/nunit4-console.tests/MakeTestPackageTests.cs b/src/NUnitConsole/nunit4-console.tests/MakeTestPackageTests.cs
index f0872a4e3..b8855d4fe 100644
--- a/src/NUnitConsole/nunit4-console.tests/MakeTestPackageTests.cs
+++ b/src/NUnitConsole/nunit4-console.tests/MakeTestPackageTests.cs
@@ -59,8 +59,8 @@ public void WhenOptionIsSpecified_PackageIncludesSetting(string option, string k
var options = ConsoleMocks.Options("test.dll", option);
var package = ConsoleRunner.MakeTestPackage(options);
- Assert.That(package.Settings.ContainsKey(key), "Setting not included for {0}", option);
- Assert.That(package.Settings[key], Is.EqualTo(val), "NumberOfTestWorkers not set correctly for {0}", option);
+ Assert.That(package.Settings.ContainsKey(key), $"Setting not included for {options}", option);
+ Assert.That(package.Settings[key], Is.EqualTo(val), $"NumberOfTestWorkers not set correctly for {option}");
}
[Test]
@@ -71,6 +71,7 @@ public void TestRunParametersAreIncludedInSettings()
Assert.That(settings.ContainsKey("TestParametersDictionary"), "TestParametersDictionary setting not included.");
var paramDictionary = settings["TestParametersDictionary"] as IDictionary;
+ Assert.That(paramDictionary, Is.Not.Null);
Assert.That(paramDictionary.Keys, Is.EqualTo(new[] { "X", "Y" }));
Assert.That(paramDictionary["X"], Is.EqualTo("5"));
Assert.That(paramDictionary["Y"], Is.EqualTo("7"));
diff --git a/src/NUnitConsole/nunit4-console.tests/Options/OutputSpecificationTests.cs b/src/NUnitConsole/nunit4-console.tests/Options/OutputSpecificationTests.cs
index 449e7f2c1..7bb462650 100644
--- a/src/NUnitConsole/nunit4-console.tests/Options/OutputSpecificationTests.cs
+++ b/src/NUnitConsole/nunit4-console.tests/Options/OutputSpecificationTests.cs
@@ -11,7 +11,7 @@ public class OutputSpecificationTests
public void SpecMayNotBeNull()
{
Assert.That(
- () => new OutputSpecification(null, null),
+ () => new OutputSpecification(null!, null),
Throws.TypeOf());
}
@@ -109,7 +109,7 @@ public void TransformWithNonUserFormatNotAllowed()
[TestCase(@"C:\")]
[TestCase(@"C:\Temp")]
- public void TransformFolderIsUsedToSpecifyTransform(string transformFolder)
+ public void TransformFolderIsUsedToSpecifyTransform(string? transformFolder)
{
const string fileName = "transform.xslt";
var spec = new OutputSpecification($"MyFile.xml;transform=transform.xslt", transformFolder);
diff --git a/src/NUnitConsole/nunit4-console.tests/ResultReporterTests.cs b/src/NUnitConsole/nunit4-console.tests/ResultReporterTests.cs
index f21bc5693..e347e57cb 100644
--- a/src/NUnitConsole/nunit4-console.tests/ResultReporterTests.cs
+++ b/src/NUnitConsole/nunit4-console.tests/ResultReporterTests.cs
@@ -191,7 +191,7 @@ private IList GetReportLines(TestDelegate del)
{
var rdr = new StringReader(GetReport(del));
- string line;
+ string? line;
var lines = new List();
while ((line = rdr.ReadLine()) != null)
lines.Add(line);
diff --git a/src/NUnitConsole/nunit4-console.tests/TestEventHandlerTests.cs b/src/NUnitConsole/nunit4-console.tests/TestEventHandlerTests.cs
index 7bae81eb5..54c8f09a3 100644
--- a/src/NUnitConsole/nunit4-console.tests/TestEventHandlerTests.cs
+++ b/src/NUnitConsole/nunit4-console.tests/TestEventHandlerTests.cs
@@ -21,13 +21,19 @@ public void CreateWriter()
_writer = new ExtendedTextWrapper(new StringWriter(_output));
}
+ [TearDown]
+ public void DisposeWriter()
+ {
+ _writer.Dispose();
+ }
+
[TestCase(char.MaxValue)]
public void TestNameContainsInvalidChar(char c)
{
Console.WriteLine($"Test for char {c}");
}
- [TestCaseSource("SingleEventData")]
+ [TestCaseSource(nameof(SingleEventData))]
public void SingleEventsWriteExpectedOutput(string report, string labels, string expected)
{
var handler = new TestEventHandler(_writer, labels);
@@ -39,7 +45,7 @@ public void SingleEventsWriteExpectedOutput(string report, string labels, string
Assert.That(Output, Is.EqualTo(expected));
}
- [TestCaseSource("MultipleEventData")]
+ [TestCaseSource(nameof(MultipleEventData))]
public void MultipleEvents(string[] reports, string labels, string expected)
{
var handler = new TestEventHandler(_writer, labels);
@@ -56,8 +62,7 @@ public void MultipleEvents(string[] reports, string labels, string expected)
Assert.That(Output, Is.EqualTo(expected));
}
-#pragma warning disable 414
- static TestCaseData[] SingleEventData = new TestCaseData[]
+ static readonly TestCaseData[] SingleEventData = new TestCaseData[]
{
// Start Events
new TestCaseData("", "Off", ""),
@@ -269,7 +274,7 @@ public void MultipleEvents(string[] reports, string labels, string expected)
""
};
- static TestCaseData[] MultipleEventData = new TestCaseData[]
+ static readonly TestCaseData[] MultipleEventData = new TestCaseData[]
{
new TestCaseData(
SingleTest_StartAndFinish,
diff --git a/src/NUnitConsole/nunit4-console.tests/VirtualFileSystem.cs b/src/NUnitConsole/nunit4-console.tests/VirtualFileSystem.cs
index 3670abb61..781be9f0d 100644
--- a/src/NUnitConsole/nunit4-console.tests/VirtualFileSystem.cs
+++ b/src/NUnitConsole/nunit4-console.tests/VirtualFileSystem.cs
@@ -3,11 +3,10 @@
using System;
using System.Collections.Generic;
using NUnit.Common;
+using System.IO;
namespace NUnit.ConsoleRunner
{
- using System.IO;
-
internal class VirtualFileSystem: IFileSystem
{
private readonly Dictionary> files = new Dictionary>();
@@ -19,7 +18,7 @@ public bool FileExists(string fileName)
public IEnumerable ReadLines(string fileName)
{
- IEnumerable lines;
+ IEnumerable? lines;
if (!files.TryGetValue(fileName, out lines))
{
throw new FileNotFoundException("File not found", fileName);
diff --git a/src/NUnitConsole/nunit4-console.tests/nunit4-console.tests.csproj b/src/NUnitConsole/nunit4-console.tests/nunit4-console.tests.csproj
index c6ad0c8ad..def87260f 100644
--- a/src/NUnitConsole/nunit4-console.tests/nunit4-console.tests.csproj
+++ b/src/NUnitConsole/nunit4-console.tests/nunit4-console.tests.csproj
@@ -16,6 +16,8 @@
Tests of the NUnit Console Runner
+
+
@@ -24,7 +26,11 @@
-
+
+
+
+
+
PreserveNewest
diff --git a/src/NUnitConsole/nunit4-console/ColorConsoleWriter.cs b/src/NUnitConsole/nunit4-console/ColorConsoleWriter.cs
index e01ef7986..69d77653e 100644
--- a/src/NUnitConsole/nunit4-console/ColorConsoleWriter.cs
+++ b/src/NUnitConsole/nunit4-console/ColorConsoleWriter.cs
@@ -86,11 +86,10 @@ public override void WriteLabelLine(string label, object option)
/// The color to display the value with
public override void WriteLabel(string label, object option, ColorStyle valueStyle)
{
- if (option == null)
- throw new NullReferenceException(nameof(option));
+ Guard.ArgumentNotNull(option, nameof(option));
Write(ColorStyle.Label, label);
- Write(valueStyle, option.ToString());
+ Write(valueStyle, option.ToString() ?? string.Empty);
}
///
diff --git a/src/NUnitConsole/nunit4-console/ConsoleOptions.cs b/src/NUnitConsole/nunit4-console/ConsoleOptions.cs
index ed746ed43..66d60717d 100644
--- a/src/NUnitConsole/nunit4-console/ConsoleOptions.cs
+++ b/src/NUnitConsole/nunit4-console/ConsoleOptions.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
@@ -52,7 +53,9 @@ internal ConsoleOptions(IDefaultOptionsProvider defaultOptionsProvider, IFileSys
public IDictionary TestParameters { get; } = new Dictionary();
- public string WhereClause { get; private set; }
+ public string? WhereClause { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(WhereClause))]
public bool WhereClauseSpecified { get { return WhereClause != null; } }
public int DefaultTestCaseTimeout { get; private set; } = -1;
@@ -61,7 +64,7 @@ internal ConsoleOptions(IDefaultOptionsProvider defaultOptionsProvider, IFileSys
public int RandomSeed { get; private set; } = -1;
public bool RandomSeedSpecified { get { return RandomSeed >= 0; } }
- public string DefaultTestNamePattern { get; private set; }
+ public string? DefaultTestNamePattern { get; private set; }
public int NumberOfTestWorkers { get; private set; } = -1;
public bool NumberOfTestWorkersSpecified { get { return NumberOfTestWorkers >= 0; } }
@@ -71,7 +74,7 @@ internal ConsoleOptions(IDefaultOptionsProvider defaultOptionsProvider, IFileSys
// Output Control
- public string ConsoleEncoding { get; private set; }
+ public string? ConsoleEncoding { get; private set; }
public bool NoHeader { get; private set; }
@@ -79,19 +82,23 @@ internal ConsoleOptions(IDefaultOptionsProvider defaultOptionsProvider, IFileSys
public bool TeamCity { get; private set; }
- public string OutFile { get; private set; }
+ public string? OutFile { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(OutFile))]
public bool OutFileSpecified { get { return OutFile != null; } }
- public string DisplayTestLabels { get; private set; }
+ public string? DisplayTestLabels { get; private set; }
- private string workDirectory = null;
+ private string? workDirectory = null;
public string WorkDirectory
{
get { return workDirectory ?? CURRENT_DIRECTORY_ON_ENTRY; }
}
public bool WorkDirectorySpecified { get { return workDirectory != null; } }
- public string InternalTraceLevel { get; private set; }
+ public string? InternalTraceLevel { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(InternalTraceLevel))]
public bool InternalTraceLevelSpecified { get { return InternalTraceLevel != null; } }
private readonly List resultOutputSpecifications = new List();
@@ -114,15 +121,19 @@ public IList ResultOutputSpecifications
public IList ExploreOutputSpecifications { get; } = new List();
- public string ActiveConfig { get; private set; }
+ public string? ActiveConfig { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(ActiveConfig))]
public bool ActiveConfigSpecified { get { return ActiveConfig != null; } }
// How to Run Tests
- public string RuntimeFramework { get; private set; }
+ public string? RuntimeFramework { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(RuntimeFramework))]
public bool RuntimeFrameworkSpecified { get { return RuntimeFramework != null; } }
- public string ConfigurationFile { get; private set; }
+ public string? ConfigurationFile { get; private set; }
public bool RunAsX86 { get; private set; }
@@ -146,7 +157,7 @@ public IList ResultOutputSpecifications
public bool PauseBeforeRun { get; private set; }
- public string PrincipalPolicy { get; private set; }
+ public string? PrincipalPolicy { get; private set; }
public IList WarningMessages { get; } = new List();
@@ -179,7 +190,7 @@ private void ConfigureOptions()
{
while (!rdr.EndOfStream)
{
- var line = rdr.ReadLine().Trim();
+ var line = rdr.ReadLine()?.Trim();
if (!string.IsNullOrEmpty(line) && line[0] != '#')
((List)TestList).Add(line);
@@ -216,10 +227,10 @@ private void ConfigureOptions()
v => NumberOfTestWorkers = parser.RequiredInt(v, "--workers"));
this.Add("stoponerror", "Stop run immediately upon any test failure or error.",
- v => StopOnError = v != null);
+ v => StopOnError = !string.IsNullOrEmpty(v));
this.Add("wait", "Wait for input before closing console window.",
- v => WaitBeforeExit = v != null);
+ v => WaitBeforeExit = !string.IsNullOrEmpty(v));
// Output Control
this.Add("work=", "{PATH} of the directory to use for output files. If not specified, defaults to the current directory.",
@@ -243,7 +254,7 @@ private void ConfigureOptions()
});
this.Add("noresult", "Don't save any test results.",
- v => NoResultSpecified = v != null);
+ v => NoResultSpecified = !string.IsNullOrEmpty(v));
this.Add("labels=", "Specify whether to write test case names to the output. Values: Off (Default), On, OnOutput, Before, After, BeforeAndAfter. On is currently an alias for OnOutput, but is subject to change.",
v => {
@@ -257,19 +268,19 @@ private void ConfigureOptions()
v => InternalTraceLevel = parser.RequiredValue(v, "--trace", "Off", "Error", "Warning", "Info", "Verbose", "Debug"));
this.Add("teamcity", "Turns on use of TeamCity service messages. TeamCity engine extension is required.",
- v => TeamCity = v != null);
+ v => TeamCity = !string.IsNullOrEmpty(v));
this.Add("noheader|noh", "Suppress display of program information at start of run.",
- v => NoHeader = v != null);
+ v => NoHeader = !string.IsNullOrEmpty(v));
this.Add("nocolor|noc", "Displays console output without color.",
- v => NoColor = v != null);
+ v => NoColor = !string.IsNullOrEmpty(v));
this.Add("help|h", "Display this message and exit.",
- v => ShowHelp = v != null);
+ v => ShowHelp = !string.IsNullOrEmpty(v));
this.Add("version|V", "Display the header and exit.",
- v => ShowVersion = v != null);
+ v => ShowVersion = !string.IsNullOrEmpty(v));
this.Add("encoding=", "Specifies the encoding to use for Console standard output, for example utf-8, ascii, unicode.",
v => ConsoleEncoding = parser.RequiredValue(v, "--encoding"));
@@ -294,38 +305,38 @@ private void ConfigureOptions()
NetFxOnlyOption("framework=", v => RuntimeFramework = parser.RequiredValue(v, "--framework")));
this.AddNetFxOnlyOption("x86", "Run tests in an x86 process on 64 bit systems",
- NetFxOnlyOption("x86", v => RunAsX86 = v != null));
+ NetFxOnlyOption("x86", v => RunAsX86 = !string.IsNullOrEmpty(v)));
this.Add("dispose-runners", "Dispose each test runner after it has finished running its tests.",
- v => DisposeRunners = v != null);
+ v => DisposeRunners = !string.IsNullOrEmpty(v));
this.AddNetFxOnlyOption("shadowcopy", "Shadow copy test files",
- NetFxOnlyOption("shadowcopy", v => ShadowCopyFiles = v != null));
+ NetFxOnlyOption("shadowcopy", v => ShadowCopyFiles = !string.IsNullOrEmpty(v)));
this.AddNetFxOnlyOption("loaduserprofile", "Load user profile in test runner processes",
- NetFxOnlyOption("loaduserprofile", v => LoadUserProfile = v != null));
+ NetFxOnlyOption("loaduserprofile", v => LoadUserProfile = !string.IsNullOrEmpty(v)));
this.Add("skipnontestassemblies", "Skip any non-test assemblies specified, without error.",
- v => SkipNonTestAssemblies = v != null);
+ v => SkipNonTestAssemblies = !string.IsNullOrEmpty(v));
this.AddNetFxOnlyOption("agents=", "Specify the maximum {NUMBER} of test assembly agents to run at one time. If not specified, there is no limit.",
NetFxOnlyOption("agents=", v => _maxAgents = parser.RequiredInt(v, "--agents")));
this.AddNetFxOnlyOption("debug", "Launch debugger to debug tests.",
- NetFxOnlyOption("debug", v => DebugTests = v != null));
+ NetFxOnlyOption("debug", v => DebugTests = !string.IsNullOrEmpty(v)));
this.AddNetFxOnlyOption("pause", "Pause before running to allow attaching a debugger.",
- NetFxOnlyOption("pause", v => PauseBeforeRun = v != null));
+ NetFxOnlyOption("pause", v => PauseBeforeRun = !string.IsNullOrEmpty(v)));
this.Add("list-extensions", "List all extension points and the extensions for each.",
- v => ListExtensions = v != null);
+ v => ListExtensions = !string.IsNullOrEmpty(v));
this.AddNetFxOnlyOption("set-principal-policy=", "Set PrincipalPolicy for the test domain.",
NetFxOnlyOption("set-principal-policy=", v => PrincipalPolicy = parser.RequiredValue(v, "--set-principal-policy", "UnauthenticatedPrincipal", "NoPrincipal", "WindowsPrincipal")));
#if DEBUG
this.AddNetFxOnlyOption("debug-agent", "Launch debugger in nunit-agent when it starts.",
- NetFxOnlyOption("debug-agent", v => DebugAgent = v != null));
+ NetFxOnlyOption("debug-agent", v => DebugAgent = !string.IsNullOrEmpty(v)));
#endif
}
@@ -431,7 +442,7 @@ private IEnumerable GetArgsFromFile(string filename)
return GetArgs(sb.ToString());
}
- private string ExpandToFullPath(string path)
+ private string? ExpandToFullPath(string path)
{
if (path == null) return null;
diff --git a/src/NUnitConsole/nunit4-console/ConsoleRunner.cs b/src/NUnitConsole/nunit4-console/ConsoleRunner.cs
index 7bdc21d99..e01e99895 100644
--- a/src/NUnitConsole/nunit4-console/ConsoleRunner.cs
+++ b/src/NUnitConsole/nunit4-console/ConsoleRunner.cs
@@ -142,7 +142,7 @@ private int ExploreTests(TestPackage package, TestFilter filter)
{
foreach (OutputSpecification spec in _options.ExploreOutputSpecifications)
{
- _resultService.GetResultWriter(spec.Format, new object[] {spec.Transform}).WriteResultFile(result, spec.OutputPath);
+ _resultService.GetResultWriter(spec.Format, spec.Transform).WriteResultFile(result, spec.OutputPath);
_outWriter.WriteLine("Results ({0}) saved as {1}", spec.Format, spec.OutputPath);
}
}
@@ -172,7 +172,7 @@ private int RunTests(TestPackage package, TestFilter filter)
try
{
- var outputDirectory = Path.GetDirectoryName(outputPath);
+ var outputDirectory = Path.GetDirectoryName(outputPath)!;
Directory.CreateDirectory(outputDirectory);
}
catch (Exception ex)
@@ -202,9 +202,9 @@ private int RunTests(TestPackage package, TestFilter filter)
? _options.DisplayTestLabels.ToUpperInvariant()
: "ON";
- XmlNode result = null;
- NUnitEngineUnloadException unloadException = null;
- NUnitEngineException engineException = null;
+ XmlNode? result = null;
+ NUnitEngineUnloadException? unloadException = null;
+ NUnitEngineException? engineException = null;
try
{
@@ -298,7 +298,7 @@ private static string GetOSVersion()
if (uname(buf) == 0)
{
var unixVariant = Marshal.PtrToStringAnsi(buf);
- if (unixVariant.Equals("Darwin"))
+ if (string.Equals(unixVariant, "Darwin"))
unixVariant = "MacOSX";
osString = string.Format("{0} {1} {2}", unixVariant, os.Version, os.ServicePack);
@@ -380,7 +380,7 @@ private ExtendedTextWriter CreateOutputWriter()
private IResultWriter GetResultWriter(OutputSpecification spec)
{
- return _resultService.GetResultWriter(spec.Format, new object[] {spec.Transform});
+ return _resultService.GetResultWriter(spec.Format, spec.Transform);
}
// This is public static for ease of testing
diff --git a/src/NUnitConsole/nunit4-console/ConsoleTestResult.cs b/src/NUnitConsole/nunit4-console/ConsoleTestResult.cs
index 971bc3fa0..19265bd28 100644
--- a/src/NUnitConsole/nunit4-console/ConsoleTestResult.cs
+++ b/src/NUnitConsole/nunit4-console/ConsoleTestResult.cs
@@ -31,23 +31,23 @@ public ConsoleTestResult(XmlNode resultNode, int reportIndex)
Label = resultNode.GetAttribute("label");
Site = resultNode.GetAttribute("site");
- Status = Label ?? Result;
+ Status = Label ?? Result ?? "Unkown";
if (Status == "Failed" || Status == "Error")
if (Site == "SetUp" || Site == "TearDown")
Status = Site + " " + Status;
- FullName = resultNode.GetAttribute("fullname");
+ FullName = resultNode.GetAttribute("fullname") ?? "Unknown";
}
- public string Result { get; private set; }
- public string Label { get; private set; }
- public string Site { get; private set; }
+ public string? Result { get; private set; }
+ public string? Label { get; private set; }
+ public string? Site { get; private set; }
public string FullName { get; private set; }
public string ReportID { get; private set; }
public string Status { get; private set; }
- public string Message
+ public string? Message
{
get
{
@@ -56,12 +56,12 @@ public string Message
}
}
- public string StackTrace
+ public string? StackTrace
{
get { return GetTrimmedInnerText(_resultNode.SelectSingleNode("failure/stack-trace")); }
}
- private List _assertions;
+ private List? _assertions;
public List Assertions
{
get
@@ -69,8 +69,10 @@ public List Assertions
if (_assertions == null)
{
_assertions = new List();
- foreach (XmlNode assertion in _resultNode.SelectNodes("assertions/assertion"))
- Assertions.Add(new ConsoleTestResult.AssertionResult(assertion));
+ XmlNodeList? assertions = _resultNode.SelectNodes("assertions/assertion");
+ if (assertions is not null)
+ foreach (XmlNode assertion in assertions)
+ Assertions.Add(new ConsoleTestResult.AssertionResult(assertion));
}
return _assertions;
@@ -98,7 +100,7 @@ public void WriteResult(ExtendedTextWriter writer)
WriteResult(writer, ReportID, Status, FullName, Message, StackTrace);
}
- private void WriteResult(ExtendedTextWriter writer, string reportID, string status, string fullName, string message, string stackTrace)
+ private void WriteResult(ExtendedTextWriter writer, string reportID, string status, string fullName, string? message, string? stackTrace)
{
ColorStyle style = GetColorStyle();
@@ -123,7 +125,7 @@ private ColorStyle GetColorStyle()
: ColorStyle.Output;
}
- private static string GetTrimmedInnerText(XmlNode node)
+ private static string? GetTrimmedInnerText(XmlNode? node)
{
// In order to control the format, we trim any line-end chars
// from end of the strings we write and supply them via calls
@@ -141,8 +143,8 @@ public AssertionResult(XmlNode assertion)
StackTrace = GetTrimmedInnerText(assertion.SelectSingleNode("stack-trace"));
}
- public string Message { get; private set; }
- public string StackTrace { get; private set; }
+ public string? Message { get; private set; }
+ public string? StackTrace { get; private set; }
}
}
}
diff --git a/src/NUnitConsole/nunit4-console/ExtendedTextWrapper.cs b/src/NUnitConsole/nunit4-console/ExtendedTextWrapper.cs
index e0ce8af53..08892960a 100644
--- a/src/NUnitConsole/nunit4-console/ExtendedTextWrapper.cs
+++ b/src/NUnitConsole/nunit4-console/ExtendedTextWrapper.cs
@@ -31,7 +31,7 @@ public override void Write(char value)
///
/// Write a string value
///
- public override void Write(string value)
+ public override void Write(string? value)
{
_writer.Write(value);
}
@@ -39,7 +39,7 @@ public override void Write(string value)
///
/// Write a string value followed by a NewLine
///
- public override void WriteLine(string value)
+ public override void WriteLine(string? value)
{
_writer.WriteLine(value);
}
diff --git a/src/NUnitConsole/nunit4-console/FileSystem.cs b/src/NUnitConsole/nunit4-console/FileSystem.cs
index 4636d8701..c1f78f008 100644
--- a/src/NUnitConsole/nunit4-console/FileSystem.cs
+++ b/src/NUnitConsole/nunit4-console/FileSystem.cs
@@ -2,11 +2,10 @@
using System.Collections.Generic;
using System.IO;
+using System;
namespace NUnit.ConsoleRunner
{
- using System;
-
internal class FileSystem : IFileSystem
{
public bool FileExists(string fileName)
@@ -22,7 +21,7 @@ public IEnumerable ReadLines(string fileName)
using (var file = File.OpenText(fileName))
{
- string line;
+ string? line;
while ((line = file.ReadLine()) != null)
{
yield return line;
diff --git a/src/NUnitConsole/nunit4-console/Options/DefaultOptionsProvider.cs b/src/NUnitConsole/nunit4-console/Options/DefaultOptionsProvider.cs
index 33bdd1e16..72fd0c520 100644
--- a/src/NUnitConsole/nunit4-console/Options/DefaultOptionsProvider.cs
+++ b/src/NUnitConsole/nunit4-console/Options/DefaultOptionsProvider.cs
@@ -1,9 +1,9 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
+using System;
+
namespace NUnit.ConsoleRunner.Options
{
- using System;
-
internal sealed class DefaultOptionsProvider : IDefaultOptionsProvider
{
private const string EnvironmentVariableTeamcityProjectName = "TEAMCITY_PROJECT_NAME";
diff --git a/src/NUnitConsole/nunit4-console/Options/OptionParser.cs b/src/NUnitConsole/nunit4-console/Options/OptionParser.cs
index 158c62d46..40f4fb6be 100644
--- a/src/NUnitConsole/nunit4-console/Options/OptionParser.cs
+++ b/src/NUnitConsole/nunit4-console/Options/OptionParser.cs
@@ -95,7 +95,7 @@ private bool IsQuotedString(string value)
return false;
}
- public OutputSpecification ResolveOutputSpecification(string value, IList outputSpecifications, IFileSystem fileSystem, string currentDir)
+ public OutputSpecification? ResolveOutputSpecification(string value, IList outputSpecifications, IFileSystem fileSystem, string currentDir)
{
if (value == null)
return null;
diff --git a/src/NUnitConsole/nunit4-console/Options/Options.cs b/src/NUnitConsole/nunit4-console/Options/Options.cs
index 1d830f1a5..0e8fe974b 100644
--- a/src/NUnitConsole/nunit4-console/Options/Options.cs
+++ b/src/NUnitConsole/nunit4-console/Options/Options.cs
@@ -160,6 +160,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
#if PCL
@@ -170,6 +171,8 @@
#endif
using System.Text;
using System.Text.RegularExpressions;
+using NUnit.Common;
+
#if LINQ
using System.Linq;
@@ -308,14 +311,14 @@ internal OptionValueCollection(OptionContext c)
#endregion
#region IList
- int IList.Add(object value) { return (values as IList).Add(value); }
- bool IList.Contains(object value) { return (values as IList).Contains(value); }
- int IList.IndexOf(object value) { return (values as IList).IndexOf(value); }
- void IList.Insert(int index, object value) { (values as IList).Insert(index, value); }
- void IList.Remove(object value) { (values as IList).Remove(value); }
+ int IList.Add(object? value) { return (values as IList).Add(value); }
+ bool IList.Contains(object? value) { return (values as IList).Contains(value); }
+ int IList.IndexOf(object? value) { return (values as IList).IndexOf(value); }
+ void IList.Insert(int index, object? value) { (values as IList).Insert(index, value); }
+ void IList.Remove(object? value) { (values as IList).Remove(value); }
void IList.RemoveAt(int index) { (values as IList).RemoveAt(index); }
bool IList.IsFixedSize { get { return false; } }
- object IList.this[int index] { get { return this[index]; } set { (values as IList)[index] = value; } }
+ object? IList.this[int index] { get { return this[index]; } set { (values as IList)[index] = value; } }
#endregion
#region IList
@@ -336,12 +339,13 @@ private void AssertValid(int index)
c.OptionName);
}
+ [DisallowNull]
public string this[int index]
{
get
{
AssertValid(index);
- return index >= values.Count ? null : values[index];
+ return index >= values.Count ? string.Empty : values[index];
}
set
{
@@ -368,8 +372,8 @@ public override string ToString()
public class OptionContext
{
- private Option option;
- private string name;
+ private Option? option;
+ private string? name;
private int index;
private readonly OptionSet set;
private readonly OptionValueCollection c;
@@ -380,13 +384,13 @@ public OptionContext(OptionSet set)
this.c = new OptionValueCollection(this);
}
- public Option Option
+ public Option? Option
{
get { return option; }
set { option = value; }
}
- public string OptionName
+ public string? OptionName
{
get { return name; }
set { name = value; }
@@ -419,24 +423,24 @@ public enum OptionValueType
public abstract class Option
{
readonly string prototype;
- readonly string description;
+ readonly string? description;
readonly string[] names;
readonly OptionValueType type;
readonly int count;
- string[] separators;
+ string[]? separators;
readonly bool hidden;
- protected Option(string prototype, string description)
+ protected Option(string prototype, string? description)
: this(prototype, description, 1, false)
{
}
- protected Option(string prototype, string description, int maxValueCount)
+ protected Option(string prototype, string? description, int maxValueCount)
: this(prototype, description, maxValueCount, false)
{
}
- protected Option(string prototype, string description, int maxValueCount, bool hidden)
+ protected Option(string prototype, string? description, int maxValueCount, bool hidden)
{
if (prototype == null)
throw new ArgumentNullException("prototype");
@@ -478,7 +482,7 @@ protected Option(string prototype, string description, int maxValueCount, bool h
}
public string Prototype { get { return prototype; } }
- public string Description { get { return description; } }
+ public string? Description { get { return description; } }
public OptionValueType OptionValueType { get { return type; } }
public int MaxValueCount { get { return count; } }
public bool Hidden { get { return hidden; } }
@@ -491,7 +495,7 @@ public string[] GetNames()
public string[] GetValueSeparators()
{
if (separators == null)
- return new string[0];
+ return Array.Empty();
return (string[])separators.Clone();
}
@@ -513,19 +517,19 @@ protected static T Parse(string value, OptionContext c)
#else
Type targetType = nullable ? tt.GetGenericArguments()[0] : tt;
#endif
- T t = default(T);
+ T t = default(T)!;
try
{
if (value != null)
{
#if PCL
- if (targetType.GetTypeInfo ().IsEnum)
- t = (T) Enum.Parse (targetType, value, true);
- else
- t = (T) Convert.ChangeType (value, targetType);
+ if (targetType.GetTypeInfo ().IsEnum)
+ t = (T) Enum.Parse (targetType, value, true);
+ else
+ t = (T) Convert.ChangeType (value, targetType);
#else
TypeConverter conv = TypeDescriptor.GetConverter(targetType);
- t = (T)conv.ConvertFromString(value);
+ t = (T)conv.ConvertFromString(value)!;
#endif
}
}
@@ -537,11 +541,12 @@ protected static T Parse(string value, OptionContext c)
value, targetType.Name, c.OptionName),
c.OptionName, e);
}
+
return t;
}
internal string[] Names { get { return names; } }
- internal string[] ValueSeparators { get { return separators; } }
+ internal string[]? ValueSeparators { get { return separators; } }
static readonly char[] NameTerminator = new char[] { '=', ':' };
@@ -551,7 +556,7 @@ private OptionValueType ParsePrototype()
List seps = new List();
for (int i = 0; i < names.Length; ++i)
{
- string name = names[i];
+ string? name = names[i];
if (name.Length == 0)
throw new ArgumentException("Empty option names are not supported.", "prototype");
@@ -652,7 +657,7 @@ protected ArgumentSource()
public abstract string[] GetNames();
public abstract string Description { get; }
- public abstract bool GetArguments(string value, out IEnumerable replacement);
+ public abstract bool GetArguments(string value, [NotNullWhen(true)] out IEnumerable? replacement);
#if !PCL || NETSTANDARD1_3
public static IEnumerable GetArgumentsFromFile(string file)
@@ -673,7 +678,7 @@ static IEnumerable GetArguments(TextReader reader, bool close)
{
StringBuilder arg = new StringBuilder();
- string line;
+ string? line;
while ((line = reader.ReadLine()) != null)
{
int t = line.Length;
@@ -735,7 +740,7 @@ public override string Description
get { return "Read response file for more options."; }
}
- public override bool GetArguments(string value, out IEnumerable replacement)
+ public override bool GetArguments(string value, [NotNullWhen(true)] out IEnumerable? replacement)
{
if (string.IsNullOrEmpty(value) || !value.StartsWith("@"))
{
@@ -753,19 +758,19 @@ public override bool GetArguments(string value, out IEnumerable replacem
#endif
public class OptionException : Exception
{
- private string option;
+ private string? option;
public OptionException()
{
}
- public OptionException(string message, string optionName)
+ public OptionException(string message, string? optionName)
: base(message)
{
this.option = optionName;
}
- public OptionException(string message, string optionName, Exception innerException)
+ public OptionException(string message, string? optionName, Exception innerException)
: base(message, innerException)
{
this.option = optionName;
@@ -779,7 +784,7 @@ protected OptionException(SerializationInfo info, StreamingContext context)
}
#endif
- public string OptionName
+ public string? OptionName
{
get { return this.option; }
}
@@ -802,20 +807,20 @@ public OptionSet()
{
}
- public OptionSet(MessageLocalizerConverter localizer)
+ public OptionSet(MessageLocalizerConverter? localizer)
+ : base(StringComparer.Ordinal, dictionaryCreationThreshold: 0)
{
this.roSources = new ReadOnlyCollection(sources);
- this.localizer = localizer;
- if (this.localizer == null)
- {
- this.localizer = delegate (string f) {
+ this.localizer = localizer ??
+ delegate (string f) {
return f;
};
- }
}
MessageLocalizerConverter localizer;
+ private new IDictionary Dictionary => base.Dictionary!;
+
public MessageLocalizerConverter MessageLocalizer
{
get { return localizer; }
@@ -843,7 +848,7 @@ protected override string GetKeyForItem(Option item)
}
[Obsolete("Use KeyedCollection.this[string]")]
- protected Option GetOptionForName(string option)
+ protected Option? GetOptionForName(string option)
{
if (option == null)
throw new ArgumentNullException("option");
@@ -938,12 +943,12 @@ sealed class ActionOption : Option
{
readonly Action action;
- public ActionOption(string prototype, string description, int count, Action action)
+ public ActionOption(string prototype, string? description, int count, Action action)
: this(prototype, description, count, action, false)
{
}
- public ActionOption(string prototype, string description, int count, Action action, bool hidden)
+ public ActionOption(string prototype, string? description, int count, Action action, bool hidden)
: base(prototype, description, count, hidden)
{
if (action == null)
@@ -962,12 +967,12 @@ public OptionSet Add(string prototype, Action action)
return Add(prototype, null, action);
}
- public OptionSet Add(string prototype, string description, Action action)
+ public OptionSet Add(string prototype, string? description, Action action)
{
return Add(prototype, description, action, false);
}
- public OptionSet Add(string prototype, string description, Action action, bool hidden)
+ public OptionSet Add(string prototype, string? description, Action action, bool hidden)
{
if (action == null)
throw new ArgumentNullException("action");
@@ -982,12 +987,12 @@ public OptionSet Add(string prototype, OptionAction action)
return Add(prototype, null, action);
}
- public OptionSet Add(string prototype, string description, OptionAction action)
+ public OptionSet Add(string prototype, string? description, OptionAction action)
{
return Add(prototype, description, action, false);
}
- public OptionSet Add(string prototype, string description, OptionAction action, bool hidden)
+ public OptionSet Add(string prototype, string? description, OptionAction action, bool hidden)
{
if (action == null)
throw new ArgumentNullException("action");
@@ -1001,7 +1006,7 @@ sealed class ActionOption : Option
{
readonly Action action;
- public ActionOption(string prototype, string description, Action action)
+ public ActionOption(string prototype, string? description, Action action)
: base(prototype, description, 1)
{
if (action == null)
@@ -1019,7 +1024,7 @@ sealed class ActionOption : Option
{
readonly OptionAction action;
- public ActionOption(string prototype, string description, OptionAction action)
+ public ActionOption(string prototype, string? description, OptionAction action)
: base(prototype, description, 2)
{
if (action == null)
@@ -1040,7 +1045,7 @@ public OptionSet Add(string prototype, Action action)
return Add(prototype, null, action);
}
- public OptionSet Add(string prototype, string description, Action action)
+ public OptionSet Add(string prototype, string? description, Action action)
{
return Add(new ActionOption(prototype, description, action));
}
@@ -1050,7 +1055,7 @@ public OptionSet Add(string prototype, OptionAction
return Add(prototype, null, action);
}
- public OptionSet Add(string prototype, string description, OptionAction action)
+ public OptionSet Add(string prototype, string? description, OptionAction action)
{
return Add(new ActionOption(prototype, description, action));
}
@@ -1076,7 +1081,7 @@ public List Parse(IEnumerable arguments)
c.OptionIndex = -1;
bool process = true;
List unprocessed = new List();
- Option def = Contains("<>") ? this["<>"] : null;
+ Option? def = Contains("<>") ? this["<>"] : null;
ArgumentEnumerator ae = new ArgumentEnumerator(arguments);
foreach (string argument in ae)
{
@@ -1140,7 +1145,7 @@ bool AddSource(ArgumentEnumerator ae, string argument)
{
foreach (ArgumentSource source in sources)
{
- IEnumerable replacement;
+ IEnumerable? replacement;
if (!source.GetArguments(argument, out replacement))
continue;
ae.Add(replacement);
@@ -1149,7 +1154,7 @@ bool AddSource(ArgumentEnumerator ae, string argument)
return false;
}
- private static bool Unprocessed(ICollection extra, Option def, OptionContext c, string argument)
+ private static bool Unprocessed(ICollection extra, Option? def, OptionContext c, string argument)
{
if (def == null)
{
@@ -1165,7 +1170,7 @@ private static bool Unprocessed(ICollection extra, Option def, OptionCon
private readonly Regex ValueOption = new Regex(
@"^(?--|-|/)(?[^:=]+)((?[:=])(?.*))?$");
- protected bool GetOptionParts(string argument, out string flag, out string name, out string sep, out string value)
+ protected bool GetOptionParts(string argument, [NotNullWhen(true)] out string? flag, [NotNullWhen(true)] out string? name, out string? sep, out string? value)
{
if (argument == null)
throw new ArgumentNullException("argument");
@@ -1194,7 +1199,7 @@ protected virtual bool Parse(string argument, OptionContext c)
return true;
}
- string f, n, s, v;
+ string? f, n, s, v;
if (!GetOptionParts(argument, out f, out n, out s, out v))
return false;
@@ -1227,8 +1232,10 @@ protected virtual bool Parse(string argument, OptionContext c)
return false;
}
- private void ParseValue(string option, OptionContext c)
+ private void ParseValue(string? option, OptionContext c)
{
+ Guard.OperationValid(c.Option != null, "OptionContext.Option != null");
+
if (option != null)
foreach (string o in c.Option.ValueSeparators != null
? option.Split(c.Option.ValueSeparators, c.Option.MaxValueCount - c.OptionValues.Count, StringSplitOptions.None)
@@ -1256,7 +1263,7 @@ private bool ParseBool(string option, string n, OptionContext c)
Contains((rn = n.Substring(0, n.Length - 1))))
{
p = this[rn];
- string v = n[n.Length - 1] == '+' ? option : null;
+ string v = n[n.Length - 1] == '+' ? option : string.Empty;
c.OptionName = option;
c.Option = p;
c.OptionValues.Add(v);
@@ -1328,13 +1335,13 @@ public void WriteOptionDescriptions(TextWriter o)
if (p.Hidden)
continue;
- Category c = p as Category;
+ Category? c = p as Category;
if (c != null)
{
WriteDescription(o, p.Description, "", 80, 80);
continue;
}
- CommandOption co = p as CommandOption;
+ CommandOption? co = p as CommandOption;
if (co != null)
{
WriteCommandDescription(o, co.Command, co.CommandName);
@@ -1385,7 +1392,7 @@ public void WriteOptionDescriptions(TextWriter o)
}
}
- internal void WriteCommandDescription(TextWriter o, Command c, string commandName)
+ internal void WriteCommandDescription(TextWriter o, Command c, string? commandName)
{
var name = new string(' ', 8) + (commandName ?? c.Name);
if (name.Length < OptionWidth - 1)
@@ -1399,7 +1406,7 @@ internal void WriteCommandDescription(TextWriter o, Command c, string commandNam
}
}
- void WriteDescription(TextWriter o, string value, string prefix, int firstWidth, int remWidth)
+ void WriteDescription(TextWriter o, string? value, string prefix, int firstWidth, int remWidth)
{
bool indent = false;
foreach (string line in GetLines(localizer(GetDescription(value)), firstWidth, remWidth))
@@ -1476,7 +1483,7 @@ static void Write(TextWriter o, ref int n, string s)
o.Write(s);
}
- static string GetArgumentName(int index, int maxIndex, string description)
+ static string GetArgumentName(int index, int maxIndex, string? description)
{
var matches = Regex.Matches(description ?? "", @"(?<=(? GetLines(string description, int firstWidth,
public class Command
{
+ private CommandSet? commandSet;
+
public string Name { get; }
- public string Help { get; }
+ public string? Help { get; }
- public OptionSet Options { get; set; }
- public Action> Run { get; set; }
+ public OptionSet? Options { get; set; }
+ public Action>? Run { get; set; }
- public CommandSet CommandSet { get; internal set; }
+ public CommandSet CommandSet { get => commandSet.ShouldNotBeNull(); internal set => commandSet = value; }
- public Command(string name, string help = null)
+ public Command(string name, string? help = null)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException(nameof(name));
@@ -1611,7 +1620,7 @@ class CommandOption : Option
// Prototype starts with '=' because this is an invalid prototype
// (see Option.ParsePrototype(), and thus it'll prevent Category
// instances from being accidentally used as normal options.
- public CommandOption(Command command, string commandName = null, bool hidden = false)
+ public CommandOption(Command command, string? commandName = null, bool hidden = false)
: base("=:Command:= " + (commandName ?? command?.Name), (commandName ?? command?.Name), maxValueCount: 0, hidden: hidden)
{
if (command == null)
@@ -1650,7 +1659,7 @@ class CommandOptionSet : OptionSet
{
readonly CommandSet commands;
- public CommandOptionSet(CommandSet commands, MessageLocalizerConverter localizer)
+ public CommandOptionSet(CommandSet commands, MessageLocalizerConverter? localizer)
: base(localizer)
{
this.commands = commands;
@@ -1700,22 +1709,22 @@ public class CommandSet : KeyedCollection
TextWriter outWriter;
TextWriter errorWriter;
- internal List NestedCommandSets;
+ internal List? NestedCommandSets;
- internal HelpCommand help;
+ internal HelpCommand? help;
internal bool showHelp;
internal OptionSet Options => options;
#if !PCL || NETSTANDARD1_3
- public CommandSet(string suite, MessageLocalizerConverter localizer = null)
+ public CommandSet(string suite, MessageLocalizerConverter? localizer = null)
: this(suite, Console.Out, Console.Error, localizer)
{
}
#endif
- public CommandSet(string suite, TextWriter output, TextWriter error, MessageLocalizerConverter localizer = null)
+ public CommandSet(string suite, TextWriter output, TextWriter error, MessageLocalizerConverter? localizer = null)
{
if (suite == null)
throw new ArgumentNullException(nameof(suite));
@@ -1737,7 +1746,7 @@ public CommandSet(string suite, TextWriter output, TextWriter error, MessageLoca
protected override string GetKeyForItem(Command item)
{
- return item?.Name;
+ return item.Name;
}
public new CommandSet Add(Command value)
@@ -1891,7 +1900,7 @@ bool AlreadyAdded(CommandSet value)
return false;
}
- public IEnumerable GetCompletions(string prefix = null)
+ public IEnumerable GetCompletions(string? prefix = null)
{
string rest;
ExtractToken(ref prefix, out rest);
@@ -1919,7 +1928,7 @@ public IEnumerable GetCompletions(string prefix = null)
}
}
- static void ExtractToken(ref string input, out string rest)
+ static void ExtractToken([NotNull] ref string? input, out string rest)
{
rest = "";
input = input ?? "";
@@ -1995,12 +2004,12 @@ public int Run(IEnumerable arguments)
return command.Invoke(extra);
}
- internal Command GetCommand(List extra)
+ internal Command? GetCommand(List extra)
{
return TryGetLocalCommand(extra) ?? TryGetNestedCommand(extra);
}
- Command TryGetLocalCommand(List extra)
+ Command? TryGetLocalCommand(List extra)
{
var name = extra[0];
if (Contains(name))
@@ -2019,7 +2028,7 @@ Command TryGetLocalCommand(List extra)
return null;
}
- Command TryGetNestedCommand(List extra)
+ Command? TryGetNestedCommand(List extra)
{
if (NestedCommandSets == null)
return null;
@@ -2053,7 +2062,7 @@ public HelpCommand()
public override int Invoke(IEnumerable arguments)
{
- var extra = new List(arguments ?? new string[0]);
+ var extra = new List();
var _ = CommandSet.Options.MessageLocalizer;
if (extra.Count == 0)
{
@@ -2078,7 +2087,8 @@ public override int Invoke(IEnumerable arguments)
}
CommandSet.Options.WriteCommandDescription(CommandSet.Out, c.Value, c.Key);
}
- CommandSet.Options.WriteCommandDescription(CommandSet.Out, CommandSet.help, "help");
+ if (CommandSet.help != null)
+ CommandSet.Options.WriteCommandDescription(CommandSet.Out, CommandSet.help, "help");
return 0;
}
if (command == null)
@@ -2098,15 +2108,17 @@ List> GetCommands()
{
var commands = new List>();
- foreach (var c in CommandSet)
+ var commandSet = CommandSet;
+
+ foreach (var c in commandSet)
{
commands.Add(new KeyValuePair(c.Name, c));
}
- if (CommandSet.NestedCommandSets == null)
+ if (commandSet.NestedCommandSets == null)
return commands;
- foreach (var nc in CommandSet.NestedCommandSets)
+ foreach (var nc in commandSet.NestedCommandSets)
{
AddNestedCommands(commands, "", nc);
}
@@ -2130,8 +2142,10 @@ void AddNestedCommands(List> commands, string oute
internal void WriteUnknownCommand(string unknownCommand)
{
- CommandSet.Error.WriteLine(CommandSet.Options.MessageLocalizer($"{CommandSet.Suite}: Unknown command: {unknownCommand}"));
- CommandSet.Error.WriteLine(CommandSet.Options.MessageLocalizer($"{CommandSet.Suite}: Use `{CommandSet.Suite} help` for usage."));
+ var commandSet = CommandSet;
+
+ commandSet.Error.WriteLine(commandSet.Options.MessageLocalizer($"{commandSet.Suite}: Unknown command: {unknownCommand}"));
+ commandSet.Error.WriteLine(commandSet.Options.MessageLocalizer($"{commandSet.Suite}: Use `{commandSet.Suite} help` for usage."));
}
}
}
diff --git a/src/NUnitConsole/nunit4-console/Options/OutputSpecification.cs b/src/NUnitConsole/nunit4-console/Options/OutputSpecification.cs
index 2390025bc..24f03b8b5 100644
--- a/src/NUnitConsole/nunit4-console/Options/OutputSpecification.cs
+++ b/src/NUnitConsole/nunit4-console/Options/OutputSpecification.cs
@@ -17,7 +17,7 @@ public class OutputSpecification
///
/// The option value string.
/// The folder containing the transform.
- public OutputSpecification(string spec, string transformFolder)
+ public OutputSpecification(string spec, string? transformFolder)
{
if (spec == null)
throw new ArgumentNullException(nameof(spec), "Output spec may not be null");
@@ -78,7 +78,7 @@ public OutputSpecification(string spec, string transformFolder)
///
/// Gets the file name of a transform to be applied
///
- public string Transform { get; private set; }
+ public string? Transform { get; private set; }
public override string ToString()
{
diff --git a/src/NUnitConsole/nunit4-console/Program.cs b/src/NUnitConsole/nunit4-console/Program.cs
index 9119b898f..5b0ed50d4 100644
--- a/src/NUnitConsole/nunit4-console/Program.cs
+++ b/src/NUnitConsole/nunit4-console/Program.cs
@@ -21,7 +21,7 @@ public class Program
{
//static Logger log = InternalTrace.GetLogger(typeof(Runner));
static readonly ConsoleOptions Options = new ConsoleOptions(new DefaultOptionsProvider(), new FileSystem());
- private static ExtendedTextWriter _outWriter;
+ private static ExtendedTextWriter? _outWriter;
// This has to be lazy otherwise NoColor command line option is not applied correctly
private static ExtendedTextWriter OutWriter
@@ -174,7 +174,7 @@ public static int Main(string[] args)
private static void WriteHeader()
{
- Assembly entryAssembly = Assembly.GetEntryAssembly();
+ Assembly entryAssembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
var versionBlock = FileVersionInfo.GetVersionInfo(entryAssembly.ManifestModule.FullyQualifiedName);
var header = $"{versionBlock.ProductName} {versionBlock.ProductVersion}";
@@ -188,7 +188,7 @@ private static void WriteHeader()
}
OutWriter.WriteLine(ColorStyle.Header, header);
- OutWriter.WriteLine(ColorStyle.SubHeader, versionBlock.LegalCopyright);
+ OutWriter.WriteLine(ColorStyle.SubHeader, versionBlock.LegalCopyright ?? "No Copyright statement found");
OutWriter.WriteLine(ColorStyle.SubHeader, DateTime.Now.ToString(CultureInfo.CurrentCulture.DateTimeFormat.FullDateTimePattern));
OutWriter.WriteLine();
}
@@ -271,7 +271,7 @@ private static void WriteErrorMessage(string msg)
OutWriter.WriteLine(ColorStyle.Error, msg);
}
- private static void CancelHandler(object sender, ConsoleCancelEventArgs args)
+ private static void CancelHandler(object? sender, ConsoleCancelEventArgs args)
{
Console.ResetColor();
}
diff --git a/src/NUnitConsole/nunit4-console/ResultReporter.cs b/src/NUnitConsole/nunit4-console/ResultReporter.cs
index 2e7dfcf85..35893f5a2 100644
--- a/src/NUnitConsole/nunit4-console/ResultReporter.cs
+++ b/src/NUnitConsole/nunit4-console/ResultReporter.cs
@@ -5,11 +5,10 @@
using System.Globalization;
using System.Xml;
using NUnit.ConsoleRunner.Options;
+using NUnit.ConsoleRunner.Utilities;
namespace NUnit.ConsoleRunner
{
- using Utilities;
-
public class ResultReporter
{
public ResultReporter(XmlNode resultNode, ExtendedTextWriter writer, ConsoleOptions options)
@@ -18,12 +17,13 @@ public ResultReporter(XmlNode resultNode, ExtendedTextWriter writer, ConsoleOpti
Writer = writer;
Options = options;
- OverallResult = resultNode.GetAttribute("result");
- if (OverallResult == "Skipped")
+ string? overallResult = resultNode.GetAttribute("result");
+ if (overallResult == "Skipped")
OverallResult = "Warning";
- if (OverallResult == null)
+ if (overallResult == null)
OverallResult = "Unknown";
-
+ else
+ OverallResult = overallResult;
Summary = new ResultSummary(resultNode);
}
@@ -60,7 +60,7 @@ internal void WriteRunSettingsReport()
{
var settings = firstSuite.SelectNodes("settings/setting");
- if (settings.Count > 0)
+ if (settings is not null && settings.Count > 0)
{
Writer.WriteLine(ColorStyle.SectionHeader, "Run Settings");
@@ -78,13 +78,18 @@ private void WriteSettingsNode(XmlNode node)
var name = node.GetAttribute("name");
var val = node.GetAttribute("value") ?? string.Empty;
- Writer.WriteLabelLine($" {name}:", items.Count > 0 ? string.Empty : $" |{val}|");
-
- foreach (XmlNode item in items)
+ if (items is null || items.Count == 0)
+ Writer.WriteLabelLine($" {name}:", $" |{val}|");
+ else
{
- var key = item.GetAttribute("key");
- var value = item.GetAttribute("value");
- Writer.WriteLine(ColorStyle.Value, $" {key} -> |{value}|");
+ Writer.WriteLabelLine($" {name}:", string.Empty);
+
+ foreach (XmlNode item in items)
+ {
+ var key = item.GetAttribute("key");
+ var value = item.GetAttribute("value");
+ Writer.WriteLine(ColorStyle.Value, $" {key} -> |{value}|");
+ }
}
}
@@ -154,7 +159,7 @@ public void WriteErrorsFailuresAndWarningsReport()
private void WriteErrorsFailuresAndWarnings(XmlNode resultNode)
{
- string resultState = resultNode.GetAttribute("result");
+ string? resultState = resultNode.GetAttribute("result");
switch (resultNode.Name)
{
@@ -225,7 +230,7 @@ private void WriteNotRunResults(XmlNode resultNode)
switch (resultNode.Name)
{
case "test-case":
- string status = resultNode.GetAttribute("result");
+ string? status = resultNode.GetAttribute("result");
if (status == "Skipped")
new ConsoleTestResult(resultNode, ++ReportIndex).WriteResult(Writer);
diff --git a/src/NUnitConsole/nunit4-console/ResultSummary.cs b/src/NUnitConsole/nunit4-console/ResultSummary.cs
index b2f408ace..73c68ab09 100644
--- a/src/NUnitConsole/nunit4-console/ResultSummary.cs
+++ b/src/NUnitConsole/nunit4-console/ResultSummary.cs
@@ -3,11 +3,10 @@
using System;
using System.Globalization;
using System.Xml;
+using NUnit.ConsoleRunner.Utilities;
namespace NUnit.ConsoleRunner
{
- using Utilities;
-
///
/// Summary description for ResultSummary.
///
@@ -138,10 +137,10 @@ private void InitializeCounters()
private void Summarize(XmlNode node, bool failedInFixtureTearDown)
{
- string type = node.GetAttribute("type");
- string status = node.GetAttribute("result");
- string label = node.GetAttribute("label");
- string site = node.GetAttribute("site");
+ string? type = node.GetAttribute("type");
+ string? status = node.GetAttribute("result");
+ string? label = node.GetAttribute("label");
+ string? site = node.GetAttribute("site");
switch (node.Name)
{
diff --git a/src/NUnitConsole/nunit4-console/SafeAttributeAccess.cs b/src/NUnitConsole/nunit4-console/SafeAttributeAccess.cs
index 35c0ef6b3..6566ef87d 100644
--- a/src/NUnitConsole/nunit4-console/SafeAttributeAccess.cs
+++ b/src/NUnitConsole/nunit4-console/SafeAttributeAccess.cs
@@ -23,9 +23,9 @@ public static class SafeAttributeAccess
/// The result.
/// The name.
///
- public static string GetAttribute(this XmlNode result, string name)
+ public static string? GetAttribute(this XmlNode result, string name)
{
- XmlAttribute attr = result.Attributes[name];
+ XmlAttribute? attr = result.Attributes?[name];
return attr == null ? null : attr.Value;
}
@@ -39,7 +39,7 @@ public static string GetAttribute(this XmlNode result, string name)
///
public static double GetAttribute(this XmlNode result, string name, double defaultValue)
{
- XmlAttribute attr = result.Attributes[name];
+ XmlAttribute? attr = result.Attributes?[name];
return attr == null
? defaultValue
@@ -55,7 +55,7 @@ public static double GetAttribute(this XmlNode result, string name, double defau
///
public static DateTime GetAttribute(this XmlNode result, string name, DateTime defaultValue)
{
- string dateStr = GetAttribute(result, name);
+ string? dateStr = GetAttribute(result, name);
if (dateStr == null)
return defaultValue;
diff --git a/src/NUnitConsole/nunit4-console/TestEventHandler.cs b/src/NUnitConsole/nunit4-console/TestEventHandler.cs
index 23013310f..871f5e260 100644
--- a/src/NUnitConsole/nunit4-console/TestEventHandler.cs
+++ b/src/NUnitConsole/nunit4-console/TestEventHandler.cs
@@ -22,7 +22,7 @@ public class TestEventHandler : ITestEventListener
private readonly bool _displayAfterTest;
private readonly bool _displayBeforeOutput;
- private string _lastTestOutput;
+ private string? _lastTestOutput;
private bool _wantNewLine = false;
public TestEventHandler(ExtendedTextWriter outWriter, string labelsOption)
@@ -41,6 +41,9 @@ public void OnTestEvent(string report)
doc.LoadXml(report);
var testEvent = doc.FirstChild;
+ if (testEvent == null)
+ return;
+
switch (testEvent.Name)
{
case "start-test":
@@ -63,16 +66,20 @@ public void OnTestEvent(string report)
private void TestStarted(XmlNode testResult)
{
- var testName = testResult.Attributes["fullname"].Value;
+ var testName = testResult.Attributes?["fullname"]?.Value;
- if (_displayBeforeTest)
+ if (_displayBeforeTest && testName != null)
WriteLabelLine(testName);
}
private void TestFinished(XmlNode testResult)
{
- var testName = testResult.Attributes["fullname"].Value;
- var status = testResult.GetAttribute("label") ?? testResult.GetAttribute("result");
+ var testName = testResult.Attributes?["fullname"]?.Value;
+
+ if (testName == null)
+ return;
+
+ var status = testResult.GetAttribute("label") ?? testResult.GetAttribute("result") ?? "Unknown";
var outputNode = testResult.SelectSingleNode("output");
if (outputNode != null)
@@ -90,10 +97,10 @@ private void TestFinished(XmlNode testResult)
private void SuiteFinished(XmlNode testResult)
{
- var suiteName = testResult.Attributes["fullname"].Value;
+ var suiteName = testResult.Attributes?["fullname"]?.Value;
var outputNode = testResult.SelectSingleNode("output");
- if (outputNode != null)
+ if (suiteName != null && outputNode != null)
{
if (_displayBeforeOutput)
WriteLabelLine(suiteName);
@@ -106,15 +113,18 @@ private void SuiteFinished(XmlNode testResult)
private void TestOutput(XmlNode outputNode)
{
var testName = outputNode.GetAttribute("testname");
- var stream = outputNode.GetAttribute("stream");
- if (_displayBeforeOutput && testName != null)
- WriteLabelLine(testName);
+ if (testName != null)
+ {
+ if (_displayBeforeOutput)
+ WriteLabelLine(testName);
- WriteOutputLine(testName, outputNode.InnerText, stream == "Error" ? ColorStyle.Error : ColorStyle.Output);
+ var stream = outputNode.GetAttribute("stream");
+ WriteOutputLine(testName, outputNode.InnerText, stream == "Error" ? ColorStyle.Error : ColorStyle.Output);
+ }
}
- private string _currentLabel;
+ private string? _currentLabel;
private void WriteLabelLine(string label)
{
@@ -198,7 +208,7 @@ private static ColorStyle GetColorForResultStatus(string status)
#if NETFRAMEWORK
public override object InitializeLifetimeService()
{
- return null;
+ return null!;
}
#endif
}
diff --git a/src/NUnitConsole/nunit4-console/nunit4-console.csproj b/src/NUnitConsole/nunit4-console/nunit4-console.csproj
index e49338b0c..f965a98ec 100644
--- a/src/NUnitConsole/nunit4-console/nunit4-console.csproj
+++ b/src/NUnitConsole/nunit4-console/nunit4-console.csproj
@@ -16,6 +16,8 @@
The standard command-line runner for NUnit
+
+
..\..\..\nunit.ico
app.manifest
@@ -23,6 +25,8 @@
+
+
diff --git a/src/NUnitConsole/nunit4-netcore-console/ColorConsoleWriter.cs b/src/NUnitConsole/nunit4-netcore-console/ColorConsoleWriter.cs
index 08853b4b9..69d77653e 100644
--- a/src/NUnitConsole/nunit4-netcore-console/ColorConsoleWriter.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/ColorConsoleWriter.cs
@@ -89,7 +89,7 @@ public override void WriteLabel(string label, object option, ColorStyle valueSty
Guard.ArgumentNotNull(option, nameof(option));
Write(ColorStyle.Label, label);
- Write(valueStyle, option.ToString());
+ Write(valueStyle, option.ToString() ?? string.Empty);
}
///
diff --git a/src/NUnitConsole/nunit4-netcore-console/ConsoleOptions.cs b/src/NUnitConsole/nunit4-netcore-console/ConsoleOptions.cs
index ed746ed43..66d60717d 100644
--- a/src/NUnitConsole/nunit4-netcore-console/ConsoleOptions.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/ConsoleOptions.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
@@ -52,7 +53,9 @@ internal ConsoleOptions(IDefaultOptionsProvider defaultOptionsProvider, IFileSys
public IDictionary TestParameters { get; } = new Dictionary();
- public string WhereClause { get; private set; }
+ public string? WhereClause { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(WhereClause))]
public bool WhereClauseSpecified { get { return WhereClause != null; } }
public int DefaultTestCaseTimeout { get; private set; } = -1;
@@ -61,7 +64,7 @@ internal ConsoleOptions(IDefaultOptionsProvider defaultOptionsProvider, IFileSys
public int RandomSeed { get; private set; } = -1;
public bool RandomSeedSpecified { get { return RandomSeed >= 0; } }
- public string DefaultTestNamePattern { get; private set; }
+ public string? DefaultTestNamePattern { get; private set; }
public int NumberOfTestWorkers { get; private set; } = -1;
public bool NumberOfTestWorkersSpecified { get { return NumberOfTestWorkers >= 0; } }
@@ -71,7 +74,7 @@ internal ConsoleOptions(IDefaultOptionsProvider defaultOptionsProvider, IFileSys
// Output Control
- public string ConsoleEncoding { get; private set; }
+ public string? ConsoleEncoding { get; private set; }
public bool NoHeader { get; private set; }
@@ -79,19 +82,23 @@ internal ConsoleOptions(IDefaultOptionsProvider defaultOptionsProvider, IFileSys
public bool TeamCity { get; private set; }
- public string OutFile { get; private set; }
+ public string? OutFile { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(OutFile))]
public bool OutFileSpecified { get { return OutFile != null; } }
- public string DisplayTestLabels { get; private set; }
+ public string? DisplayTestLabels { get; private set; }
- private string workDirectory = null;
+ private string? workDirectory = null;
public string WorkDirectory
{
get { return workDirectory ?? CURRENT_DIRECTORY_ON_ENTRY; }
}
public bool WorkDirectorySpecified { get { return workDirectory != null; } }
- public string InternalTraceLevel { get; private set; }
+ public string? InternalTraceLevel { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(InternalTraceLevel))]
public bool InternalTraceLevelSpecified { get { return InternalTraceLevel != null; } }
private readonly List resultOutputSpecifications = new List();
@@ -114,15 +121,19 @@ public IList ResultOutputSpecifications
public IList ExploreOutputSpecifications { get; } = new List();
- public string ActiveConfig { get; private set; }
+ public string? ActiveConfig { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(ActiveConfig))]
public bool ActiveConfigSpecified { get { return ActiveConfig != null; } }
// How to Run Tests
- public string RuntimeFramework { get; private set; }
+ public string? RuntimeFramework { get; private set; }
+
+ [MemberNotNullWhen(true, nameof(RuntimeFramework))]
public bool RuntimeFrameworkSpecified { get { return RuntimeFramework != null; } }
- public string ConfigurationFile { get; private set; }
+ public string? ConfigurationFile { get; private set; }
public bool RunAsX86 { get; private set; }
@@ -146,7 +157,7 @@ public IList ResultOutputSpecifications
public bool PauseBeforeRun { get; private set; }
- public string PrincipalPolicy { get; private set; }
+ public string? PrincipalPolicy { get; private set; }
public IList WarningMessages { get; } = new List();
@@ -179,7 +190,7 @@ private void ConfigureOptions()
{
while (!rdr.EndOfStream)
{
- var line = rdr.ReadLine().Trim();
+ var line = rdr.ReadLine()?.Trim();
if (!string.IsNullOrEmpty(line) && line[0] != '#')
((List)TestList).Add(line);
@@ -216,10 +227,10 @@ private void ConfigureOptions()
v => NumberOfTestWorkers = parser.RequiredInt(v, "--workers"));
this.Add("stoponerror", "Stop run immediately upon any test failure or error.",
- v => StopOnError = v != null);
+ v => StopOnError = !string.IsNullOrEmpty(v));
this.Add("wait", "Wait for input before closing console window.",
- v => WaitBeforeExit = v != null);
+ v => WaitBeforeExit = !string.IsNullOrEmpty(v));
// Output Control
this.Add("work=", "{PATH} of the directory to use for output files. If not specified, defaults to the current directory.",
@@ -243,7 +254,7 @@ private void ConfigureOptions()
});
this.Add("noresult", "Don't save any test results.",
- v => NoResultSpecified = v != null);
+ v => NoResultSpecified = !string.IsNullOrEmpty(v));
this.Add("labels=", "Specify whether to write test case names to the output. Values: Off (Default), On, OnOutput, Before, After, BeforeAndAfter. On is currently an alias for OnOutput, but is subject to change.",
v => {
@@ -257,19 +268,19 @@ private void ConfigureOptions()
v => InternalTraceLevel = parser.RequiredValue(v, "--trace", "Off", "Error", "Warning", "Info", "Verbose", "Debug"));
this.Add("teamcity", "Turns on use of TeamCity service messages. TeamCity engine extension is required.",
- v => TeamCity = v != null);
+ v => TeamCity = !string.IsNullOrEmpty(v));
this.Add("noheader|noh", "Suppress display of program information at start of run.",
- v => NoHeader = v != null);
+ v => NoHeader = !string.IsNullOrEmpty(v));
this.Add("nocolor|noc", "Displays console output without color.",
- v => NoColor = v != null);
+ v => NoColor = !string.IsNullOrEmpty(v));
this.Add("help|h", "Display this message and exit.",
- v => ShowHelp = v != null);
+ v => ShowHelp = !string.IsNullOrEmpty(v));
this.Add("version|V", "Display the header and exit.",
- v => ShowVersion = v != null);
+ v => ShowVersion = !string.IsNullOrEmpty(v));
this.Add("encoding=", "Specifies the encoding to use for Console standard output, for example utf-8, ascii, unicode.",
v => ConsoleEncoding = parser.RequiredValue(v, "--encoding"));
@@ -294,38 +305,38 @@ private void ConfigureOptions()
NetFxOnlyOption("framework=", v => RuntimeFramework = parser.RequiredValue(v, "--framework")));
this.AddNetFxOnlyOption("x86", "Run tests in an x86 process on 64 bit systems",
- NetFxOnlyOption("x86", v => RunAsX86 = v != null));
+ NetFxOnlyOption("x86", v => RunAsX86 = !string.IsNullOrEmpty(v)));
this.Add("dispose-runners", "Dispose each test runner after it has finished running its tests.",
- v => DisposeRunners = v != null);
+ v => DisposeRunners = !string.IsNullOrEmpty(v));
this.AddNetFxOnlyOption("shadowcopy", "Shadow copy test files",
- NetFxOnlyOption("shadowcopy", v => ShadowCopyFiles = v != null));
+ NetFxOnlyOption("shadowcopy", v => ShadowCopyFiles = !string.IsNullOrEmpty(v)));
this.AddNetFxOnlyOption("loaduserprofile", "Load user profile in test runner processes",
- NetFxOnlyOption("loaduserprofile", v => LoadUserProfile = v != null));
+ NetFxOnlyOption("loaduserprofile", v => LoadUserProfile = !string.IsNullOrEmpty(v)));
this.Add("skipnontestassemblies", "Skip any non-test assemblies specified, without error.",
- v => SkipNonTestAssemblies = v != null);
+ v => SkipNonTestAssemblies = !string.IsNullOrEmpty(v));
this.AddNetFxOnlyOption("agents=", "Specify the maximum {NUMBER} of test assembly agents to run at one time. If not specified, there is no limit.",
NetFxOnlyOption("agents=", v => _maxAgents = parser.RequiredInt(v, "--agents")));
this.AddNetFxOnlyOption("debug", "Launch debugger to debug tests.",
- NetFxOnlyOption("debug", v => DebugTests = v != null));
+ NetFxOnlyOption("debug", v => DebugTests = !string.IsNullOrEmpty(v)));
this.AddNetFxOnlyOption("pause", "Pause before running to allow attaching a debugger.",
- NetFxOnlyOption("pause", v => PauseBeforeRun = v != null));
+ NetFxOnlyOption("pause", v => PauseBeforeRun = !string.IsNullOrEmpty(v)));
this.Add("list-extensions", "List all extension points and the extensions for each.",
- v => ListExtensions = v != null);
+ v => ListExtensions = !string.IsNullOrEmpty(v));
this.AddNetFxOnlyOption("set-principal-policy=", "Set PrincipalPolicy for the test domain.",
NetFxOnlyOption("set-principal-policy=", v => PrincipalPolicy = parser.RequiredValue(v, "--set-principal-policy", "UnauthenticatedPrincipal", "NoPrincipal", "WindowsPrincipal")));
#if DEBUG
this.AddNetFxOnlyOption("debug-agent", "Launch debugger in nunit-agent when it starts.",
- NetFxOnlyOption("debug-agent", v => DebugAgent = v != null));
+ NetFxOnlyOption("debug-agent", v => DebugAgent = !string.IsNullOrEmpty(v)));
#endif
}
@@ -431,7 +442,7 @@ private IEnumerable GetArgsFromFile(string filename)
return GetArgs(sb.ToString());
}
- private string ExpandToFullPath(string path)
+ private string? ExpandToFullPath(string path)
{
if (path == null) return null;
diff --git a/src/NUnitConsole/nunit4-netcore-console/ConsoleRunner.cs b/src/NUnitConsole/nunit4-netcore-console/ConsoleRunner.cs
index 7bdc21d99..581f87692 100644
--- a/src/NUnitConsole/nunit4-netcore-console/ConsoleRunner.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/ConsoleRunner.cs
@@ -142,7 +142,7 @@ private int ExploreTests(TestPackage package, TestFilter filter)
{
foreach (OutputSpecification spec in _options.ExploreOutputSpecifications)
{
- _resultService.GetResultWriter(spec.Format, new object[] {spec.Transform}).WriteResultFile(result, spec.OutputPath);
+ _resultService.GetResultWriter(spec.Format, spec.Transform).WriteResultFile(result, spec.OutputPath);
_outWriter.WriteLine("Results ({0}) saved as {1}", spec.Format, spec.OutputPath);
}
}
@@ -172,7 +172,7 @@ private int RunTests(TestPackage package, TestFilter filter)
try
{
- var outputDirectory = Path.GetDirectoryName(outputPath);
+ var outputDirectory = Path.GetDirectoryName(outputPath)!;
Directory.CreateDirectory(outputDirectory);
}
catch (Exception ex)
@@ -202,9 +202,9 @@ private int RunTests(TestPackage package, TestFilter filter)
? _options.DisplayTestLabels.ToUpperInvariant()
: "ON";
- XmlNode result = null;
- NUnitEngineUnloadException unloadException = null;
- NUnitEngineException engineException = null;
+ XmlNode? result = null;
+ NUnitEngineUnloadException? unloadException = null;
+ NUnitEngineException? engineException = null;
try
{
@@ -380,7 +380,7 @@ private ExtendedTextWriter CreateOutputWriter()
private IResultWriter GetResultWriter(OutputSpecification spec)
{
- return _resultService.GetResultWriter(spec.Format, new object[] {spec.Transform});
+ return _resultService.GetResultWriter(spec.Format, spec.Transform);
}
// This is public static for ease of testing
diff --git a/src/NUnitConsole/nunit4-netcore-console/ConsoleTestResult.cs b/src/NUnitConsole/nunit4-netcore-console/ConsoleTestResult.cs
index 971bc3fa0..19265bd28 100644
--- a/src/NUnitConsole/nunit4-netcore-console/ConsoleTestResult.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/ConsoleTestResult.cs
@@ -31,23 +31,23 @@ public ConsoleTestResult(XmlNode resultNode, int reportIndex)
Label = resultNode.GetAttribute("label");
Site = resultNode.GetAttribute("site");
- Status = Label ?? Result;
+ Status = Label ?? Result ?? "Unkown";
if (Status == "Failed" || Status == "Error")
if (Site == "SetUp" || Site == "TearDown")
Status = Site + " " + Status;
- FullName = resultNode.GetAttribute("fullname");
+ FullName = resultNode.GetAttribute("fullname") ?? "Unknown";
}
- public string Result { get; private set; }
- public string Label { get; private set; }
- public string Site { get; private set; }
+ public string? Result { get; private set; }
+ public string? Label { get; private set; }
+ public string? Site { get; private set; }
public string FullName { get; private set; }
public string ReportID { get; private set; }
public string Status { get; private set; }
- public string Message
+ public string? Message
{
get
{
@@ -56,12 +56,12 @@ public string Message
}
}
- public string StackTrace
+ public string? StackTrace
{
get { return GetTrimmedInnerText(_resultNode.SelectSingleNode("failure/stack-trace")); }
}
- private List _assertions;
+ private List? _assertions;
public List Assertions
{
get
@@ -69,8 +69,10 @@ public List Assertions
if (_assertions == null)
{
_assertions = new List();
- foreach (XmlNode assertion in _resultNode.SelectNodes("assertions/assertion"))
- Assertions.Add(new ConsoleTestResult.AssertionResult(assertion));
+ XmlNodeList? assertions = _resultNode.SelectNodes("assertions/assertion");
+ if (assertions is not null)
+ foreach (XmlNode assertion in assertions)
+ Assertions.Add(new ConsoleTestResult.AssertionResult(assertion));
}
return _assertions;
@@ -98,7 +100,7 @@ public void WriteResult(ExtendedTextWriter writer)
WriteResult(writer, ReportID, Status, FullName, Message, StackTrace);
}
- private void WriteResult(ExtendedTextWriter writer, string reportID, string status, string fullName, string message, string stackTrace)
+ private void WriteResult(ExtendedTextWriter writer, string reportID, string status, string fullName, string? message, string? stackTrace)
{
ColorStyle style = GetColorStyle();
@@ -123,7 +125,7 @@ private ColorStyle GetColorStyle()
: ColorStyle.Output;
}
- private static string GetTrimmedInnerText(XmlNode node)
+ private static string? GetTrimmedInnerText(XmlNode? node)
{
// In order to control the format, we trim any line-end chars
// from end of the strings we write and supply them via calls
@@ -141,8 +143,8 @@ public AssertionResult(XmlNode assertion)
StackTrace = GetTrimmedInnerText(assertion.SelectSingleNode("stack-trace"));
}
- public string Message { get; private set; }
- public string StackTrace { get; private set; }
+ public string? Message { get; private set; }
+ public string? StackTrace { get; private set; }
}
}
}
diff --git a/src/NUnitConsole/nunit4-netcore-console/EnginePackageSettings.cs b/src/NUnitConsole/nunit4-netcore-console/EnginePackageSettings.cs
deleted file mode 100644
index 96db5c685..000000000
--- a/src/NUnitConsole/nunit4-netcore-console/EnginePackageSettings.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
-
-#if false
-using System;
-
-namespace NUnit
-{
- ///
- /// EngineSettings contains constant values that
- /// are used as keys in setting up a TestPackage.
- /// Values here are used in the engine, and set by the runner.
- /// Setting values may be a string, int or bool.
- ///
- public static class EnginePackageSettings
- {
- ///
- /// The name of the config to use in loading a project.
- /// If not specified, the first config found is used.
- ///
- public const string ActiveConfig = "ActiveConfig";
-
- ///
- /// Bool indicating whether the engine should determine the private
- /// bin path by examining the paths to all the tests. Defaults to
- /// true unless PrivateBinPath is specified.
- ///
- public const string AutoBinPath = "AutoBinPath";
-
- ///
- /// The ApplicationBase to use in loading the tests. If not
- /// specified, and each assembly has its own process, then the
- /// location of the assembly is used. For multiple assemblies
- /// in a single process, the closest common root directory is used.
- ///
- public const string BasePath = "BasePath";
-
- ///
- /// Path to the config file to use in running the tests.
- ///
- public const string ConfigurationFile = "ConfigurationFile";
-
- ///
- /// Flag (bool) indicating whether tests are being debugged.
- ///
- public const string DebugTests = "DebugTests";
-
- ///
- /// Bool flag indicating whether a debugger should be launched at agent
- /// startup. Used only for debugging NUnit itself.
- ///
- public const string DebugAgent = "DebugAgent";
-
- ///
- /// The private binpath used to locate assemblies. Directory paths
- /// is separated by a semicolon. It's an error to specify this and
- /// also set AutoBinPath to true.
- ///
- public const string PrivateBinPath = "PrivateBinPath";
-
- ///
- /// The maximum number of test agents permitted to run simultaneously.
- /// Ignored if the ProcessModel is not set or defaulted to Multiple.
- ///
- public const string MaxAgents = "MaxAgents";
-
- ///
- /// Indicates how to allocate assemblies to processes. Values are:
- /// "Default", "Single", "Separate", "Multiple". Default is "Multiple"
- /// for more than one assembly, "Separate" for a single assembly.
- ///
- public const string ProcessModel = "ProcessModel";
-
- ///
- /// Indicates the desired runtime to use for the tests. Values
- /// are strings like "net-4.5", "mono-4.0", etc. Default is to
- /// use the target framework for which an assembly was built.
- ///
- [Obsolete("Use 'RequestedRuntimeFramework' instead.")]
- public const string RuntimeFramework = "RequestedRuntimeFramework";
-
- ///
- /// Indicates the desired runtime to use for the tests. Values
- /// are strings like "net-4.5", "mono-4.0", etc. Default is to
- /// use the target framework for which an assembly was built.
- ///
- public const string RequestedRuntimeFramework = "RequestedRuntimeFramework";
-
- ///
- /// Indicates the Target runtime selected for use by the engine,
- /// based on the requested runtime and assembly metadata.
- ///
- public const string TargetRuntimeFramework = "TargetRuntimeFramework";
-
- ///
- /// Bool flag indicating that the test should be run in a 32-bit process
- /// on a 64-bit system. By default, NUNit runs in a 64-bit process on
- /// a 64-bit system. Ignored if set on a 32-bit system.
- ///
- public const string RunAsX86 = "RunAsX86";
-
- ///
- /// Indicates that test runners should be disposed after the tests are executed
- ///
- public const string DisposeRunners = "DisposeRunners";
-
- ///
- /// Bool flag indicating that the test assemblies should be shadow copied.
- /// Defaults to false.
- ///
- public const string ShadowCopyFiles = "ShadowCopyFiles";
-
- ///
- /// Bool flag indicating that user profile should be loaded on test runner processes
- ///
- public const string LoadUserProfile = "LoadUserProfile";
-
- ///
- /// Bool flag indicating that non-test assemblies should be skipped without error.
- ///
- public const string SkipNonTestAssemblies = "SkipNonTestAssemblies";
-
- ///
- /// Flag (bool) indicating whether to pause execution of tests to allow
- /// the user to attach a debugger.
- ///
- public const string PauseBeforeRun = "PauseBeforeRun";
-
- ///
- /// The InternalTraceLevel for this run. Values are: "Default",
- /// "Off", "Error", "Warning", "Info", "Debug", "Verbose".
- /// Default is "Off". "Debug" and "Verbose" are synonyms.
- ///
- public const string InternalTraceLevel = "InternalTraceLevel";
-
- ///
- /// The PrincipalPolicy to set on the test application domain. Values are:
- /// "UnauthenticatedPrincipal", "NoPrincipal" and "WindowsPrincipal".
- ///
- public const string PrincipalPolicy = "PrincipalPolicy";
- }
-}
-#endif
diff --git a/src/NUnitConsole/nunit4-netcore-console/ExtendedTextWrapper.cs b/src/NUnitConsole/nunit4-netcore-console/ExtendedTextWrapper.cs
index e0ce8af53..08892960a 100644
--- a/src/NUnitConsole/nunit4-netcore-console/ExtendedTextWrapper.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/ExtendedTextWrapper.cs
@@ -31,7 +31,7 @@ public override void Write(char value)
///
/// Write a string value
///
- public override void Write(string value)
+ public override void Write(string? value)
{
_writer.Write(value);
}
@@ -39,7 +39,7 @@ public override void Write(string value)
///
/// Write a string value followed by a NewLine
///
- public override void WriteLine(string value)
+ public override void WriteLine(string? value)
{
_writer.WriteLine(value);
}
diff --git a/src/NUnitConsole/nunit4-netcore-console/FileSystem.cs b/src/NUnitConsole/nunit4-netcore-console/FileSystem.cs
index 4636d8701..c1f78f008 100644
--- a/src/NUnitConsole/nunit4-netcore-console/FileSystem.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/FileSystem.cs
@@ -2,11 +2,10 @@
using System.Collections.Generic;
using System.IO;
+using System;
namespace NUnit.ConsoleRunner
{
- using System;
-
internal class FileSystem : IFileSystem
{
public bool FileExists(string fileName)
@@ -22,7 +21,7 @@ public IEnumerable ReadLines(string fileName)
using (var file = File.OpenText(fileName))
{
- string line;
+ string? line;
while ((line = file.ReadLine()) != null)
{
yield return line;
diff --git a/src/NUnitConsole/nunit4-netcore-console/Options/DefaultOptionsProvider.cs b/src/NUnitConsole/nunit4-netcore-console/Options/DefaultOptionsProvider.cs
index 33bdd1e16..72fd0c520 100644
--- a/src/NUnitConsole/nunit4-netcore-console/Options/DefaultOptionsProvider.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/Options/DefaultOptionsProvider.cs
@@ -1,9 +1,9 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
+using System;
+
namespace NUnit.ConsoleRunner.Options
{
- using System;
-
internal sealed class DefaultOptionsProvider : IDefaultOptionsProvider
{
private const string EnvironmentVariableTeamcityProjectName = "TEAMCITY_PROJECT_NAME";
diff --git a/src/NUnitConsole/nunit4-netcore-console/Options/OptionParser.cs b/src/NUnitConsole/nunit4-netcore-console/Options/OptionParser.cs
index 158c62d46..40f4fb6be 100644
--- a/src/NUnitConsole/nunit4-netcore-console/Options/OptionParser.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/Options/OptionParser.cs
@@ -95,7 +95,7 @@ private bool IsQuotedString(string value)
return false;
}
- public OutputSpecification ResolveOutputSpecification(string value, IList outputSpecifications, IFileSystem fileSystem, string currentDir)
+ public OutputSpecification? ResolveOutputSpecification(string value, IList outputSpecifications, IFileSystem fileSystem, string currentDir)
{
if (value == null)
return null;
diff --git a/src/NUnitConsole/nunit4-netcore-console/Options/Options.cs b/src/NUnitConsole/nunit4-netcore-console/Options/Options.cs
index 56d4b19f1..7cb932a4c 100644
--- a/src/NUnitConsole/nunit4-netcore-console/Options/Options.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/Options/Options.cs
@@ -160,6 +160,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
#if PCL
@@ -170,6 +171,8 @@
#endif
using System.Text;
using System.Text.RegularExpressions;
+using NUnit.Common;
+
#if LINQ
using System.Linq;
@@ -308,14 +311,14 @@ internal OptionValueCollection(OptionContext c)
#endregion
#region IList
- int IList.Add(object value) { return (values as IList).Add(value); }
- bool IList.Contains(object value) { return (values as IList).Contains(value); }
- int IList.IndexOf(object value) { return (values as IList).IndexOf(value); }
- void IList.Insert(int index, object value) { (values as IList).Insert(index, value); }
- void IList.Remove(object value) { (values as IList).Remove(value); }
+ int IList.Add(object? value) { return (values as IList).Add(value); }
+ bool IList.Contains(object? value) { return (values as IList).Contains(value); }
+ int IList.IndexOf(object? value) { return (values as IList).IndexOf(value); }
+ void IList.Insert(int index, object? value) { (values as IList).Insert(index, value); }
+ void IList.Remove(object? value) { (values as IList).Remove(value); }
void IList.RemoveAt(int index) { (values as IList).RemoveAt(index); }
bool IList.IsFixedSize { get { return false; } }
- object IList.this[int index] { get { return this[index]; } set { (values as IList)[index] = value; } }
+ object? IList.this[int index] { get { return this[index]; } set { (values as IList)[index] = value; } }
#endregion
#region IList
@@ -336,12 +339,13 @@ private void AssertValid(int index)
c.OptionName);
}
+ [DisallowNull]
public string this[int index]
{
get
{
AssertValid(index);
- return index >= values.Count ? null : values[index];
+ return index >= values.Count ? string.Empty : values[index];
}
set
{
@@ -368,8 +372,8 @@ public override string ToString()
public class OptionContext
{
- private Option option;
- private string name;
+ private Option? option;
+ private string? name;
private int index;
private readonly OptionSet set;
private readonly OptionValueCollection c;
@@ -380,13 +384,13 @@ public OptionContext(OptionSet set)
this.c = new OptionValueCollection(this);
}
- public Option Option
+ public Option? Option
{
get { return option; }
set { option = value; }
}
- public string OptionName
+ public string? OptionName
{
get { return name; }
set { name = value; }
@@ -419,24 +423,24 @@ public enum OptionValueType
public abstract class Option
{
readonly string prototype;
- readonly string description;
+ readonly string? description;
readonly string[] names;
readonly OptionValueType type;
readonly int count;
- string[] separators;
+ string[]? separators;
readonly bool hidden;
- protected Option(string prototype, string description)
+ protected Option(string prototype, string? description)
: this(prototype, description, 1, false)
{
}
- protected Option(string prototype, string description, int maxValueCount)
+ protected Option(string prototype, string? description, int maxValueCount)
: this(prototype, description, maxValueCount, false)
{
}
- protected Option(string prototype, string description, int maxValueCount, bool hidden)
+ protected Option(string prototype, string? description, int maxValueCount, bool hidden)
{
if (prototype == null)
throw new ArgumentNullException("prototype");
@@ -478,7 +482,7 @@ protected Option(string prototype, string description, int maxValueCount, bool h
}
public string Prototype { get { return prototype; } }
- public string Description { get { return description; } }
+ public string? Description { get { return description; } }
public OptionValueType OptionValueType { get { return type; } }
public int MaxValueCount { get { return count; } }
public bool Hidden { get { return hidden; } }
@@ -491,7 +495,7 @@ public string[] GetNames()
public string[] GetValueSeparators()
{
if (separators == null)
- return new string[0];
+ return Array.Empty();
return (string[])separators.Clone();
}
@@ -513,19 +517,19 @@ protected static T Parse(string value, OptionContext c)
#else
Type targetType = nullable ? tt.GetGenericArguments()[0] : tt;
#endif
- T t = default(T);
+ T t = default(T)!;
try
{
if (value != null)
{
#if PCL
- if (targetType.GetTypeInfo ().IsEnum)
- t = (T) Enum.Parse (targetType, value, true);
- else
- t = (T) Convert.ChangeType (value, targetType);
+ if (targetType.GetTypeInfo ().IsEnum)
+ t = (T) Enum.Parse (targetType, value, true);
+ else
+ t = (T) Convert.ChangeType (value, targetType);
#else
TypeConverter conv = TypeDescriptor.GetConverter(targetType);
- t = (T)conv.ConvertFromString(value);
+ t = (T)conv.ConvertFromString(value)!;
#endif
}
}
@@ -537,11 +541,12 @@ protected static T Parse(string value, OptionContext c)
value, targetType.Name, c.OptionName),
c.OptionName, e);
}
+
return t;
}
internal string[] Names { get { return names; } }
- internal string[] ValueSeparators { get { return separators; } }
+ internal string[]? ValueSeparators { get { return separators; } }
static readonly char[] NameTerminator = new char[] { '=', ':' };
@@ -551,7 +556,7 @@ private OptionValueType ParsePrototype()
List seps = new List();
for (int i = 0; i < names.Length; ++i)
{
- string name = names[i];
+ string? name = names[i];
if (name.Length == 0)
throw new ArgumentException("Empty option names are not supported.", "prototype");
@@ -652,7 +657,7 @@ protected ArgumentSource()
public abstract string[] GetNames();
public abstract string Description { get; }
- public abstract bool GetArguments(string value, out IEnumerable replacement);
+ public abstract bool GetArguments(string value, [NotNullWhen(true)] out IEnumerable? replacement);
#if !PCL || NETSTANDARD1_3
public static IEnumerable GetArgumentsFromFile(string file)
@@ -673,7 +678,7 @@ static IEnumerable GetArguments(TextReader reader, bool close)
{
StringBuilder arg = new StringBuilder();
- string line;
+ string? line;
while ((line = reader.ReadLine()) != null)
{
int t = line.Length;
@@ -735,7 +740,7 @@ public override string Description
get { return "Read response file for more options."; }
}
- public override bool GetArguments(string value, out IEnumerable replacement)
+ public override bool GetArguments(string value, [NotNullWhen(true)] out IEnumerable? replacement)
{
if (string.IsNullOrEmpty(value) || !value.StartsWith("@"))
{
@@ -753,19 +758,19 @@ public override bool GetArguments(string value, out IEnumerable replacem
#endif
public class OptionException : Exception
{
- private string option;
+ private string? option;
public OptionException()
{
}
- public OptionException(string message, string optionName)
+ public OptionException(string message, string? optionName)
: base(message)
{
this.option = optionName;
}
- public OptionException(string message, string optionName, Exception innerException)
+ public OptionException(string message, string? optionName, Exception innerException)
: base(message, innerException)
{
this.option = optionName;
@@ -780,7 +785,7 @@ protected OptionException(SerializationInfo info, StreamingContext context)
}
#endif
- public string OptionName
+ public string? OptionName
{
get { return this.option; }
}
@@ -804,20 +809,20 @@ public OptionSet()
{
}
- public OptionSet(MessageLocalizerConverter localizer)
+ public OptionSet(MessageLocalizerConverter? localizer)
+ : base(StringComparer.Ordinal, dictionaryCreationThreshold: 0)
{
this.roSources = new ReadOnlyCollection(sources);
- this.localizer = localizer;
- if (this.localizer == null)
- {
- this.localizer = delegate (string f) {
+ this.localizer = localizer ??
+ delegate (string f) {
return f;
};
- }
}
MessageLocalizerConverter localizer;
+ private new IDictionary Dictionary => base.Dictionary!;
+
public MessageLocalizerConverter MessageLocalizer
{
get { return localizer; }
@@ -845,7 +850,7 @@ protected override string GetKeyForItem(Option item)
}
[Obsolete("Use KeyedCollection.this[string]")]
- protected Option GetOptionForName(string option)
+ protected Option? GetOptionForName(string option)
{
if (option == null)
throw new ArgumentNullException("option");
@@ -940,12 +945,12 @@ sealed class ActionOption : Option
{
readonly Action action;
- public ActionOption(string prototype, string description, int count, Action action)
+ public ActionOption(string prototype, string? description, int count, Action action)
: this(prototype, description, count, action, false)
{
}
- public ActionOption(string prototype, string description, int count, Action action, bool hidden)
+ public ActionOption(string prototype, string? description, int count, Action action, bool hidden)
: base(prototype, description, count, hidden)
{
if (action == null)
@@ -964,12 +969,12 @@ public OptionSet Add(string prototype, Action action)
return Add(prototype, null, action);
}
- public OptionSet Add(string prototype, string description, Action action)
+ public OptionSet Add(string prototype, string? description, Action action)
{
return Add(prototype, description, action, false);
}
- public OptionSet Add(string prototype, string description, Action action, bool hidden)
+ public OptionSet Add(string prototype, string? description, Action action, bool hidden)
{
if (action == null)
throw new ArgumentNullException("action");
@@ -984,12 +989,12 @@ public OptionSet Add(string prototype, OptionAction action)
return Add(prototype, null, action);
}
- public OptionSet Add(string prototype, string description, OptionAction action)
+ public OptionSet Add(string prototype, string? description, OptionAction action)
{
return Add(prototype, description, action, false);
}
- public OptionSet Add(string prototype, string description, OptionAction action, bool hidden)
+ public OptionSet Add(string prototype, string? description, OptionAction action, bool hidden)
{
if (action == null)
throw new ArgumentNullException("action");
@@ -1003,7 +1008,7 @@ sealed class ActionOption : Option
{
readonly Action action;
- public ActionOption(string prototype, string description, Action action)
+ public ActionOption(string prototype, string? description, Action action)
: base(prototype, description, 1)
{
if (action == null)
@@ -1021,7 +1026,7 @@ sealed class ActionOption : Option
{
readonly OptionAction action;
- public ActionOption(string prototype, string description, OptionAction action)
+ public ActionOption(string prototype, string? description, OptionAction action)
: base(prototype, description, 2)
{
if (action == null)
@@ -1042,7 +1047,7 @@ public OptionSet Add(string prototype, Action action)
return Add(prototype, null, action);
}
- public OptionSet Add(string prototype, string description, Action action)
+ public OptionSet Add(string prototype, string? description, Action action)
{
return Add(new ActionOption(prototype, description, action));
}
@@ -1052,7 +1057,7 @@ public OptionSet Add(string prototype, OptionAction
return Add(prototype, null, action);
}
- public OptionSet Add(string prototype, string description, OptionAction action)
+ public OptionSet Add(string prototype, string? description, OptionAction action)
{
return Add(new ActionOption(prototype, description, action));
}
@@ -1078,7 +1083,7 @@ public List Parse(IEnumerable arguments)
c.OptionIndex = -1;
bool process = true;
List unprocessed = new List();
- Option def = Contains("<>") ? this["<>"] : null;
+ Option? def = Contains("<>") ? this["<>"] : null;
ArgumentEnumerator ae = new ArgumentEnumerator(arguments);
foreach (string argument in ae)
{
@@ -1142,7 +1147,7 @@ bool AddSource(ArgumentEnumerator ae, string argument)
{
foreach (ArgumentSource source in sources)
{
- IEnumerable replacement;
+ IEnumerable? replacement;
if (!source.GetArguments(argument, out replacement))
continue;
ae.Add(replacement);
@@ -1151,7 +1156,7 @@ bool AddSource(ArgumentEnumerator ae, string argument)
return false;
}
- private static bool Unprocessed(ICollection extra, Option def, OptionContext c, string argument)
+ private static bool Unprocessed(ICollection extra, Option? def, OptionContext c, string argument)
{
if (def == null)
{
@@ -1167,7 +1172,7 @@ private static bool Unprocessed(ICollection extra, Option def, OptionCon
private readonly Regex ValueOption = new Regex(
@"^(?--|-|/)(?[^:=]+)((?[:=])(?.*))?$");
- protected bool GetOptionParts(string argument, out string flag, out string name, out string sep, out string value)
+ protected bool GetOptionParts(string argument, [NotNullWhen(true)] out string? flag, [NotNullWhen(true)] out string? name, out string? sep, out string? value)
{
if (argument == null)
throw new ArgumentNullException("argument");
@@ -1196,7 +1201,7 @@ protected virtual bool Parse(string argument, OptionContext c)
return true;
}
- string f, n, s, v;
+ string? f, n, s, v;
if (!GetOptionParts(argument, out f, out n, out s, out v))
return false;
@@ -1229,8 +1234,10 @@ protected virtual bool Parse(string argument, OptionContext c)
return false;
}
- private void ParseValue(string option, OptionContext c)
+ private void ParseValue(string? option, OptionContext c)
{
+ Guard.OperationValid(c.Option != null, "OptionContext.Option != null");
+
if (option != null)
foreach (string o in c.Option.ValueSeparators != null
? option.Split(c.Option.ValueSeparators, c.Option.MaxValueCount - c.OptionValues.Count, StringSplitOptions.None)
@@ -1258,7 +1265,7 @@ private bool ParseBool(string option, string n, OptionContext c)
Contains((rn = n.Substring(0, n.Length - 1))))
{
p = this[rn];
- string v = n[n.Length - 1] == '+' ? option : null;
+ string v = n[n.Length - 1] == '+' ? option : string.Empty;
c.OptionName = option;
c.Option = p;
c.OptionValues.Add(v);
@@ -1330,13 +1337,13 @@ public void WriteOptionDescriptions(TextWriter o)
if (p.Hidden)
continue;
- Category c = p as Category;
+ Category? c = p as Category;
if (c != null)
{
WriteDescription(o, p.Description, "", 80, 80);
continue;
}
- CommandOption co = p as CommandOption;
+ CommandOption? co = p as CommandOption;
if (co != null)
{
WriteCommandDescription(o, co.Command, co.CommandName);
@@ -1387,7 +1394,7 @@ public void WriteOptionDescriptions(TextWriter o)
}
}
- internal void WriteCommandDescription(TextWriter o, Command c, string commandName)
+ internal void WriteCommandDescription(TextWriter o, Command c, string? commandName)
{
var name = new string(' ', 8) + (commandName ?? c.Name);
if (name.Length < OptionWidth - 1)
@@ -1401,7 +1408,7 @@ internal void WriteCommandDescription(TextWriter o, Command c, string commandNam
}
}
- void WriteDescription(TextWriter o, string value, string prefix, int firstWidth, int remWidth)
+ void WriteDescription(TextWriter o, string? value, string prefix, int firstWidth, int remWidth)
{
bool indent = false;
foreach (string line in GetLines(localizer(GetDescription(value)), firstWidth, remWidth))
@@ -1478,7 +1485,7 @@ static void Write(TextWriter o, ref int n, string s)
o.Write(s);
}
- static string GetArgumentName(int index, int maxIndex, string description)
+ static string GetArgumentName(int index, int maxIndex, string? description)
{
var matches = Regex.Matches(description ?? "", @"(?<=(? GetLines(string description, int firstWidth,
public class Command
{
+ private CommandSet? commandSet;
+
public string Name { get; }
- public string Help { get; }
+ public string? Help { get; }
- public OptionSet Options { get; set; }
- public Action> Run { get; set; }
+ public OptionSet? Options { get; set; }
+ public Action>? Run { get; set; }
- public CommandSet CommandSet { get; internal set; }
+ public CommandSet CommandSet { get => commandSet.ShouldNotBeNull(); internal set => commandSet = value; }
- public Command(string name, string help = null)
+ public Command(string name, string? help = null)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException(nameof(name));
@@ -1613,7 +1622,7 @@ class CommandOption : Option
// Prototype starts with '=' because this is an invalid prototype
// (see Option.ParsePrototype(), and thus it'll prevent Category
// instances from being accidentally used as normal options.
- public CommandOption(Command command, string commandName = null, bool hidden = false)
+ public CommandOption(Command command, string? commandName = null, bool hidden = false)
: base("=:Command:= " + (commandName ?? command?.Name), (commandName ?? command?.Name), maxValueCount: 0, hidden: hidden)
{
if (command == null)
@@ -1652,7 +1661,7 @@ class CommandOptionSet : OptionSet
{
readonly CommandSet commands;
- public CommandOptionSet(CommandSet commands, MessageLocalizerConverter localizer)
+ public CommandOptionSet(CommandSet commands, MessageLocalizerConverter? localizer)
: base(localizer)
{
this.commands = commands;
@@ -1702,22 +1711,22 @@ public class CommandSet : KeyedCollection
TextWriter outWriter;
TextWriter errorWriter;
- internal List NestedCommandSets;
+ internal List? NestedCommandSets;
- internal HelpCommand help;
+ internal HelpCommand? help;
internal bool showHelp;
internal OptionSet Options => options;
#if !PCL || NETSTANDARD1_3
- public CommandSet(string suite, MessageLocalizerConverter localizer = null)
+ public CommandSet(string suite, MessageLocalizerConverter? localizer = null)
: this(suite, Console.Out, Console.Error, localizer)
{
}
#endif
- public CommandSet(string suite, TextWriter output, TextWriter error, MessageLocalizerConverter localizer = null)
+ public CommandSet(string suite, TextWriter output, TextWriter error, MessageLocalizerConverter? localizer = null)
{
if (suite == null)
throw new ArgumentNullException(nameof(suite));
@@ -1739,7 +1748,7 @@ public CommandSet(string suite, TextWriter output, TextWriter error, MessageLoca
protected override string GetKeyForItem(Command item)
{
- return item?.Name;
+ return item.Name;
}
public new CommandSet Add(Command value)
@@ -1893,7 +1902,7 @@ bool AlreadyAdded(CommandSet value)
return false;
}
- public IEnumerable GetCompletions(string prefix = null)
+ public IEnumerable GetCompletions(string? prefix = null)
{
string rest;
ExtractToken(ref prefix, out rest);
@@ -1921,7 +1930,7 @@ public IEnumerable GetCompletions(string prefix = null)
}
}
- static void ExtractToken(ref string input, out string rest)
+ static void ExtractToken([NotNull] ref string? input, out string rest)
{
rest = "";
input = input ?? "";
@@ -1997,12 +2006,12 @@ public int Run(IEnumerable arguments)
return command.Invoke(extra);
}
- internal Command GetCommand(List extra)
+ internal Command? GetCommand(List extra)
{
return TryGetLocalCommand(extra) ?? TryGetNestedCommand(extra);
}
- Command TryGetLocalCommand(List extra)
+ Command? TryGetLocalCommand(List extra)
{
var name = extra[0];
if (Contains(name))
@@ -2021,7 +2030,7 @@ Command TryGetLocalCommand(List extra)
return null;
}
- Command TryGetNestedCommand(List extra)
+ Command? TryGetNestedCommand(List extra)
{
if (NestedCommandSets == null)
return null;
@@ -2055,7 +2064,7 @@ public HelpCommand()
public override int Invoke(IEnumerable arguments)
{
- var extra = new List(arguments ?? new string[0]);
+ var extra = new List();
var _ = CommandSet.Options.MessageLocalizer;
if (extra.Count == 0)
{
@@ -2080,7 +2089,8 @@ public override int Invoke(IEnumerable arguments)
}
CommandSet.Options.WriteCommandDescription(CommandSet.Out, c.Value, c.Key);
}
- CommandSet.Options.WriteCommandDescription(CommandSet.Out, CommandSet.help, "help");
+ if (CommandSet.help != null)
+ CommandSet.Options.WriteCommandDescription(CommandSet.Out, CommandSet.help, "help");
return 0;
}
if (command == null)
@@ -2100,15 +2110,17 @@ List> GetCommands()
{
var commands = new List>();
- foreach (var c in CommandSet)
+ var commandSet = CommandSet;
+
+ foreach (var c in commandSet)
{
commands.Add(new KeyValuePair(c.Name, c));
}
- if (CommandSet.NestedCommandSets == null)
+ if (commandSet.NestedCommandSets == null)
return commands;
- foreach (var nc in CommandSet.NestedCommandSets)
+ foreach (var nc in commandSet.NestedCommandSets)
{
AddNestedCommands(commands, "", nc);
}
@@ -2132,8 +2144,10 @@ void AddNestedCommands(List> commands, string oute
internal void WriteUnknownCommand(string unknownCommand)
{
- CommandSet.Error.WriteLine(CommandSet.Options.MessageLocalizer($"{CommandSet.Suite}: Unknown command: {unknownCommand}"));
- CommandSet.Error.WriteLine(CommandSet.Options.MessageLocalizer($"{CommandSet.Suite}: Use `{CommandSet.Suite} help` for usage."));
+ var commandSet = CommandSet;
+
+ commandSet.Error.WriteLine(commandSet.Options.MessageLocalizer($"{commandSet.Suite}: Unknown command: {unknownCommand}"));
+ commandSet.Error.WriteLine(commandSet.Options.MessageLocalizer($"{commandSet.Suite}: Use `{commandSet.Suite} help` for usage."));
}
}
}
diff --git a/src/NUnitConsole/nunit4-netcore-console/Options/OutputSpecification.cs b/src/NUnitConsole/nunit4-netcore-console/Options/OutputSpecification.cs
index 2390025bc..24f03b8b5 100644
--- a/src/NUnitConsole/nunit4-netcore-console/Options/OutputSpecification.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/Options/OutputSpecification.cs
@@ -17,7 +17,7 @@ public class OutputSpecification
///
/// The option value string.
/// The folder containing the transform.
- public OutputSpecification(string spec, string transformFolder)
+ public OutputSpecification(string spec, string? transformFolder)
{
if (spec == null)
throw new ArgumentNullException(nameof(spec), "Output spec may not be null");
@@ -78,7 +78,7 @@ public OutputSpecification(string spec, string transformFolder)
///
/// Gets the file name of a transform to be applied
///
- public string Transform { get; private set; }
+ public string? Transform { get; private set; }
public override string ToString()
{
diff --git a/src/NUnitConsole/nunit4-netcore-console/Program.cs b/src/NUnitConsole/nunit4-netcore-console/Program.cs
index 59f545d6e..5103f372b 100644
--- a/src/NUnitConsole/nunit4-netcore-console/Program.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/Program.cs
@@ -21,7 +21,7 @@ public class Program
{
//static Logger log = InternalTrace.GetLogger(typeof(Runner));
static readonly ConsoleOptions Options = new ConsoleOptions(new DefaultOptionsProvider(), new FileSystem());
- private static ExtendedTextWriter _outWriter;
+ private static ExtendedTextWriter? _outWriter;
// This has to be lazy otherwise NoColor command line option is not applied correctly
private static ExtendedTextWriter OutWriter
@@ -173,7 +173,7 @@ public static int Main(string[] args)
private static void WriteHeader()
{
- Assembly entryAssembly = Assembly.GetEntryAssembly();
+ Assembly entryAssembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
var versionBlock = FileVersionInfo.GetVersionInfo(entryAssembly.ManifestModule.FullyQualifiedName);
var header = $"{versionBlock.ProductName} {versionBlock.ProductVersion}";
@@ -187,7 +187,7 @@ private static void WriteHeader()
}
OutWriter.WriteLine(ColorStyle.Header, header);
- OutWriter.WriteLine(ColorStyle.SubHeader, versionBlock.LegalCopyright);
+ OutWriter.WriteLine(ColorStyle.SubHeader, versionBlock.LegalCopyright ?? "No Copyright statement found");
OutWriter.WriteLine(ColorStyle.SubHeader, DateTime.Now.ToString(CultureInfo.CurrentCulture.DateTimeFormat.FullDateTimePattern));
OutWriter.WriteLine();
}
@@ -195,9 +195,9 @@ private static void WriteHeader()
private static void WriteHelpText()
{
OutWriter.WriteLine();
- OutWriter.WriteLine(ColorStyle.Header, "NUNIT3-CONSOLE [inputfiles] [options]");
+ OutWriter.WriteLine(ColorStyle.Header, "NUNIT4-CONSOLE [inputfiles] [options]");
OutWriter.WriteLine();
- OutWriter.WriteLine(ColorStyle.SectionHeader, "Operation");
+ OutWriter.WriteLine(ColorStyle.SectionHeader, "Operation:");
using (new ColorConsole(ColorStyle.Default))
{
OutWriter.WriteLine(" The NetCore Console Runner runs a set of NUnit tests from the console");
@@ -294,7 +294,7 @@ private static void WriteErrorMessage(string msg)
OutWriter.WriteLine(ColorStyle.Error, msg);
}
- private static void CancelHandler(object sender, ConsoleCancelEventArgs args)
+ private static void CancelHandler(object? sender, ConsoleCancelEventArgs args)
{
Console.ResetColor();
}
diff --git a/src/NUnitConsole/nunit4-netcore-console/ResultReporter.cs b/src/NUnitConsole/nunit4-netcore-console/ResultReporter.cs
index 2e7dfcf85..35893f5a2 100644
--- a/src/NUnitConsole/nunit4-netcore-console/ResultReporter.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/ResultReporter.cs
@@ -5,11 +5,10 @@
using System.Globalization;
using System.Xml;
using NUnit.ConsoleRunner.Options;
+using NUnit.ConsoleRunner.Utilities;
namespace NUnit.ConsoleRunner
{
- using Utilities;
-
public class ResultReporter
{
public ResultReporter(XmlNode resultNode, ExtendedTextWriter writer, ConsoleOptions options)
@@ -18,12 +17,13 @@ public ResultReporter(XmlNode resultNode, ExtendedTextWriter writer, ConsoleOpti
Writer = writer;
Options = options;
- OverallResult = resultNode.GetAttribute("result");
- if (OverallResult == "Skipped")
+ string? overallResult = resultNode.GetAttribute("result");
+ if (overallResult == "Skipped")
OverallResult = "Warning";
- if (OverallResult == null)
+ if (overallResult == null)
OverallResult = "Unknown";
-
+ else
+ OverallResult = overallResult;
Summary = new ResultSummary(resultNode);
}
@@ -60,7 +60,7 @@ internal void WriteRunSettingsReport()
{
var settings = firstSuite.SelectNodes("settings/setting");
- if (settings.Count > 0)
+ if (settings is not null && settings.Count > 0)
{
Writer.WriteLine(ColorStyle.SectionHeader, "Run Settings");
@@ -78,13 +78,18 @@ private void WriteSettingsNode(XmlNode node)
var name = node.GetAttribute("name");
var val = node.GetAttribute("value") ?? string.Empty;
- Writer.WriteLabelLine($" {name}:", items.Count > 0 ? string.Empty : $" |{val}|");
-
- foreach (XmlNode item in items)
+ if (items is null || items.Count == 0)
+ Writer.WriteLabelLine($" {name}:", $" |{val}|");
+ else
{
- var key = item.GetAttribute("key");
- var value = item.GetAttribute("value");
- Writer.WriteLine(ColorStyle.Value, $" {key} -> |{value}|");
+ Writer.WriteLabelLine($" {name}:", string.Empty);
+
+ foreach (XmlNode item in items)
+ {
+ var key = item.GetAttribute("key");
+ var value = item.GetAttribute("value");
+ Writer.WriteLine(ColorStyle.Value, $" {key} -> |{value}|");
+ }
}
}
@@ -154,7 +159,7 @@ public void WriteErrorsFailuresAndWarningsReport()
private void WriteErrorsFailuresAndWarnings(XmlNode resultNode)
{
- string resultState = resultNode.GetAttribute("result");
+ string? resultState = resultNode.GetAttribute("result");
switch (resultNode.Name)
{
@@ -225,7 +230,7 @@ private void WriteNotRunResults(XmlNode resultNode)
switch (resultNode.Name)
{
case "test-case":
- string status = resultNode.GetAttribute("result");
+ string? status = resultNode.GetAttribute("result");
if (status == "Skipped")
new ConsoleTestResult(resultNode, ++ReportIndex).WriteResult(Writer);
diff --git a/src/NUnitConsole/nunit4-netcore-console/ResultSummary.cs b/src/NUnitConsole/nunit4-netcore-console/ResultSummary.cs
index b2f408ace..73c68ab09 100644
--- a/src/NUnitConsole/nunit4-netcore-console/ResultSummary.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/ResultSummary.cs
@@ -3,11 +3,10 @@
using System;
using System.Globalization;
using System.Xml;
+using NUnit.ConsoleRunner.Utilities;
namespace NUnit.ConsoleRunner
{
- using Utilities;
-
///
/// Summary description for ResultSummary.
///
@@ -138,10 +137,10 @@ private void InitializeCounters()
private void Summarize(XmlNode node, bool failedInFixtureTearDown)
{
- string type = node.GetAttribute("type");
- string status = node.GetAttribute("result");
- string label = node.GetAttribute("label");
- string site = node.GetAttribute("site");
+ string? type = node.GetAttribute("type");
+ string? status = node.GetAttribute("result");
+ string? label = node.GetAttribute("label");
+ string? site = node.GetAttribute("site");
switch (node.Name)
{
diff --git a/src/NUnitConsole/nunit4-netcore-console/SafeAttributeAccess.cs b/src/NUnitConsole/nunit4-netcore-console/SafeAttributeAccess.cs
index 35c0ef6b3..6566ef87d 100644
--- a/src/NUnitConsole/nunit4-netcore-console/SafeAttributeAccess.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/SafeAttributeAccess.cs
@@ -23,9 +23,9 @@ public static class SafeAttributeAccess
/// The result.
/// The name.
///
- public static string GetAttribute(this XmlNode result, string name)
+ public static string? GetAttribute(this XmlNode result, string name)
{
- XmlAttribute attr = result.Attributes[name];
+ XmlAttribute? attr = result.Attributes?[name];
return attr == null ? null : attr.Value;
}
@@ -39,7 +39,7 @@ public static string GetAttribute(this XmlNode result, string name)
///
public static double GetAttribute(this XmlNode result, string name, double defaultValue)
{
- XmlAttribute attr = result.Attributes[name];
+ XmlAttribute? attr = result.Attributes?[name];
return attr == null
? defaultValue
@@ -55,7 +55,7 @@ public static double GetAttribute(this XmlNode result, string name, double defau
///
public static DateTime GetAttribute(this XmlNode result, string name, DateTime defaultValue)
{
- string dateStr = GetAttribute(result, name);
+ string? dateStr = GetAttribute(result, name);
if (dateStr == null)
return defaultValue;
diff --git a/src/NUnitConsole/nunit4-netcore-console/TestEventHandler.cs b/src/NUnitConsole/nunit4-netcore-console/TestEventHandler.cs
index 23013310f..871f5e260 100644
--- a/src/NUnitConsole/nunit4-netcore-console/TestEventHandler.cs
+++ b/src/NUnitConsole/nunit4-netcore-console/TestEventHandler.cs
@@ -22,7 +22,7 @@ public class TestEventHandler : ITestEventListener
private readonly bool _displayAfterTest;
private readonly bool _displayBeforeOutput;
- private string _lastTestOutput;
+ private string? _lastTestOutput;
private bool _wantNewLine = false;
public TestEventHandler(ExtendedTextWriter outWriter, string labelsOption)
@@ -41,6 +41,9 @@ public void OnTestEvent(string report)
doc.LoadXml(report);
var testEvent = doc.FirstChild;
+ if (testEvent == null)
+ return;
+
switch (testEvent.Name)
{
case "start-test":
@@ -63,16 +66,20 @@ public void OnTestEvent(string report)
private void TestStarted(XmlNode testResult)
{
- var testName = testResult.Attributes["fullname"].Value;
+ var testName = testResult.Attributes?["fullname"]?.Value;
- if (_displayBeforeTest)
+ if (_displayBeforeTest && testName != null)
WriteLabelLine(testName);
}
private void TestFinished(XmlNode testResult)
{
- var testName = testResult.Attributes["fullname"].Value;
- var status = testResult.GetAttribute("label") ?? testResult.GetAttribute("result");
+ var testName = testResult.Attributes?["fullname"]?.Value;
+
+ if (testName == null)
+ return;
+
+ var status = testResult.GetAttribute("label") ?? testResult.GetAttribute("result") ?? "Unknown";
var outputNode = testResult.SelectSingleNode("output");
if (outputNode != null)
@@ -90,10 +97,10 @@ private void TestFinished(XmlNode testResult)
private void SuiteFinished(XmlNode testResult)
{
- var suiteName = testResult.Attributes["fullname"].Value;
+ var suiteName = testResult.Attributes?["fullname"]?.Value;
var outputNode = testResult.SelectSingleNode("output");
- if (outputNode != null)
+ if (suiteName != null && outputNode != null)
{
if (_displayBeforeOutput)
WriteLabelLine(suiteName);
@@ -106,15 +113,18 @@ private void SuiteFinished(XmlNode testResult)
private void TestOutput(XmlNode outputNode)
{
var testName = outputNode.GetAttribute("testname");
- var stream = outputNode.GetAttribute("stream");
- if (_displayBeforeOutput && testName != null)
- WriteLabelLine(testName);
+ if (testName != null)
+ {
+ if (_displayBeforeOutput)
+ WriteLabelLine(testName);
- WriteOutputLine(testName, outputNode.InnerText, stream == "Error" ? ColorStyle.Error : ColorStyle.Output);
+ var stream = outputNode.GetAttribute("stream");
+ WriteOutputLine(testName, outputNode.InnerText, stream == "Error" ? ColorStyle.Error : ColorStyle.Output);
+ }
}
- private string _currentLabel;
+ private string? _currentLabel;
private void WriteLabelLine(string label)
{
@@ -198,7 +208,7 @@ private static ColorStyle GetColorForResultStatus(string status)
#if NETFRAMEWORK
public override object InitializeLifetimeService()
{
- return null;
+ return null!;
}
#endif
}
diff --git a/src/NUnitConsole/nunit4-netcore-console/nunit4-netcore-console.csproj b/src/NUnitConsole/nunit4-netcore-console/nunit4-netcore-console.csproj
index 83f6ee8fb..d0d29ef09 100644
--- a/src/NUnitConsole/nunit4-netcore-console/nunit4-netcore-console.csproj
+++ b/src/NUnitConsole/nunit4-netcore-console/nunit4-netcore-console.csproj
@@ -34,12 +34,17 @@
Copyright (c) 2022 Charlie Poole, Rob Prouse
+
+
..\..\..\nunit.ico
app.manifest
+
+
+
@@ -53,7 +58,6 @@
-
\ No newline at end of file
diff --git a/src/NUnitEngine/agents/Program.cs b/src/NUnitEngine/agents/Program.cs
index 5ccb3475d..3b5af3031 100644
--- a/src/NUnitEngine/agents/Program.cs
+++ b/src/NUnitEngine/agents/Program.cs
@@ -2,10 +2,8 @@
using System;
using System.Diagnostics;
-using System.IO;
using System.Runtime.InteropServices;
using System.Security;
-using Microsoft.Win32;
using NUnit.Common;
using NUnit.Engine;
using NUnit.Engine.Agents;
@@ -38,10 +36,9 @@ public class NUnitTestAgent
#endif
static Guid AgentId;
- static string AgencyUrl;
- static Process AgencyProcess;
- static RemoteTestAgent Agent;
- private static Logger log;
+ static string? AgencyUrl;
+ static Process? AgencyProcess;
+ static RemoteTestAgent? Agent;
///
/// The main entry point for the application.
@@ -84,15 +81,15 @@ public static void Main(string[] args)
var logName = $"nunit-agent_{pid}.log";
//InternalTrace.Initialize(Path.Combine(workDirectory, logName), traceLevel);
- log = InternalTrace.GetLogger(typeof(NUnitTestAgent));
+ Logger log = InternalTrace.GetLogger(typeof(NUnitTestAgent));
log.Info($"Agent process {pid} starting");
log.Info($"Running {AGENT_RUNTIME} agent under {CURRENT_RUNTIME}");
if (debugArgPassed)
- TryLaunchDebugger();
+ TryLaunchDebugger(log);
- LocateAgencyProcess(agencyPid);
+ AgencyProcess = LocateAgencyProcess(log, agencyPid);
log.Info("Starting RemoteTestAgent");
Agent = new RemoteTestAgent(AgentId);
@@ -106,7 +103,7 @@ public static void Main(string[] args)
try
{
if (Agent.Start())
- WaitForStop();
+ WaitForStop(log, Agent, AgencyProcess);
else
{
log.Error("Failed to start RemoteTestAgent");
@@ -123,28 +120,29 @@ public static void Main(string[] args)
Environment.Exit(AgentExitCodes.OK);
}
- private static void LocateAgencyProcess(string agencyPid)
+ private static Process LocateAgencyProcess(Logger log, string agencyPid)
{
var agencyProcessId = int.Parse(agencyPid);
try
{
- AgencyProcess = Process.GetProcessById(agencyProcessId);
+ return Process.GetProcessById(agencyProcessId);
}
catch (Exception e)
{
log.Error($"Unable to connect to agency process with PID: {agencyProcessId}");
log.Error($"Failed with exception: {e.Message} {e.StackTrace}");
Environment.Exit(AgentExitCodes.UNABLE_TO_LOCATE_AGENCY);
+ return null; // Will never reach here
}
}
- private static void WaitForStop()
+ private static void WaitForStop(Logger log, RemoteTestAgent agent, Process agencyProcess)
{
log.Debug("Waiting for stopSignal");
- while (!Agent.WaitForStop(500))
+ while (!agent.WaitForStop(500))
{
- if (AgencyProcess.HasExited)
+ if (agencyProcess.HasExited)
{
log.Error("Parent process has been terminated.");
Environment.Exit(AgentExitCodes.PARENT_PROCESS_TERMINATED);
@@ -154,7 +152,7 @@ private static void WaitForStop()
log.Debug("Stop signal received");
}
- private static void TryLaunchDebugger()
+ private static void TryLaunchDebugger(Logger log)
{
if (Debugger.IsAttached)
return;
diff --git a/src/NUnitEngine/agents/nunit-agent-net462-x86/nunit-agent-net462-x86.csproj b/src/NUnitEngine/agents/nunit-agent-net462-x86/nunit-agent-net462-x86.csproj
index d1f40e79b..eebdb98cc 100644
--- a/src/NUnitEngine/agents/nunit-agent-net462-x86/nunit-agent-net462-x86.csproj
+++ b/src/NUnitEngine/agents/nunit-agent-net462-x86/nunit-agent-net462-x86.csproj
@@ -11,6 +11,8 @@
False
+
+
NUnit Engine
NUnit X86 Agent ($(TargetFramework))
diff --git a/src/NUnitEngine/agents/nunit-agent-net462/nunit-agent-net462.csproj b/src/NUnitEngine/agents/nunit-agent-net462/nunit-agent-net462.csproj
index 02dfc2346..f13bce4c4 100644
--- a/src/NUnitEngine/agents/nunit-agent-net462/nunit-agent-net462.csproj
+++ b/src/NUnitEngine/agents/nunit-agent-net462/nunit-agent-net462.csproj
@@ -10,6 +10,8 @@
false
+
+
NUnit Engine
NUnit Agent ($(TargetFramework))
diff --git a/src/NUnitEngine/agents/nunit-agent-net60/nunit-agent-net60.csproj b/src/NUnitEngine/agents/nunit-agent-net60/nunit-agent-net60.csproj
index 05cfc0e5e..e784b37e8 100644
--- a/src/NUnitEngine/agents/nunit-agent-net60/nunit-agent-net60.csproj
+++ b/src/NUnitEngine/agents/nunit-agent-net60/nunit-agent-net60.csproj
@@ -11,6 +11,8 @@
1505
+
+
NUnit Engine
NUnit Agent ($(TargetFramework))
diff --git a/src/NUnitEngine/agents/nunit-agent-net70/nunit-agent-net70.csproj b/src/NUnitEngine/agents/nunit-agent-net70/nunit-agent-net70.csproj
index 5e583844d..79fe076cb 100644
--- a/src/NUnitEngine/agents/nunit-agent-net70/nunit-agent-net70.csproj
+++ b/src/NUnitEngine/agents/nunit-agent-net70/nunit-agent-net70.csproj
@@ -11,6 +11,8 @@
1505
+
+
NUnit Engine
NUnit Agent ($(TargetFramework))
diff --git a/src/NUnitEngine/agents/nunit-agent-net80/nunit-agent-net80.csproj b/src/NUnitEngine/agents/nunit-agent-net80/nunit-agent-net80.csproj
index 4dc66611a..571deac30 100644
--- a/src/NUnitEngine/agents/nunit-agent-net80/nunit-agent-net80.csproj
+++ b/src/NUnitEngine/agents/nunit-agent-net80/nunit-agent-net80.csproj
@@ -12,6 +12,8 @@
true
+
+
NUnit Engine
NUnit Agent ($(TargetFramework))
diff --git a/src/NUnitEngine/agents/nunit-agent-netcore31/nunit-agent-netcore31.csproj b/src/NUnitEngine/agents/nunit-agent-netcore31/nunit-agent-netcore31.csproj
index d7d7b10af..62ca5ee1b 100644
--- a/src/NUnitEngine/agents/nunit-agent-netcore31/nunit-agent-netcore31.csproj
+++ b/src/NUnitEngine/agents/nunit-agent-netcore31/nunit-agent-netcore31.csproj
@@ -12,6 +12,8 @@
$(NoWarn);SYSLIB0011;SYSLIB0012;1505
+
+
NUnit Engine
NUnit Agent ($(TargetFramework))
diff --git a/src/NUnitEngine/nunit.engine.api/Exceptions/NUnitEngineException.cs b/src/NUnitEngine/nunit.engine.api/Exceptions/NUnitEngineException.cs
index 9fd086f39..4502ee5b6 100644
--- a/src/NUnitEngine/nunit.engine.api/Exceptions/NUnitEngineException.cs
+++ b/src/NUnitEngine/nunit.engine.api/Exceptions/NUnitEngineException.cs
@@ -23,7 +23,7 @@ public NUnitEngineException(string message) : base(message)
///
/// Construct with a message and inner exception
///
- public NUnitEngineException(string message, Exception innerException) : base(message, innerException)
+ public NUnitEngineException(string message, Exception? innerException) : base(message, innerException)
{
}
diff --git a/src/NUnitEngine/nunit.engine.api/Exceptions/NUnitEngineUnloadException.cs b/src/NUnitEngine/nunit.engine.api/Exceptions/NUnitEngineUnloadException.cs
index 44b8d2fe7..ce9a00121 100644
--- a/src/NUnitEngine/nunit.engine.api/Exceptions/NUnitEngineUnloadException.cs
+++ b/src/NUnitEngine/nunit.engine.api/Exceptions/NUnitEngineUnloadException.cs
@@ -49,6 +49,6 @@ public NUnitEngineUnloadException(SerializationInfo info, StreamingContext conte
///
/// Gets the collection of exceptions .
///
- public ICollection AggregatedExceptions { get; }
+ public ICollection? AggregatedExceptions { get; }
}
-}
\ No newline at end of file
+}
diff --git a/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionAttribute.cs b/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionAttribute.cs
index 0d00818b1..44aeeee2f 100644
--- a/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionAttribute.cs
+++ b/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionAttribute.cs
@@ -24,12 +24,12 @@ public ExtensionAttribute()
/// intended. This is an optional field provided NUnit is able to deduce the
/// ExtensionPoint from the Type of the extension class.
///
- public string Path { get; set; }
+ public string? Path { get; set; }
///
/// An optional description of what the extension does.
///
- public string Description { get; set; }
+ public string? Description { get; set; }
///
/// Flag indicating whether the extension is enabled.
@@ -40,6 +40,6 @@ public ExtensionAttribute()
///
/// The minimum Engine version for which this extension is designed
///
- public string EngineVersion { get; set; }
+ public string? EngineVersion { get; set; }
}
}
diff --git a/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionPointAttribute.cs b/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionPointAttribute.cs
index e6dc9c7ec..652241ff7 100644
--- a/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionPointAttribute.cs
+++ b/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionPointAttribute.cs
@@ -27,17 +27,17 @@ public ExtensionPointAttribute(string path, Type type)
/// is typically formatted as a path using '/' and the set of extension
/// points is sometimes viewed as forming a tree.
///
- public string Path { get; private set; }
+ public string Path { get; }
///
/// The required Type (usually an interface) of any extension that is
/// installed at this ExtensionPoint.
///
- public Type Type { get; private set; }
+ public Type Type { get; }
///
/// An optional description of the purpose of the ExtensionPoint
///
- public string Description { get; set; }
+ public string? Description { get; set; }
}
}
diff --git a/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionPropertyAttribute.cs b/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionPropertyAttribute.cs
index 21cef130e..b09b652e1 100644
--- a/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionPropertyAttribute.cs
+++ b/src/NUnitEngine/nunit.engine.api/Extensibility/ExtensionPropertyAttribute.cs
@@ -24,11 +24,11 @@ public ExtensionPropertyAttribute(string name, string value)
///
/// The name of the property.
///
- public string Name { get; private set; }
+ public string Name { get; }
///
/// The property value
///
- public string Value { get; private set; }
+ public string Value { get; }
}
}
diff --git a/src/NUnitEngine/nunit.engine.api/Extensibility/IExtensionNode.cs b/src/NUnitEngine/nunit.engine.api/Extensibility/IExtensionNode.cs
index dd7a09fe2..1edbfde00 100644
--- a/src/NUnitEngine/nunit.engine.api/Extensibility/IExtensionNode.cs
+++ b/src/NUnitEngine/nunit.engine.api/Extensibility/IExtensionNode.cs
@@ -32,12 +32,12 @@ public interface IExtensionNode
///
/// Gets an optional description of what the extension does.
///
- string Description { get; }
+ string? Description { get; }
///
/// The TargetFramework of the extension assembly.
///
- IRuntimeFramework TargetFramework { get; }
+ IRuntimeFramework? TargetFramework { get; }
///
/// Gets a collection of the names of all this extension's properties
diff --git a/src/NUnitEngine/nunit.engine.api/Extensibility/IExtensionPoint.cs b/src/NUnitEngine/nunit.engine.api/Extensibility/IExtensionPoint.cs
index c0365a5c6..9c436862c 100644
--- a/src/NUnitEngine/nunit.engine.api/Extensibility/IExtensionPoint.cs
+++ b/src/NUnitEngine/nunit.engine.api/Extensibility/IExtensionPoint.cs
@@ -19,7 +19,7 @@ public interface IExtensionPoint
///
/// Gets the description of this extension point. May be null.
///
- string Description { get; }
+ string? Description { get; }
///
/// Gets the FullName of the Type required for any extension to be installed at this extension point.
diff --git a/src/NUnitEngine/nunit.engine.api/Extensibility/IFrameworkDriver.cs b/src/NUnitEngine/nunit.engine.api/Extensibility/IFrameworkDriver.cs
index 0c0599b2a..3f8f190bb 100644
--- a/src/NUnitEngine/nunit.engine.api/Extensibility/IFrameworkDriver.cs
+++ b/src/NUnitEngine/nunit.engine.api/Extensibility/IFrameworkDriver.cs
@@ -39,7 +39,7 @@ public interface IFrameworkDriver
/// An ITestEventHandler that receives progress notices
/// A XML string representing the filter that controls which tests are executed
/// An Xml string representing the result
- string Run(ITestEventListener listener, string filter);
+ string Run(ITestEventListener? listener, string filter);
///
/// Returns information about the tests in an assembly.
diff --git a/src/NUnitEngine/nunit.engine.api/Extensibility/TypeExtensionPointAttribute.cs b/src/NUnitEngine/nunit.engine.api/Extensibility/TypeExtensionPointAttribute.cs
index 170cfa6b0..a005119f1 100644
--- a/src/NUnitEngine/nunit.engine.api/Extensibility/TypeExtensionPointAttribute.cs
+++ b/src/NUnitEngine/nunit.engine.api/Extensibility/TypeExtensionPointAttribute.cs
@@ -35,11 +35,11 @@ public TypeExtensionPointAttribute()
/// is typically formatted as a path using '/' and the set of extension
/// points is sometimes viewed as forming a tree.
///
- public string Path { get; private set; }
+ public string? Path { get; }
///
/// An optional description of the purpose of the ExtensionPoint
///
- public string Description { get; set; }
+ public string? Description { get; set; }
}
}
diff --git a/src/NUnitEngine/nunit.engine.api/IExtensionService.cs b/src/NUnitEngine/nunit.engine.api/IExtensionService.cs
index 6c8b31544..3574bfbb8 100644
--- a/src/NUnitEngine/nunit.engine.api/IExtensionService.cs
+++ b/src/NUnitEngine/nunit.engine.api/IExtensionService.cs
@@ -31,7 +31,7 @@ public interface IExtensionService
///
/// Get an ExtensionPoint based on its unique identifying path.
///
- IExtensionPoint GetExtensionPoint(string path);
+ IExtensionPoint? GetExtensionPoint(string path);
///
/// Get an enumeration of ExtensionNodes based on their identifying path.
diff --git a/src/NUnitEngine/nunit.engine.api/IResultService.cs b/src/NUnitEngine/nunit.engine.api/IResultService.cs
index 2a04a53a3..f511b7bee 100644
--- a/src/NUnitEngine/nunit.engine.api/IResultService.cs
+++ b/src/NUnitEngine/nunit.engine.api/IResultService.cs
@@ -22,6 +22,6 @@ public interface IResultService
/// The name of the format to be used
/// A set of arguments to be used in constructing the writer or null if non arguments are needed
/// An IResultWriter
- IResultWriter GetResultWriter(string format, object[] args);
+ IResultWriter GetResultWriter(string format, params object?[]? args);
}
}
diff --git a/src/NUnitEngine/nunit.engine.api/IRuntimeFramework.cs b/src/NUnitEngine/nunit.engine.api/IRuntimeFramework.cs
index ce41f6b92..ddbd4839a 100644
--- a/src/NUnitEngine/nunit.engine.api/IRuntimeFramework.cs
+++ b/src/NUnitEngine/nunit.engine.api/IRuntimeFramework.cs
@@ -30,6 +30,6 @@ public interface IRuntimeFramework
/// or null if there is no profile. Currently. the only defined
/// values are Full and Client.
///
- string Profile { get; }
+ string? Profile { get; }
}
}
diff --git a/src/NUnitEngine/nunit.engine.api/IRuntimeFrameworkService.cs b/src/NUnitEngine/nunit.engine.api/IRuntimeFrameworkService.cs
index 4f5ffb6de..788a4f5ee 100644
--- a/src/NUnitEngine/nunit.engine.api/IRuntimeFrameworkService.cs
+++ b/src/NUnitEngine/nunit.engine.api/IRuntimeFrameworkService.cs
@@ -15,7 +15,7 @@ public interface IRuntimeFrameworkService
/// Gets a RuntimeFramework instance representing the runtime under
/// which the code is currently running.
///
- IRuntimeFramework CurrentFramework { get; }
+ IRuntimeFramework? CurrentFramework { get; }
///
/// Returns true if the runtime framework represented by
diff --git a/src/NUnitEngine/nunit.engine.api/IService.cs b/src/NUnitEngine/nunit.engine.api/IService.cs
index 979308c7a..f4dc069ad 100644
--- a/src/NUnitEngine/nunit.engine.api/IService.cs
+++ b/src/NUnitEngine/nunit.engine.api/IService.cs
@@ -1,6 +1,7 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
using System;
+using System.Diagnostics.CodeAnalysis;
using NUnit.Engine.Extensibility;
namespace NUnit.Engine
@@ -30,7 +31,8 @@ public interface IService
///
/// The ServiceContext
///
- IServiceLocator ServiceContext { get; set; }
+ [DisallowNull]
+ IServiceLocator? ServiceContext { get; set; }
///
/// Gets the ServiceStatus of this service
diff --git a/src/NUnitEngine/nunit.engine.api/TestEngineActivator.cs b/src/NUnitEngine/nunit.engine.api/TestEngineActivator.cs
index ccfebd961..c4b0481ba 100644
--- a/src/NUnitEngine/nunit.engine.api/TestEngineActivator.cs
+++ b/src/NUnitEngine/nunit.engine.api/TestEngineActivator.cs
@@ -24,8 +24,8 @@ public static ITestEngine CreateInstance()
var directoryName = Path.GetDirectoryName(apiLocation);
var enginePath = directoryName == null ? DEFAULT_ENGINE_ASSEMBLY : Path.Combine(directoryName, DEFAULT_ENGINE_ASSEMBLY);
var assembly = Assembly.LoadFrom(enginePath);
- var engineType = assembly.GetType(DEFAULT_ENGINE_TYPE);
- return Activator.CreateInstance(engineType) as ITestEngine;
+ var engineType = assembly.GetType(DEFAULT_ENGINE_TYPE, throwOnError: true)!;
+ return (ITestEngine)Activator.CreateInstance(engineType)!;
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.api/TestFilter.cs b/src/NUnitEngine/nunit.engine.api/TestFilter.cs
index 7550a310a..21126fdd3 100644
--- a/src/NUnitEngine/nunit.engine.api/TestFilter.cs
+++ b/src/NUnitEngine/nunit.engine.api/TestFilter.cs
@@ -31,6 +31,6 @@ public TestFilter(string xmlText)
///
/// Gets the XML representation of this filter as a string.
///
- public string Text { get; private set; }
+ public string Text { get; }
}
}
diff --git a/src/NUnitEngine/nunit.engine.api/TestPackage.cs b/src/NUnitEngine/nunit.engine.api/TestPackage.cs
index bba36c05e..0f85d1d60 100644
--- a/src/NUnitEngine/nunit.engine.api/TestPackage.cs
+++ b/src/NUnitEngine/nunit.engine.api/TestPackage.cs
@@ -76,7 +76,7 @@ private static string GetNextID()
///
/// Gets the name of the package
///
- public string Name
+ public string? Name
{
get { return FullName == null ? null : Path.GetFileName(FullName); }
}
@@ -85,7 +85,7 @@ public string Name
/// Gets the path to the file containing tests. It may be
/// an assembly or a recognized project type.
///
- public string FullName { get; private set; }
+ public string? FullName { get; private init; }
///
/// Gets the list of SubPackages contained in this package
@@ -149,8 +149,8 @@ public void AddSetting(string name, object value)
///
public T GetSetting(string name, T defaultSetting)
{
- return Settings.ContainsKey(name)
- ? (T)Settings[name]
+ return (Settings.TryGetValue(name, out object? setting) && setting is not null)
+ ? (T)setting
: defaultSetting;
}
}
diff --git a/src/NUnitEngine/nunit.engine.api/nunit.engine.api.csproj b/src/NUnitEngine/nunit.engine.api/nunit.engine.api.csproj
index e11144055..007606c92 100644
--- a/src/NUnitEngine/nunit.engine.api/nunit.engine.api.csproj
+++ b/src/NUnitEngine/nunit.engine.api/nunit.engine.api.csproj
@@ -3,14 +3,16 @@
NUnit.Engine
net462;netstandard2.0
- ../../../bin/$(Configuration)
+ $(MSBuildThisFileDirectory)/../../../bin/$(Configuration)
true
- ..\..\nunit.snk
+ $(MSBuildThisFileDirectory)/../../nunit.snk
true
portable
true
+
+
NUnit Engine
NUnit Engine API ($(TargetFramework))
@@ -19,8 +21,4 @@
3.99.0.0
-
-
-
-
diff --git a/src/NUnitEngine/nunit.engine.core.tests/AppContextTest.cs b/src/NUnitEngine/nunit.engine.core.tests/AppContextTest.cs
index 40fa60e63..4b00b250d 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/AppContextTest.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/AppContextTest.cs
@@ -11,7 +11,7 @@ public class AppContextTest
[Test]
public void VerifyBasePath()
{
- var expectedPath = Path.GetDirectoryName(GetType().Assembly.Location);
+ var expectedPath = Path.GetDirectoryName(GetType().Assembly.Location)!;
#if NETCORAPP
Assert.That(AppContext.GetData("APP_CONTEXT_BASE_DIRECTORY"), Is.EqualTo(expectedPath));
#endif
diff --git a/src/NUnitEngine/nunit.engine.core.tests/AsyncTestEngineResultTests.cs b/src/NUnitEngine/nunit.engine.core.tests/AsyncTestEngineResultTests.cs
index 69b15d07e..a5bf60705 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/AsyncTestEngineResultTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/AsyncTestEngineResultTests.cs
@@ -19,14 +19,13 @@ public void SetUp()
[Test]
public void Result_ThrowsIfNotSet()
{
- XmlNode result = null;
- Assert.Throws(() => result = _asyncResult.EngineResult.Xml);
+ Assert.Throws(() => _ = _asyncResult.EngineResult.Xml);
}
[Test]
public void SetResult_ThrowsIfNull()
{
- Assert.Throws(() => _asyncResult.SetResult(null));
+ Assert.Throws(() => _asyncResult.SetResult(null!));
}
[Test]
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Drivers/NUnit3FrameworkDriverTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Drivers/NUnit3FrameworkDriverTests.cs
index 388bb0941..43d6b0b42 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Drivers/NUnit3FrameworkDriverTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Drivers/NUnit3FrameworkDriverTests.cs
@@ -40,7 +40,7 @@ public void Load_GoodFile_ReturnsRunnableSuite()
Assert.That(result.GetAttribute("type"), Is.EqualTo("Assembly"));
Assert.That(result.GetAttribute("runstate"), Is.EqualTo("Runnable"));
Assert.That(result.GetAttribute("testcasecount"), Is.EqualTo(MockAssembly.Tests.ToString()));
- Assert.That(result.SelectNodes("test-suite").Count, Is.EqualTo(0), "Load result should not have child tests");
+ Assert.That(result.SelectNodes("test-suite")?.Count, Is.EqualTo(0), "Load result should not have child tests");
}
[Test]
@@ -53,7 +53,7 @@ public void Explore_AfterLoad_ReturnsRunnableSuite()
Assert.That(result.GetAttribute("type"), Is.EqualTo("Assembly"));
Assert.That(result.GetAttribute("runstate"), Is.EqualTo("Runnable"));
Assert.That(result.GetAttribute("testcasecount"), Is.EqualTo(MockAssembly.Tests.ToString()));
- Assert.That(result.SelectNodes("test-suite").Count, Is.GreaterThan(0), "Explore result should have child tests");
+ Assert.That(result.SelectNodes("test-suite")?.Count, Is.GreaterThan(0), "Explore result should have child tests");
}
[Test]
@@ -98,7 +98,7 @@ public void RunTestsAction_AfterLoad_ReturnsRunnableSuite()
Assert.That(result.GetAttribute("failed"), Is.EqualTo(MockAssembly.Failed.ToString()));
Assert.That(result.GetAttribute("skipped"), Is.EqualTo(MockAssembly.Skipped.ToString()));
Assert.That(result.GetAttribute("inconclusive"), Is.EqualTo(MockAssembly.Inconclusive.ToString()));
- Assert.That(result.SelectNodes("test-suite").Count, Is.GreaterThan(0), "Explore result should have child tests");
+ Assert.That(result.SelectNodes("test-suite")?.Count, Is.GreaterThan(0), "Explore result should have child tests");
}
[Test]
@@ -119,17 +119,11 @@ public void RunTestsAction_WithInvalidFilterElement_ThrowsNUnitEngineException()
Assert.That(ex, Is.TypeOf());
}
- private static string GetSkipReason(XmlNode result)
- {
- var propNode = result.SelectSingleNode(string.Format("properties/property[@name='{0}']", PropertyNames.SkipReason));
- return propNode == null ? null : propNode.GetAttribute("value");
- }
-
private class CallbackEventHandler : System.Web.UI.ICallbackEventHandler
{
- private string _result;
+ private string? _result;
- public string GetCallbackResult()
+ public string? GetCallbackResult()
{
return _result;
}
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Drivers/NotRunnableFrameworkDriverTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Drivers/NotRunnableFrameworkDriverTests.cs
index f6173b558..0119e74ed 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Drivers/NotRunnableFrameworkDriverTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Drivers/NotRunnableFrameworkDriverTests.cs
@@ -17,10 +17,10 @@ public abstract class NotRunnableFrameworkDriverTests
private const string DRIVER_ID = "99";
private const string EXPECTED_ID = "99-1";
- protected string _expectedRunState;
- protected string _expectedReason;
- protected string _expectedResult;
- protected string _expectedLabel;
+ protected string? _expectedRunState;
+ protected string? _expectedReason;
+ protected string? _expectedResult;
+ protected string? _expectedLabel;
[TestCase("junk.dll", "Assembly")]
[TestCase("junk.exe", "Assembly")]
@@ -38,7 +38,7 @@ public void Load(string filePath, string expectedType)
Assert.That(result.GetAttribute("runstate"), Is.EqualTo(_expectedRunState));
Assert.That(result.GetAttribute("testcasecount"), Is.EqualTo("0"));
Assert.That(GetSkipReason(result), Is.EqualTo(_expectedReason));
- Assert.That(result.SelectNodes("test-suite").Count, Is.EqualTo(0), "Load result should not have child tests");
+ Assert.That(result.SelectNodes("test-suite")?.Count, Is.EqualTo(0), "Load result should not have child tests");
}
[TestCase("junk.dll", "Assembly")]
@@ -57,7 +57,7 @@ public void Explore(string filePath, string expectedType)
Assert.That(result.GetAttribute("runstate"), Is.EqualTo(_expectedRunState));
Assert.That(result.GetAttribute("testcasecount"), Is.EqualTo("0"));
Assert.That(GetSkipReason(result), Is.EqualTo(_expectedReason));
- Assert.That(result.SelectNodes("test-suite").Count, Is.EqualTo(0), "Result should not have child tests");
+ Assert.That(result.SelectNodes("test-suite")?.Count, Is.EqualTo(0), "Result should not have child tests");
}
[TestCase("junk.dll")]
@@ -84,10 +84,10 @@ public void Run(string filePath, string expectedType)
Assert.That(result.GetAttribute("runstate"), Is.EqualTo(_expectedRunState));
Assert.That(result.GetAttribute("testcasecount"), Is.EqualTo("0"));
Assert.That(GetSkipReason(result), Is.EqualTo(_expectedReason));
- Assert.That(result.SelectNodes("test-suite").Count, Is.EqualTo(0), "Load result should not have child tests");
+ Assert.That(result.SelectNodes("test-suite")?.Count, Is.EqualTo(0), "Load result should not have child tests");
Assert.That(result.GetAttribute("result"), Is.EqualTo(_expectedResult));
Assert.That(result.GetAttribute("label"), Is.EqualTo(_expectedLabel));
- Assert.That(result.SelectSingleNode("reason/message").InnerText, Is.EqualTo(_expectedReason));
+ Assert.That(result.SelectSingleNode("reason/message")?.InnerText, Is.EqualTo(_expectedReason));
}
protected abstract IFrameworkDriver CreateDriver(string filePath);
@@ -99,7 +99,7 @@ private IFrameworkDriver GetDriver(string filePath)
return driver;
}
- private static string GetSkipReason(XmlNode result)
+ private static string? GetSkipReason(XmlNode result)
{
var propNode = result.SelectSingleNode(string.Format("properties/property[@name='{0}']", PropertyNames.SkipReason));
return propNode == null ? null : propNode.GetAttribute("value");
@@ -126,7 +126,7 @@ public InvalidAssemblyFrameworkDriverTests()
protected override IFrameworkDriver CreateDriver(string filePath)
{
- return new InvalidAssemblyFrameworkDriver(filePath, _expectedReason);
+ return new InvalidAssemblyFrameworkDriver(filePath, _expectedReason ?? "Not Specified");
}
}
diff --git a/src/NUnitEngine/nunit.engine.core.tests/DummyExtensions.cs b/src/NUnitEngine/nunit.engine.core.tests/DummyExtensions.cs
index 21fd479cb..5d549efad 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/DummyExtensions.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/DummyExtensions.cs
@@ -135,7 +135,7 @@ public string Load(string testAssemblyPath, IDictionary settings
throw new NotImplementedException();
}
- public string Run(ITestEventListener listener, string filter)
+ public string Run(ITestEventListener? listener, string filter)
{
throw new NotImplementedException();
}
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Extensibility/ExtensionAssemblyTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Extensibility/ExtensionAssemblyTests.cs
index 39e38a7e5..0f3c03829 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Extensibility/ExtensionAssemblyTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Extensibility/ExtensionAssemblyTests.cs
@@ -12,8 +12,8 @@ public class ExtensionAssemblyTests
{
private static readonly Assembly THIS_ASSEMBLY = Assembly.GetExecutingAssembly();
private static readonly string THIS_ASSEMBLY_PATH = THIS_ASSEMBLY.Location;
- private static readonly string THIS_ASSEMBLY_NAME = THIS_ASSEMBLY.GetName().Name;
- private static readonly Version THIS_ASSEMBLY_VERSION = THIS_ASSEMBLY.GetName().Version;
+ private static readonly string? THIS_ASSEMBLY_NAME = THIS_ASSEMBLY.GetName().Name;
+ private static readonly Version? THIS_ASSEMBLY_VERSION = THIS_ASSEMBLY.GetName().Version;
private ExtensionAssembly _ea;
@@ -23,6 +23,12 @@ public void CreateExtensionAssemblies()
_ea = new ExtensionAssembly(THIS_ASSEMBLY_PATH, false);
}
+ [OneTimeTearDown]
+ public void DisposeExtensionAssemblies()
+ {
+ _ea.Dispose();
+ }
+
[Test]
public void AssemblyName()
{
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Extensibility/ExtensionSelectorTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Extensibility/ExtensionSelectorTests.cs
index 97effeaea..a68154fc4 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Extensibility/ExtensionSelectorTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Extensibility/ExtensionSelectorTests.cs
@@ -105,8 +105,8 @@ public void IsBetterVersionOfPrefersNoChangeIfFromWildcard()
}
private static IExtensionAssembly MockExtension(string assemblyName = "ExtensionSelectorTestsExtension",
- Version assemblyVersion = null,
- Version targetFramework = null,
+ Version? assemblyVersion = null,
+ Version? targetFramework = null,
bool fromWildcard = false)
{
var sub = Substitute.For();
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Helpers/On.cs b/src/NUnitEngine/nunit.engine.core.tests/Helpers/On.cs
index 6e0af761f..212d93aad 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Helpers/On.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Helpers/On.cs
@@ -11,7 +11,7 @@ public static class On
private sealed class OnDisposeAction : IDisposable
{
- private Action action;
+ private Action? action;
public OnDisposeAction(Action action)
{
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/AddinsFileTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/AddinsFileTests.cs
index 25d4363b1..05bbfa581 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/AddinsFileTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/AddinsFileTests.cs
@@ -19,7 +19,7 @@ public class AddinsFileTests
[Test]
public void Read_IFile_Null()
{
- Assert.That(() => AddinsFile.Read((IFile)null), Throws.ArgumentNullException);
+ Assert.That(() => AddinsFile.Read((IFile)null!), Throws.ArgumentNullException);
}
[Test]
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/AssemblyHelperTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/AssemblyHelperTests.cs
index e13a2cf4b..8afbf20bb 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/AssemblyHelperTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/AssemblyHelperTests.cs
@@ -22,6 +22,7 @@ public void GetPathForAssembly()
Assert.That(File.Exists(path));
}
+#if NETFRAMEWORK
// The following tests are only useful to the extent that the test cases
// match what will actually be provided to the method in production.
// As currently used, NUnit's codebase can only use the file: schema,
@@ -54,5 +55,6 @@ public void GetAssemblyPathFromCodeBase(string uri, string expectedPath)
string localPath = AssemblyHelper.GetAssemblyPathFromCodeBase(uri);
Assert.That(localPath, Is.SamePath(expectedPath));
}
+#endif
}
}
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/Backports/PathTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/Backports/PathTests.cs
index 1606e57f4..94facf7f4 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/Backports/PathTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/Backports/PathTests.cs
@@ -54,7 +54,7 @@ public bool IsPathFullyQualified_NonWindows(string path)
[Test]
public void IsPathFullyQualified_PathIsNull()
{
- Assert.That(() => Path.IsPathFullyQualified(null), Throws.ArgumentNullException);
+ Assert.That(() => Path.IsPathFullyQualified(null!), Throws.ArgumentNullException);
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/DirectoryFinderTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/DirectoryFinderTests.cs
index 17c9d7f56..0e77b99c4 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/DirectoryFinderTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/DirectoryFinderTests.cs
@@ -110,7 +110,7 @@ public void GetDirectories_Asterisk_Tools()
var actual = result.Select(x => x.FullName);
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories("*", SIO.SearchOption.TopDirectoryOnly);
this.GetFakeDirectory("tools", "frobuscator").DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
this.GetFakeDirectory("tools", "metamorphosator").DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
@@ -127,7 +127,7 @@ public void GetDirectories_Asterisk_Metamorphosator()
var actual = result.Select(x => x.FullName);
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories(Arg.Any(), Arg.Any());
this.GetFakeDirectory("tools", "frobuscator").DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
this.GetFakeDirectory("tools", "metamorphosator", "addins").DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
@@ -145,7 +145,7 @@ public void GetDirectories_Greedy_Tools()
var actual = result.Select(x => x.FullName);
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories("*", SIO.SearchOption.AllDirectories);
this.GetFakeDirectory("tools", "frobuscator").DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
this.GetFakeDirectory("tools", "metamorphosator").DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
@@ -172,7 +172,7 @@ public void GetDirectories_Greedy_Metamorphosator()
var actual = result.Select(x => x.FullName);
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories("*", SIO.SearchOption.AllDirectories);
this.GetFakeDirectory("tools", "frobuscator").DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
}
@@ -188,7 +188,7 @@ public void GetDirectories_WordWithWildcard_NoMatch(string pattern)
var result = finder.GetDirectories(baseDir, pattern);
Assert.That(result, Is.Empty);
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories(pattern, SIO.SearchOption.TopDirectoryOnly);
}
@@ -208,7 +208,7 @@ public void GetDirectories_WordWithWildcard_OneMatch(string pattern)
var actual = result.Select(x => x.FullName);
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories(pattern, SIO.SearchOption.TopDirectoryOnly);
}
@@ -226,7 +226,7 @@ public void GetDirectories_WordWithWildcard_MultipleMatches(string pattern)
var actual = result.Select(x => x.FullName);
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories(pattern, SIO.SearchOption.TopDirectoryOnly);
}
@@ -308,7 +308,7 @@ public void GetDirectories_MultipleComponents_MultipleMatches_Asterisk(string pa
var actual = result.Select(x => x.FullName);
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
testsDir.Received().GetDirectories("v*", SIO.SearchOption.TopDirectoryOnly);
}
@@ -332,7 +332,7 @@ public void GetDirectories_MultipleComponents_MultipleMatches_QuestionMark(strin
var actual = result.Select(x => x.FullName);
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
testsDir.Received().GetDirectories("v?", SIO.SearchOption.TopDirectoryOnly);
}
@@ -347,7 +347,7 @@ public void GetDirectories_MultipleComponents_AllDirectories(string pattern)
var actual = finder.GetDirectories(baseDir, pattern);
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories("*", SIO.SearchOption.AllDirectories);
foreach (var dir in this.fakedDirectories.Values.Where(x => x != baseDir))
{
@@ -376,7 +376,7 @@ public void GetDirectories_GreedyThenWordThenGreedy()
var actual = finder.GetDirectories(baseDir, "**/tests/**");
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories("*", SIO.SearchOption.AllDirectories);
this.GetFakeDirectory("tools", "frobuscator").Received().GetDirectories("tests", SIO.SearchOption.TopDirectoryOnly);
this.GetFakeDirectory("tools", "metamorphosator").Received().GetDirectories("tests", SIO.SearchOption.TopDirectoryOnly);
@@ -397,7 +397,7 @@ public void GetDirectories_WordWithAsteriskThenGreedyThenWord()
var actual = finder.GetDirectories(baseDir, "meta*/**/v1");
Assert.That(actual, Is.EquivalentTo(expected));
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
baseDir.Received().GetDirectories("meta*", SIO.SearchOption.TopDirectoryOnly);
this.GetFakeDirectory("tools", "frobuscator").DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
this.GetFakeDirectory("tools", "metamorphosator").Received().GetDirectories("*", SIO.SearchOption.AllDirectories);
@@ -415,7 +415,7 @@ public void GetDirectories_Parent()
Assert.That(actual, Is.EquivalentTo(expected));
baseDir.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
}
[Test]
@@ -431,8 +431,8 @@ public void GetDirectories_ParentThenParentThenWordThenWord()
Assert.That(actual, Is.EquivalentTo(expected));
baseDir.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
- baseDir.Parent.Parent.Received().GetDirectories("metamorphosator", SIO.SearchOption.TopDirectoryOnly);
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.Parent!.Received().GetDirectories("metamorphosator", SIO.SearchOption.TopDirectoryOnly);
this.GetFakeDirectory("tools", "metamorphosator").Received().GetDirectories("addins", SIO.SearchOption.TopDirectoryOnly);
}
@@ -441,7 +441,7 @@ public void GetDirectories_StartDirectoryIsNull()
{
var finder = new DirectoryFinder(Substitute.For());
- Assert.That(() => finder.GetDirectories((IDirectory)null, "notused"), Throws.ArgumentNullException.With.Message.Contains(" startDirectory "));
+ Assert.That(() => finder.GetDirectories((IDirectory)null!, "notused"), Throws.ArgumentNullException.With.Message.Contains(" startDirectory "));
}
[Test]
@@ -449,7 +449,7 @@ public void GetDirectories_PatternIsNull()
{
var finder = new DirectoryFinder(Substitute.For());
- Assert.That(() => finder.GetDirectories(Substitute.For(), null), Throws.ArgumentNullException.With.Message.Contains(" pattern "));
+ Assert.That(() => finder.GetDirectories(Substitute.For(), null!), Throws.ArgumentNullException.With.Message.Contains(" pattern "));
}
[Test]
@@ -460,7 +460,7 @@ public void GetDirectories_PatternIsEmpty()
var directories = sut.GetDirectories(directory, string.Empty);
- Assert.That(directories, Has.Count.EqualTo(1));
+ Assert.That(directories.Count(), Is.EqualTo(1));
Assert.That(directories.First(), Is.EqualTo(directory));
}
@@ -478,7 +478,7 @@ public void GetFiles_WordWithWildcard(string pattern)
Assert.That(actual, Is.EquivalentTo(expected));
baseDir.Received().GetFiles(pattern);
- baseDir.Parent.DidNotReceive().GetFiles(Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetFiles(Arg.Any());
}
[TestCase("*/tests.*.dll")]
@@ -500,7 +500,7 @@ public void GetFiles_AsteriskThenWordWithWildcard(string pattern)
Assert.That(actual, Is.EquivalentTo(expected));
abcDir.Received().GetFiles(filePattern);
defDir.Received().GetFiles(filePattern);
- baseDir.Parent.DidNotReceive().GetFiles(Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetFiles(Arg.Any());
baseDir.DidNotReceive().GetFiles(Arg.Any());
abcDir.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
defDir.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
@@ -539,7 +539,7 @@ public void GetFiles_GreedyThenWordWithWildcard(string pattern)
{
dir.Received().GetFiles(filePattern);
}
- baseDir.Parent.DidNotReceive().GetFiles(Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetFiles(Arg.Any());
abcDir.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
defDir.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
v1Dir.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
@@ -585,8 +585,8 @@ public void GetFiles_CurrentDirThenAsterisk()
Assert.That(actual, Is.EquivalentTo(expected));
baseDir.Received().GetFiles("*");
- baseDir.Parent.DidNotReceive().GetFiles(Arg.Any());
- baseDir.Parent.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetFiles(Arg.Any());
+ baseDir.Parent!.DidNotReceive().GetDirectories(Arg.Any(), Arg.Any());
}
[Test]
@@ -594,7 +594,7 @@ public void GetFiles_StartDirectoryIsNull()
{
var finder = new DirectoryFinder(Substitute.For());
- Assert.That(() => finder.GetFiles((IDirectory)null, "notused"), Throws.ArgumentNullException.With.Message.Contains(" startDirectory "));
+ Assert.That(() => finder.GetFiles((IDirectory)null!, "notused"), Throws.ArgumentNullException.With.Message.Contains(" startDirectory "));
}
[Test]
@@ -602,7 +602,7 @@ public void GetFiles_PatternIsNull()
{
var finder = new DirectoryFinder(Substitute.For());
- Assert.That(() => finder.GetDirectories(Substitute.For(), null), Throws.ArgumentNullException.With.Message.Contains(" pattern "));
+ Assert.That(() => finder.GetDirectories(Substitute.For(), null!), Throws.ArgumentNullException.With.Message.Contains(" pattern "));
}
[Test]
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/DirectoryTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/DirectoryTests.cs
index 2fb12c939..200d86e15 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/DirectoryTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/DirectoryTests.cs
@@ -14,18 +14,18 @@ public sealed class DirectoryTests
public void Init()
{
var path = SIO.Directory.GetCurrentDirectory();
- var parent = new SIO.DirectoryInfo(path).Parent.FullName;
+ var parent = new SIO.DirectoryInfo(path).Parent!.FullName;
var directory = new Directory(path);
Assert.That(path, Is.EqualTo(directory.FullName));
- Assert.That(parent, Is.EqualTo(directory.Parent.FullName));
+ Assert.That(parent, Is.EqualTo(directory.Parent!.FullName));
}
[Test]
public void Init_PathIsNull()
{
- Assert.That(() => new Directory(null), Throws.ArgumentNullException);
+ Assert.That(() => new Directory(null!), Throws.ArgumentNullException);
}
[Test]
@@ -49,12 +49,12 @@ public void Init_EmptyPath()
public void Init_TrailingDirectorySeparator()
{
var path = SIO.Directory.GetCurrentDirectory() + SIO.Path.DirectorySeparatorChar;
- var parent = new SIO.DirectoryInfo(SIO.Directory.GetCurrentDirectory()).Parent.FullName;
+ var parent = new SIO.DirectoryInfo(SIO.Directory.GetCurrentDirectory()).Parent!.FullName;
var directory = new Directory(path);
Assert.That(path, Is.EqualTo(directory.FullName));
- Assert.That(parent, Is.EqualTo(directory.Parent.FullName));
+ Assert.That(parent, Is.EqualTo(directory.Parent!.FullName));
}
// Skip this test on non-Windows systems since System.IO.DirectoryInfo appends '\\server\share' to the current working-directory, making this test useless.
@@ -136,7 +136,7 @@ public void GetFiles_SearchPatternIsNull()
var path = SIO.Directory.GetCurrentDirectory();
var directory = new Directory(path);
- Assert.That(() => directory.GetFiles(null), Throws.ArgumentNullException);
+ Assert.That(() => directory.GetFiles(null!), Throws.ArgumentNullException);
}
[Test]
@@ -158,7 +158,7 @@ public void GetDirectories_SearchPatternIsNull()
var path = SIO.Directory.GetCurrentDirectory();
var directory = new Directory(path);
- Assert.That(() => directory.GetDirectories(null, SIO.SearchOption.TopDirectoryOnly), Throws.ArgumentNullException);
+ Assert.That(() => directory.GetDirectories(null!, SIO.SearchOption.TopDirectoryOnly), Throws.ArgumentNullException);
}
[Test]
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/FileSystemTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/FileSystemTests.cs
index 4b48331ce..5ad1c2ee4 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/FileSystemTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/FileSystemTests.cs
@@ -98,7 +98,7 @@ public void ExistsFileIsNull()
{
var fileSystem = new FileSystem();
- Assert.That(() => fileSystem.Exists((IFile)null), Throws.ArgumentNullException);
+ Assert.That(() => fileSystem.Exists((IFile)null!), Throws.ArgumentNullException);
}
[Test]
@@ -135,12 +135,12 @@ public void Exists_DirectoryIsNull()
{
var fileSystem = new FileSystem();
- Assert.That(() => fileSystem.Exists((IDirectory)null), Throws.ArgumentNullException);
+ Assert.That(() => fileSystem.Exists((IDirectory)null!), Throws.ArgumentNullException);
}
private string GetTestFileLocation()
{
- return Assembly.GetAssembly(typeof(FileTests)).Location;
+ return Assembly.GetAssembly(typeof(FileTests))!.Location;
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/FileTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/FileTests.cs
index 541aeb3a2..46e5d5606 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/FileTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/FileSystemAccess/Default/FileTests.cs
@@ -26,7 +26,7 @@ public void Init()
[Test]
public void Init_PathIsNull()
{
- Assert.That(() => new File(null), Throws.ArgumentNullException);
+ Assert.That(() => new File(null!), Throws.ArgumentNullException);
}
[Test]
@@ -89,7 +89,7 @@ public void Init_PathIsDirectory()
private string GetTestFileLocation()
{
- return Assembly.GetAssembly(typeof(FileTests)).Location;
+ return Assembly.GetAssembly(typeof(FileTests))!.Location;
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/PathUtilTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/PathUtilTests.cs
index 81389009f..127bcc152 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/PathUtilTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/PathUtilTests.cs
@@ -55,13 +55,13 @@ public bool IsFullyQualifiedUnixPath(string path)
[Test]
public void IsFullyQualifiedUnixPath_PathIsNull()
{
- Assert.That(() => PathUtils.IsFullyQualifiedUnixPath(null), Throws.ArgumentNullException);
+ Assert.That(() => PathUtils.IsFullyQualifiedUnixPath(null!), Throws.ArgumentNullException);
}
[Test]
public void IsFullyQualifiedWindowsPath_PathIsNull()
{
- Assert.That(() => PathUtils.IsFullyQualifiedWindowsPath(null), Throws.ArgumentNullException);
+ Assert.That(() => PathUtils.IsFullyQualifiedWindowsPath(null!), Throws.ArgumentNullException);
}
}
@@ -81,14 +81,12 @@ internal class PathAssert : NUnit.Framework.Assert
{
public static void SamePathOrUnder( string path1, string path2 )
{
- string msg = "\r\n\texpected: Same path or under <{0}>\r\n\t but was: <{1}>";
- Assert.That(PathUtils.SamePathOrUnder( path1, path2 ), Is.True, msg, path1, path2);
+ Assert.That(PathUtils.SamePathOrUnder( path1, path2 ), Is.True, $"\r\n\texpected: Same path or under <{path1}>\r\n\t but was: <{path2}>");
}
public static void NotSamePathOrUnder( string path1, string path2 )
{
- string msg = "\r\n\texpected: Not same path or under <{0}>\r\n\t but was: <{1}>";
- Assert.That(PathUtils.SamePathOrUnder( path1, path2 ), Is.False, msg, path1, path2);
+ Assert.That(PathUtils.SamePathOrUnder( path1, path2 ), Is.False, $"\r\n\texpected: Not same path or under <{path1}>\r\n\t but was: <{path2}>");
}
}
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/ProcessUtilsTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/ProcessUtilsTests.cs
index 44b508f96..fefb9c53c 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/ProcessUtilsTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/ProcessUtilsTests.cs
@@ -29,7 +29,7 @@ namespace NUnit.Engine.Tests.Internal
{
public static class ProcessUtilsTests
{
- private static string EscapeProcessArgument(string value, bool alwaysQuote = false)
+ private static string EscapeProcessArgument(string? value, bool alwaysQuote = false)
{
var builder = new StringBuilder();
ProcessUtils.EscapeProcessArgument(builder, value, alwaysQuote);
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Internal/TcpChannelUtilsTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Internal/TcpChannelUtilsTests.cs
index 79a3c2154..3468c6073 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Internal/TcpChannelUtilsTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Internal/TcpChannelUtilsTests.cs
@@ -18,6 +18,7 @@ public class TcpChannelUtilsTests
public void GetTcpChannelReturnsSameChannelForSameNameDifferentPort()
{
var first = TcpChannelUtils.GetTcpChannel("test", 1234);
+ Assert.That(first, Is.Not.Null);
using (CleanUpOnDispose(first))
{
var second = TcpChannelUtils.GetTcpChannel("test", 4321);
@@ -29,6 +30,7 @@ public void GetTcpChannelReturnsSameChannelForSameNameDifferentPort()
public void GetTcpChannelReturnsSameChannelForSameNameUnspecifiedPorts()
{
var first = TcpChannelUtils.GetTcpChannel("test", 0);
+ Assert.That(first, Is.Not.Null);
using (CleanUpOnDispose(first))
{
var second = TcpChannelUtils.GetTcpChannel("test", 0);
@@ -40,6 +42,7 @@ public void GetTcpChannelReturnsSameChannelForSameNameUnspecifiedPorts()
public void GetTcpChannelReturnsChannelWithCorrectName()
{
var channel = TcpChannelUtils.GetTcpChannel("test", 1234);
+ Assert.That(channel, Is.Not.Null);
using (CleanUpOnDispose(channel))
{
Assert.That(channel, HasChannelName().EqualTo("test"));
@@ -50,6 +53,7 @@ public void GetTcpChannelReturnsChannelWithCorrectName()
public void GetTcpChannelReturnsChannelWithCorrectNameForUnspecifiedPort()
{
var channel = TcpChannelUtils.GetTcpChannel("test", 0);
+ Assert.That(channel, Is.Not.Null);
using (CleanUpOnDispose(channel))
{
Assert.That(channel, HasChannelName().EqualTo("test"));
@@ -60,6 +64,7 @@ public void GetTcpChannelReturnsChannelWithCorrectNameForUnspecifiedPort()
public void GetTcpChannelReturnsChannelWithCorrectURI()
{
var channel = TcpChannelUtils.GetTcpChannel("test", 1234);
+ Assert.That(channel, Is.Not.Null);
using (CleanUpOnDispose(channel))
{
Assert.That(channel, HasChannelUris().EqualTo(new[] { "tcp://127.0.0.1:1234" }));
diff --git a/src/NUnitEngine/nunit.engine.core.tests/ResultHelperTests.cs b/src/NUnitEngine/nunit.engine.core.tests/ResultHelperTests.cs
index 4f18da030..d5636ee81 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/ResultHelperTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/ResultHelperTests.cs
@@ -1,11 +1,10 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
using System.Xml;
+using NUnit.Framework;
namespace NUnit.Engine.Internal
{
- using Framework;
-
public class ResultHelperTests
{
private const string resultText1 = "";
@@ -46,17 +45,18 @@ public void AggregateTestResult()
XmlNode combinedNode = combined.Xml;
Assert.That(combinedNode.Name, Is.EqualTo("test-run"));
- Assert.That(combinedNode.Attributes["id"].Value, Is.EqualTo("ID"));
- Assert.That(combinedNode.Attributes["name"].Value, Is.EqualTo("NAME"));
- Assert.That(combinedNode.Attributes["fullname"].Value, Is.EqualTo("FULLNAME"));
- Assert.That(combinedNode.Attributes["result"].Value, Is.EqualTo("Failed"));
- Assert.That(combinedNode.Attributes["total"].Value, Is.EqualTo("42"));
- Assert.That(combinedNode.Attributes["passed"].Value, Is.EqualTo("31"));
- Assert.That(combinedNode.Attributes["failed"].Value, Is.EqualTo("3"));
- Assert.That(combinedNode.Attributes["warnings"].Value, Is.EqualTo("1"));
- Assert.That(combinedNode.Attributes["inconclusive"].Value, Is.EqualTo("5"));
- Assert.That(combinedNode.Attributes["skipped"].Value, Is.EqualTo("2"));
- Assert.That(combinedNode.Attributes["asserts"].Value, Is.EqualTo("53"));
+ Assert.That(combinedNode.Attributes, Is.Not.Null);
+ Assert.That(combinedNode.Attributes["id"]?.Value, Is.EqualTo("ID"));
+ Assert.That(combinedNode.Attributes["name"]?.Value, Is.EqualTo("NAME"));
+ Assert.That(combinedNode.Attributes["fullname"]?.Value, Is.EqualTo("FULLNAME"));
+ Assert.That(combinedNode.Attributes["result"]?.Value, Is.EqualTo("Failed"));
+ Assert.That(combinedNode.Attributes["total"]?.Value, Is.EqualTo("42"));
+ Assert.That(combinedNode.Attributes["passed"]?.Value, Is.EqualTo("31"));
+ Assert.That(combinedNode.Attributes["failed"]?.Value, Is.EqualTo("3"));
+ Assert.That(combinedNode.Attributes["warnings"]?.Value, Is.EqualTo("1"));
+ Assert.That(combinedNode.Attributes["inconclusive"]?.Value, Is.EqualTo("5"));
+ Assert.That(combinedNode.Attributes["skipped"]?.Value, Is.EqualTo("2"));
+ Assert.That(combinedNode.Attributes["asserts"]?.Value, Is.EqualTo("53"));
}
[Test]
@@ -68,18 +68,19 @@ public void MergeAndAggregateTestResults()
XmlNode combinedNode = combined.Xml;
Assert.That(combinedNode.Name, Is.EqualTo("test-suite"));
- Assert.That(combinedNode.Attributes["type"].Value, Is.EqualTo("Project"));
- Assert.That(combinedNode.Attributes["id"].Value, Is.EqualTo("ID"));
- Assert.That(combinedNode.Attributes["name"].Value, Is.EqualTo("NAME"));
- Assert.That(combinedNode.Attributes["fullname"].Value, Is.EqualTo("FULLNAME"));
- Assert.That(combinedNode.Attributes["result"].Value, Is.EqualTo("Failed"));
- Assert.That(combinedNode.Attributes["total"].Value, Is.EqualTo("65"));
- Assert.That(combinedNode.Attributes["passed"].Value, Is.EqualTo("54"));
- Assert.That(combinedNode.Attributes["failed"].Value, Is.EqualTo("3"));
- Assert.That(combinedNode.Attributes["warnings"].Value, Is.EqualTo("1"));
- Assert.That(combinedNode.Attributes["inconclusive"].Value, Is.EqualTo("5"));
- Assert.That(combinedNode.Attributes["skipped"].Value, Is.EqualTo("2"));
- Assert.That(combinedNode.Attributes["asserts"].Value, Is.EqualTo("93"));
+ Assert.That(combinedNode.Attributes, Is.Not.Null);
+ Assert.That(combinedNode.Attributes["type"]?.Value, Is.EqualTo("Project"));
+ Assert.That(combinedNode.Attributes["id"]?.Value, Is.EqualTo("ID"));
+ Assert.That(combinedNode.Attributes["name"]?.Value, Is.EqualTo("NAME"));
+ Assert.That(combinedNode.Attributes["fullname"]?.Value, Is.EqualTo("FULLNAME"));
+ Assert.That(combinedNode.Attributes["result"]?.Value, Is.EqualTo("Failed"));
+ Assert.That(combinedNode.Attributes["total"]?.Value, Is.EqualTo("65"));
+ Assert.That(combinedNode.Attributes["passed"]?.Value, Is.EqualTo("54"));
+ Assert.That(combinedNode.Attributes["failed"]?.Value, Is.EqualTo("3"));
+ Assert.That(combinedNode.Attributes["warnings"]?.Value, Is.EqualTo("1"));
+ Assert.That(combinedNode.Attributes["inconclusive"]?.Value, Is.EqualTo("5"));
+ Assert.That(combinedNode.Attributes["skipped"]?.Value, Is.EqualTo("2"));
+ Assert.That(combinedNode.Attributes["asserts"]?.Value, Is.EqualTo("93"));
}
[Test]
@@ -88,17 +89,18 @@ public void AggregateXmlNodes()
XmlNode combined = ResultHelper.Aggregate("test-run", "ID", "NAME", "FULLNAME", twoNodes);
Assert.That(combined.Name, Is.EqualTo("test-run"));
- Assert.That(combined.Attributes["id"].Value, Is.EqualTo("ID"));
- Assert.That(combined.Attributes["name"].Value, Is.EqualTo("NAME"));
- Assert.That(combined.Attributes["fullname"].Value, Is.EqualTo("FULLNAME"));
- Assert.That(combined.Attributes["result"].Value, Is.EqualTo("Failed"));
- Assert.That(combined.Attributes["total"].Value, Is.EqualTo("65"));
- Assert.That(combined.Attributes["passed"].Value, Is.EqualTo("54"));
- Assert.That(combined.Attributes["failed"].Value, Is.EqualTo("3"));
- Assert.That(combined.Attributes["warnings"].Value, Is.EqualTo("1"));
- Assert.That(combined.Attributes["inconclusive"].Value, Is.EqualTo("5"));
- Assert.That(combined.Attributes["skipped"].Value, Is.EqualTo("2"));
- Assert.That(combined.Attributes["asserts"].Value, Is.EqualTo("93"));
+ Assert.That(combined.Attributes, Is.Not.Null);
+ Assert.That(combined.Attributes["id"]?.Value, Is.EqualTo("ID"));
+ Assert.That(combined.Attributes["name"]?.Value, Is.EqualTo("NAME"));
+ Assert.That(combined.Attributes["fullname"]?.Value, Is.EqualTo("FULLNAME"));
+ Assert.That(combined.Attributes["result"]?.Value, Is.EqualTo("Failed"));
+ Assert.That(combined.Attributes["total"]?.Value, Is.EqualTo("65"));
+ Assert.That(combined.Attributes["passed"]?.Value, Is.EqualTo("54"));
+ Assert.That(combined.Attributes["failed"]?.Value, Is.EqualTo("3"));
+ Assert.That(combined.Attributes["warnings"]?.Value, Is.EqualTo("1"));
+ Assert.That(combined.Attributes["inconclusive"]?.Value, Is.EqualTo("5"));
+ Assert.That(combined.Attributes["skipped"]?.Value, Is.EqualTo("2"));
+ Assert.That(combined.Attributes["asserts"]?.Value, Is.EqualTo("93"));
}
[TestCase("Skipped", "Skipped", "Skipped")]
@@ -126,7 +128,7 @@ public void Aggregate_CalculatesAggregateResultCorrectly(string firstResult, str
var secondEngineResult = new TestEngineResult(secondResultText);
var data = new XmlNode[]{ firstEngineResult.Xml, secondEngineResult.Xml };
XmlNode combined = ResultHelper.Aggregate("test-run", "ID", "NAME", "FULLNAME", data);
- Assert.That(combined.Attributes["result"].Value, Is.EqualTo(aggregateResult));
+ Assert.That(combined.Attributes?["result"]?.Value, Is.EqualTo(aggregateResult));
}
}
}
\ No newline at end of file
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Runners/DomainManagerStaticTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Runners/DomainManagerStaticTests.cs
index 595174aa7..3e03e2659 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Runners/DomainManagerStaticTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Runners/DomainManagerStaticTests.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Configuration;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using NUnit.Framework;
@@ -85,7 +86,7 @@ public static void CanReadConfigFile()
[TestCase("/path/to/mytest.dll", null, "/path/to/")]
[TestCase("/path/to/mytest.dll", "/path", "/path/")]
- public static void ApplicationBaseTests(string filePath, string appBase, string expected)
+ public static void ApplicationBaseTests(string filePath, string? appBase, string expected)
{
filePath = TestPath(filePath);
appBase = TestPath(appBase);
@@ -100,7 +101,7 @@ public static void ApplicationBaseTests(string filePath, string appBase, string
[TestCase("/path/to/mytest.dll", "/path/to", null)]
[TestCase("/path/to/mytest.dll", "/path", "to")]
- public static void PrivateBinPathTests(string filePath, string appBase, string expected)
+ public static void PrivateBinPathTests(string filePath, string appBase, string? expected)
{
filePath = TestPath(filePath);
appBase = TestPath(appBase);
@@ -115,7 +116,7 @@ public static void PrivateBinPathTests(string filePath, string appBase, string e
[TestCase("/path/to/mytest.dll", "/path", null, "/path/to/mytest.dll.config")]
[TestCase("/path/to/mytest.nunit", "/path/to", null, null)]
[TestCase("/path/to/mytest.nunit", "/path/to", "/path/to/mytest.config", "/path/to/mytest.config")]
- public static void ConfigFileTests(string filePath, string appBase, string configSetting, string expected)
+ public static void ConfigFileTests(string filePath, string appBase, string? configSetting, string? expected)
{
filePath = TestPath(filePath);
appBase = TestPath(appBase);
@@ -134,7 +135,8 @@ public static void ConfigFileTests(string filePath, string appBase, string confi
/// if we are on Windows. Change slashes to backslashes and, if the
/// filePath starts with a slash, add C: in front of it.
///
- private static string TestPath(string path)
+ [return: NotNullIfNotNull(nameof(path))]
+ private static string? TestPath(string? path)
{
if (path != null && Path.DirectorySeparatorChar != '/')
{
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Runners/DomainManagerTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Runners/DomainManagerTests.cs
index 9026b37f9..aa6c7ee5a 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Runners/DomainManagerTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Runners/DomainManagerTests.cs
@@ -47,8 +47,8 @@ public void CanCreateDomain()
[Test, Platform("Linux,Net", Reason = "get_SetupInformation() fails on Windows+Mono")]
public void CanCreateDomainWithApplicationBaseSpecified()
{
- string assemblyDir = Path.GetDirectoryName(_package.FullName);
- string basePath = Path.GetDirectoryName(Path.GetDirectoryName(assemblyDir));
+ string assemblyDir = Path.GetDirectoryName(_package.FullName)!;
+ string basePath = Path.GetDirectoryName(Path.GetDirectoryName(assemblyDir))!;
string relPath = assemblyDir.Substring(basePath.Length + 1);
_package.Settings["BasePath"] = basePath;
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Runners/TestAgentRunnerExceptionTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Runners/TestAgentRunnerExceptionTests.cs
index 881c58f83..098237a5b 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Runners/TestAgentRunnerExceptionTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Runners/TestAgentRunnerExceptionTests.cs
@@ -32,6 +32,12 @@ public void Initialize()
};
}
+ [TearDown]
+ public void Cleanup()
+ {
+ _runner.Dispose();
+ }
+
[Test]
public void Explore_Passes_Along_NUnitEngineException()
{
@@ -45,7 +51,8 @@ public void Explore_Throws_NUnitEngineException()
{
_driver.Explore(Arg.Any()).Throws(new ArgumentException("Message"));
var ex = Assert.Throws(() => _runner.Explore(new TestFilter(string.Empty)));
- Assert.That(ex.InnerException is ArgumentException);
+ Assert.That(ex.InnerException, Is.Not.Null);
+ Assert.That(ex.InnerException, Is.InstanceOf());
Assert.That(ex.InnerException.Message, Is.EqualTo("Message"));
}
@@ -62,7 +69,8 @@ public void Load_Throws_NUnitEngineException()
{
_driver.Load(Arg.Any(), Arg.Any>()).Throws(new ArgumentException("Message"));
var ex = Assert.Throws(() => _runner.Load());
- Assert.That(ex.InnerException is ArgumentException);
+ Assert.That(ex.InnerException, Is.Not.Null);
+ Assert.That(ex.InnerException, Is.InstanceOf());
Assert.That(ex.InnerException.Message, Is.EqualTo("Message"));
}
@@ -79,7 +87,8 @@ public void CountTestCases_Throws_NUnitEngineException()
{
_driver.CountTestCases(Arg.Any()).Throws(new ArgumentException("Message"));
var ex = Assert.Throws(() => _runner.CountTestCases(_testFilter));
- Assert.That(ex.InnerException is ArgumentException);
+ Assert.That(ex.InnerException, Is.Not.Null);
+ Assert.That(ex.InnerException, Is.InstanceOf());
Assert.That(ex.InnerException.Message, Is.EqualTo("Message"));
}
@@ -96,7 +105,8 @@ public void Run_Throws_NUnitEngineException()
{
_driver.Run(Arg.Any(), Arg.Any()).Throws(new ArgumentException("Message"));
var ex = Assert.Throws(() => _runner.Run(Substitute.For(), _testFilter));
- Assert.That(ex.InnerException is ArgumentException);
+ Assert.That(ex.InnerException, Is.Not.Null);
+ Assert.That(ex.InnerException, Is.InstanceOf());
Assert.That(ex.InnerException.Message, Is.EqualTo("Message"));
}
@@ -117,7 +127,8 @@ public void StopRun_Throws_NUnitEngineException()
.Do(x => { throw new ArgumentException("Message"); });
var ex = Assert.Throws(() => _runner.StopRun(true));
- Assert.That(ex.InnerException is ArgumentException);
+ Assert.That(ex.InnerException, Is.Not.Null);
+ Assert.That(ex.InnerException, Is.InstanceOf());
Assert.That(ex.InnerException.Message, Is.EqualTo("Message"));
}
}
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Runners/TestAgentRunnerTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Runners/TestAgentRunnerTests.cs
index a3ff805c7..b02f94a7a 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Runners/TestAgentRunnerTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Runners/TestAgentRunnerTests.cs
@@ -28,7 +28,7 @@ public void Initialize()
_package = new TestPackage(mockAssemblyPath).SubPackages[0];
- _runner = (TRunner)Activator.CreateInstance(typeof(TRunner), _package);
+ _runner = (TRunner)Activator.CreateInstance(typeof(TRunner), _package)!;
}
[TearDown]
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Services/DriverServiceTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Services/DriverServiceTests.cs
index 48d13429d..61122628c 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Services/DriverServiceTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Services/DriverServiceTests.cs
@@ -72,7 +72,7 @@ public void EnsureWeHaveSomeValidTestCases()
{
// Third argument is the Type of the driver
var driverType = testcase.Arguments[2] as Type;
- if (!(driverType.BaseType == typeof(NotRunnableFrameworkDriver)))
+ if (driverType is null || !(driverType.BaseType == typeof(NotRunnableFrameworkDriver)))
break;
// All expected drivers derive from NotRunnableFrameworkDriver
diff --git a/src/NUnitEngine/nunit.engine.core.tests/Services/ExtensionManagerTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Services/ExtensionManagerTests.cs
index 8d7eee359..f427ecc22 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/Services/ExtensionManagerTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/Services/ExtensionManagerTests.cs
@@ -295,14 +295,14 @@ public static IEnumerable InvalidRunnerCombos()
private static string GetSiblingDirectory(string dir)
{
var file = new FileInfo(typeof(ExtensionManagerTests).Assembly.Location);
- return Path.Combine(file.Directory.Parent.FullName, dir);
+ return Path.Combine(file.Directory!.Parent!.FullName, dir);
}
private static readonly Assembly THIS_ASSEMBLY = typeof(ExtensionManagerTests).Assembly;
- private static readonly string THIS_ASSEMBLY_DIRECTORY = Path.GetDirectoryName(THIS_ASSEMBLY.Location);
+ private static readonly string THIS_ASSEMBLY_DIRECTORY = Path.GetDirectoryName(THIS_ASSEMBLY.Location)!;
private const string FAKE_EXTENSIONS_FILENAME = "FakeExtensions.dll";
private static readonly string FAKE_EXTENSIONS_PARENT_DIRECTORY =
- Path.Combine(new DirectoryInfo(THIS_ASSEMBLY_DIRECTORY).Parent.FullName, "fakes");
+ Path.Combine(new DirectoryInfo(THIS_ASSEMBLY_DIRECTORY).Parent!.FullName, "fakes");
///
/// Returns an ExtensionAssembly referring to a particular build of the fake test extensions
diff --git a/src/NUnitEngine/nunit.engine.core.tests/TestEngineResultTests.cs b/src/NUnitEngine/nunit.engine.core.tests/TestEngineResultTests.cs
index 80f03f121..f0a57a1fe 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/TestEngineResultTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/TestEngineResultTests.cs
@@ -17,13 +17,14 @@ public void CanCreateFromXmlString()
TestEngineResult result = new TestEngineResult(xmlText);
Assert.That(result.IsSingle, Is.True);
Assert.That(result.Xml.Name, Is.EqualTo("test-assembly"));
- Assert.That(result.Xml.Attributes["result"].Value, Is.EqualTo("Passed"));
- Assert.That(result.Xml.Attributes["total"].Value, Is.EqualTo("23"));
- Assert.That(result.Xml.Attributes["passed"].Value, Is.EqualTo("23"));
- Assert.That(result.Xml.Attributes["failed"].Value, Is.EqualTo("0"));
- Assert.That(result.Xml.Attributes["inconclusive"].Value, Is.EqualTo("0"));
- Assert.That(result.Xml.Attributes["skipped"].Value, Is.EqualTo("0"));
- Assert.That(result.Xml.Attributes["asserts"].Value, Is.EqualTo("40"));
+ Assert.That(result.Xml.Attributes, Is.Not.Null);
+ Assert.That(result.Xml.Attributes["result"]?.Value, Is.EqualTo("Passed"));
+ Assert.That(result.Xml.Attributes["total"]?.Value, Is.EqualTo("23"));
+ Assert.That(result.Xml.Attributes["passed"]?.Value, Is.EqualTo("23"));
+ Assert.That(result.Xml.Attributes["failed"]?.Value, Is.EqualTo("0"));
+ Assert.That(result.Xml.Attributes["inconclusive"]?.Value, Is.EqualTo("0"));
+ Assert.That(result.Xml.Attributes["skipped"]?.Value, Is.EqualTo("0"));
+ Assert.That(result.Xml.Attributes["asserts"]?.Value, Is.EqualTo("40"));
}
[Test]
diff --git a/src/NUnitEngine/nunit.engine.core.tests/XmlHelperTests.cs b/src/NUnitEngine/nunit.engine.core.tests/XmlHelperTests.cs
index fc20a739d..05d83d3c5 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/XmlHelperTests.cs
+++ b/src/NUnitEngine/nunit.engine.core.tests/XmlHelperTests.cs
@@ -15,6 +15,7 @@ public void SingleElement()
XmlNode node = XmlHelper.CreateTopLevelElement("myelement");
Assert.That(node.Name, Is.EqualTo("myelement"));
+ Assert.That(node.Attributes, Is.Not.Null);
Assert.That(node.Attributes.Count, Is.EqualTo(0));
Assert.That(node.ChildNodes.Count, Is.EqualTo(0));
}
@@ -28,11 +29,12 @@ public void SingleElementWithAttributes()
XmlHelper.AddAttribute(node, "quotes", "'c' is a char but \"c\" is a string");
Assert.That(node.Name, Is.EqualTo("person"));
+ Assert.That(node.Attributes, Is.Not.Null);
Assert.That(node.Attributes.Count, Is.EqualTo(3));
Assert.That(node.ChildNodes.Count, Is.EqualTo(0));
- Assert.That(node.Attributes["name"].Value, Is.EqualTo("Fred"));
- Assert.That(node.Attributes["age"].Value, Is.EqualTo("42"));
- Assert.That(node.Attributes["quotes"].Value, Is.EqualTo("'c' is a char but \"c\" is a string"));
+ Assert.That(node.Attributes["name"]?.Value, Is.EqualTo("Fred"));
+ Assert.That(node.Attributes["age"]?.Value, Is.EqualTo("42"));
+ Assert.That(node.Attributes["quotes"]?.Value, Is.EqualTo("'c' is a char but \"c\" is a string"));
}
[Test]
@@ -42,7 +44,7 @@ public void ElementContainsElementWithInnerText()
XmlNode message = top.AddElement("message");
message.InnerText = "This is my message";
- Assert.That(top.SelectSingleNode("message").InnerText, Is.EqualTo("This is my message"));
+ Assert.That(top.SelectSingleNode("message")?.InnerText, Is.EqualTo("This is my message"));
}
[Test]
@@ -51,7 +53,7 @@ public void ElementContainsElementWithCData()
XmlNode top = XmlHelper.CreateTopLevelElement("top");
top.AddElementWithCDataSection("message", "x > 5 && x < 7");
- Assert.That(top.SelectSingleNode("message").InnerText, Is.EqualTo("x > 5 && x < 7"));
+ Assert.That(top.SelectSingleNode("message")?.InnerText, Is.EqualTo("x > 5 && x < 7"));
}
[Test]
diff --git a/src/NUnitEngine/nunit.engine.core.tests/nunit.engine.core.tests.csproj b/src/NUnitEngine/nunit.engine.core.tests/nunit.engine.core.tests.csproj
index 76c531c66..ee7dd4d94 100644
--- a/src/NUnitEngine/nunit.engine.core.tests/nunit.engine.core.tests.csproj
+++ b/src/NUnitEngine/nunit.engine.core.tests/nunit.engine.core.tests.csproj
@@ -18,6 +18,12 @@
Tests of nunit.engine.core assembly
+
+ true
+
+
+
+
@@ -28,6 +34,10 @@
+
+
+
+
diff --git a/src/NUnitEngine/nunit.engine.core/Agents/RemoteTestAgent.cs b/src/NUnitEngine/nunit.engine.core/Agents/RemoteTestAgent.cs
index f272e2fe3..bbeeeff0d 100644
--- a/src/NUnitEngine/nunit.engine.core/Agents/RemoteTestAgent.cs
+++ b/src/NUnitEngine/nunit.engine.core/Agents/RemoteTestAgent.cs
@@ -25,7 +25,7 @@ public class RemoteTestAgent : TestAgent
///
public RemoteTestAgent(Guid agentId) : base(agentId) { }
- public ITestAgentTransport Transport;
+ public ITestAgentTransport? Transport;
public int ProcessId => System.Diagnostics.Process.GetCurrentProcess().Id;
@@ -37,6 +37,7 @@ public override bool Start()
public override void Stop()
{
+ Guard.OperationValid(Transport != null, "Transport must be set before calling Stop().");
Transport.Stop();
}
diff --git a/src/NUnitEngine/nunit.engine.core/AsyncTestEngineResult.cs b/src/NUnitEngine/nunit.engine.core/AsyncTestEngineResult.cs
index 5b586fd0f..16b674298 100644
--- a/src/NUnitEngine/nunit.engine.core/AsyncTestEngineResult.cs
+++ b/src/NUnitEngine/nunit.engine.core/AsyncTestEngineResult.cs
@@ -13,7 +13,7 @@ namespace NUnit.Engine
[Serializable]
public class AsyncTestEngineResult : ITestRun
{
- private volatile TestEngineResult _result;
+ private volatile TestEngineResult? _result;
private readonly ManualResetEvent _waitHandle = new ManualResetEvent(false);
///
diff --git a/src/NUnitEngine/nunit.engine.core/CallbackHandler.cs b/src/NUnitEngine/nunit.engine.core/CallbackHandler.cs
index d18f27ff4..cec574316 100644
--- a/src/NUnitEngine/nunit.engine.core/CallbackHandler.cs
+++ b/src/NUnitEngine/nunit.engine.core/CallbackHandler.cs
@@ -8,11 +8,11 @@ namespace NUnit.Engine
{
public class CallbackHandler : MarshalByRefObject, ICallbackEventHandler
{
- public string Result { get; private set; }
+ public string? Result { get; private set; }
public override object InitializeLifetimeService()
{
- return null;
+ return null!;
}
public string GetCallbackResult()
diff --git a/src/NUnitEngine/nunit.engine.core/Communication/Transports/Remoting/TestAgentRemotingTransport.cs b/src/NUnitEngine/nunit.engine.core/Communication/Transports/Remoting/TestAgentRemotingTransport.cs
index ac8486355..a772ee97c 100644
--- a/src/NUnitEngine/nunit.engine.core/Communication/Transports/Remoting/TestAgentRemotingTransport.cs
+++ b/src/NUnitEngine/nunit.engine.core/Communication/Transports/Remoting/TestAgentRemotingTransport.cs
@@ -22,10 +22,10 @@ public class TestAgentRemotingTransport : MarshalByRefObject, ITestAgentTranspor
private static readonly Logger log = InternalTrace.GetLogger(typeof(TestAgentRemotingTransport));
private readonly string _agencyUrl;
- private ITestEngineRunner _runner;
+ private ITestEngineRunner? _runner;
- private TcpChannel _channel;
- private ITestAgency _agency;
+ private TcpChannel? _channel;
+ private ITestAgency? _agency;
private readonly CurrentMessageCounter _currentMessageCounter = new CurrentMessageCounter();
public TestAgentRemotingTransport(RemoteTestAgent agent, string agencyUrl)
@@ -54,6 +54,7 @@ public bool Start()
catch (Exception ex)
{
log.Error("Unable to connect: {0}", ExceptionHelper.BuildMessageAndStackTrace(ex));
+ return false;
}
try
@@ -72,6 +73,8 @@ public bool Start()
public void Stop()
{
+ Guard.OperationValid(_channel != null, "Channel is not open");
+
log.Info("Stopping");
// Do this on a different thread since we need to wait until all messages are through,
@@ -97,6 +100,7 @@ public void Stop()
public ITestEngineRunner CreateRunner(TestPackage package)
{
+ _runner?.Dispose();
_runner = Agent.CreateRunner(package);
return this;
}
@@ -104,7 +108,7 @@ public ITestEngineRunner CreateRunner(TestPackage package)
public void Dispose()
{
Agent.Dispose();
- _runner.Dispose();
+ _runner?.Dispose();
}
#region ITestEngineRunner Implementation
@@ -117,23 +121,22 @@ public void Dispose()
/// A TestEngineResult.
public TestEngineResult Explore(TestFilter filter)
{
- return _runner.Explore(filter);
+ return _runner.ShouldNotBeNull().Explore(filter);
}
public TestEngineResult Load()
{
- return _runner.Load();
+ return _runner.ShouldNotBeNull().Load();
}
public void Unload()
{
- if (_runner != null)
- _runner.Unload();
+ _runner?.Unload();
}
public TestEngineResult Reload()
{
- return _runner.Reload();
+ return _runner.ShouldNotBeNull().Reload();
}
///
@@ -144,7 +147,7 @@ public TestEngineResult Reload()
/// The count of test cases
public int CountTestCases(TestFilter filter)
{
- return _runner.CountTestCases(filter);
+ return _runner.ShouldNotBeNull().CountTestCases(filter);
}
///
@@ -156,7 +159,7 @@ public int CountTestCases(TestFilter filter)
/// A TestEngineResult giving the result of the test execution
public TestEngineResult Run(ITestEventListener listener, TestFilter filter)
{
- return _runner.Run(listener, filter);
+ return _runner.ShouldNotBeNull().Run(listener, filter);
}
///
@@ -168,7 +171,7 @@ public TestEngineResult Run(ITestEventListener listener, TestFilter filter)
/// A that will provide the result of the test execution
public AsyncTestEngineResult RunAsync(ITestEventListener listener, TestFilter filter)
{
- return _runner.RunAsync(listener, filter);
+ return _runner.ShouldNotBeNull().RunAsync(listener, filter);
}
///
@@ -177,8 +180,7 @@ public AsyncTestEngineResult RunAsync(ITestEventListener listener, TestFilter fi
/// If true, cancel any ongoing test threads, otherwise wait for them to complete.
public void StopRun(bool force)
{
- if (_runner != null)
- _runner.StopRun(force);
+ _runner?.StopRun(force);
}
#endregion
@@ -188,7 +190,7 @@ public void StopRun(bool force)
///
public override object InitializeLifetimeService()
{
- return null;
+ return null!;
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Communication/Transports/Tcp/SocketReader.cs b/src/NUnitEngine/nunit.engine.core/Communication/Transports/Tcp/SocketReader.cs
index 60223956e..2553a59d5 100644
--- a/src/NUnitEngine/nunit.engine.core/Communication/Transports/Tcp/SocketReader.cs
+++ b/src/NUnitEngine/nunit.engine.core/Communication/Transports/Tcp/SocketReader.cs
@@ -16,11 +16,11 @@ public class SocketReader
{
private const int BUFFER_SIZE = 1024;
- private Socket _socket;
- private ISerializationProtocol _wireProtocol;
+ private readonly Socket _socket;
+ private readonly ISerializationProtocol _wireProtocol;
- private Queue _msgQueue;
- private byte[] _buffer;
+ private readonly Queue _msgQueue;
+ private readonly byte[] _buffer;
public SocketReader(Socket socket, ISerializationProtocol protocol)
{
diff --git a/src/NUnitEngine/nunit.engine.core/Communication/Transports/Tcp/TestAgentTcpTransport.cs b/src/NUnitEngine/nunit.engine.core/Communication/Transports/Tcp/TestAgentTcpTransport.cs
index bd8f913e3..f130c8621 100644
--- a/src/NUnitEngine/nunit.engine.core/Communication/Transports/Tcp/TestAgentTcpTransport.cs
+++ b/src/NUnitEngine/nunit.engine.core/Communication/Transports/Tcp/TestAgentTcpTransport.cs
@@ -20,9 +20,9 @@ public class TestAgentTcpTransport : ITestAgentTransport, ITestEventListener
{
private static readonly Logger log = InternalTrace.GetLogger(typeof(TestAgentTcpTransport));
- private string _agencyUrl;
- private Socket _clientSocket;
- private ITestEngineRunner _runner;
+ private readonly string _agencyUrl;
+ private Socket? _clientSocket;
+ private ITestEngineRunner? _runner;
public TestAgentTcpTransport(RemoteTestAgent agent, string serverUrl)
{
@@ -72,7 +72,7 @@ public ITestEngineRunner CreateRunner(TestPackage package)
private void CommandLoop()
{
bool keepRunning = true;
- var socketReader = new SocketReader(_clientSocket, new BinarySerializationProtocol());
+ var socketReader = new SocketReader(_clientSocket.ShouldNotBeNull(), new BinarySerializationProtocol());
while (keepRunning)
{
@@ -82,33 +82,34 @@ private void CommandLoop()
{
case "CreateRunner":
var package = (TestPackage)command.Arguments[0];
+ _runner?.Unload();
_runner = CreateRunner(package);
break;
case "Load":
- SendResult(_runner.Load());
+ SendResult(_runner.ShouldNotBeNull().Load());
break;
case "Reload":
- SendResult(_runner.Reload());
+ SendResult(_runner.ShouldNotBeNull().Reload());
break;
case "Unload":
- _runner.Unload();
+ _runner.ShouldNotBeNull().Unload();
break;
case "Explore":
var filter = (TestFilter)command.Arguments[0];
- SendResult(_runner.Explore(filter));
+ SendResult(_runner.ShouldNotBeNull().Explore(filter));
break;
case "CountTestCases":
filter = (TestFilter)command.Arguments[0];
- SendResult(_runner.CountTestCases(filter));
+ SendResult(_runner.ShouldNotBeNull().CountTestCases(filter));
break;
case "Run":
filter = (TestFilter)command.Arguments[0];
- SendResult(_runner.Run(this, filter));
+ SendResult(_runner.ShouldNotBeNull().Run(this, filter));
break;
case "RunAsync":
filter = (TestFilter)command.Arguments[0];
- _runner.RunAsync(this, filter);
+ _runner.ShouldNotBeNull().RunAsync(this, filter);
break;
case "Stop":
@@ -124,14 +125,14 @@ private void SendResult(object result)
{
var resultMessage = new CommandReturnMessage(result);
var bytes = new BinarySerializationProtocol().Encode(resultMessage);
- _clientSocket.Send(bytes);
+ _clientSocket.ShouldNotBeNull().Send(bytes);
}
public void OnTestEvent(string report)
{
var progressMessage = new ProgressMessage(report);
var bytes = new BinarySerializationProtocol().Encode(progressMessage);
- _clientSocket.Send(bytes);
+ _clientSocket.ShouldNotBeNull().Send(bytes);
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/DotNet.cs b/src/NUnitEngine/nunit.engine.core/DotNet.cs
index bba07a275..5d4eece65 100644
--- a/src/NUnitEngine/nunit.engine.core/DotNet.cs
+++ b/src/NUnitEngine/nunit.engine.core/DotNet.cs
@@ -9,14 +9,14 @@ namespace NUnit.Engine
{
public static class DotNet
{
- public static string GetInstallDirectory() => Environment.Is64BitProcess
+ public static string? GetInstallDirectory() => Environment.Is64BitProcess
? GetX64InstallDirectory() : GetX86InstallDirectory();
- public static string GetInstallDirectory(bool x86) => x86
+ public static string? GetInstallDirectory(bool x86) => x86
? GetX86InstallDirectory() : GetX64InstallDirectory();
- private static string _x64InstallDirectory;
- public static string GetX64InstallDirectory()
+ private static string? _x64InstallDirectory;
+ public static string? GetX64InstallDirectory()
{
if (_x64InstallDirectory == null)
_x64InstallDirectory = Environment.GetEnvironmentVariable("DOTNET_ROOT");
@@ -29,8 +29,8 @@ public static string GetX64InstallDirectory()
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
#endif
{
- RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\dotnet\SetUp\InstalledVersions\x64\sharedHost\");
- _x64InstallDirectory = (string)key?.GetValue("Path");
+ using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\dotnet\SetUp\InstalledVersions\x64\sharedHost\"))
+ _x64InstallDirectory = (string?)key?.GetValue("Path");
}
else
_x64InstallDirectory = "/usr/shared/dotnet/";
@@ -39,8 +39,8 @@ public static string GetX64InstallDirectory()
return _x64InstallDirectory;
}
- private static string _x86InstallDirectory;
- public static string GetX86InstallDirectory()
+ private static string? _x86InstallDirectory;
+ public static string? GetX86InstallDirectory()
{
if (_x86InstallDirectory == null)
_x86InstallDirectory = Environment.GetEnvironmentVariable("DOTNET_ROOT_X86");
@@ -53,8 +53,8 @@ public static string GetX86InstallDirectory()
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
#endif
{
- RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\dotnet\SetUp\InstalledVersions\x86\");
- _x86InstallDirectory = (string)key?.GetValue("InstallLocation");
+ using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\dotnet\SetUp\InstalledVersions\x86\"))
+ _x86InstallDirectory = (string?)key?.GetValue("InstallLocation");
}
else
_x86InstallDirectory = "/usr/shared/dotnet/";
diff --git a/src/NUnitEngine/nunit.engine.core/Drivers/DriverService.cs b/src/NUnitEngine/nunit.engine.core/Drivers/DriverService.cs
index 15e6bea3f..ccaec8db7 100644
--- a/src/NUnitEngine/nunit.engine.core/Drivers/DriverService.cs
+++ b/src/NUnitEngine/nunit.engine.core/Drivers/DriverService.cs
@@ -51,7 +51,7 @@ public DriverService()
/// The value of any TargetFrameworkAttribute on the assembly, or null
/// True if non-test assemblies should simply be skipped rather than reporting an error
///
- public IFrameworkDriver GetDriver(AppDomain domain, string assemblyPath, string targetFramework, bool skipNonTestAssemblies)
+ public IFrameworkDriver GetDriver(AppDomain domain, string assemblyPath, string? targetFramework, bool skipNonTestAssemblies)
{
if (!File.Exists(assemblyPath))
return new InvalidAssemblyFrameworkDriver(assemblyPath, "File not found: " + assemblyPath);
@@ -98,11 +98,13 @@ public IFrameworkDriver GetDriver(AppDomain domain, string assemblyPath, string
foreach (var reference in references)
{
if (factory.IsSupportedTestFramework(reference))
+ {
#if NETFRAMEWORK
- return factory.GetDriver(domain, reference);
+ return factory.GetDriver(domain, reference);
#else
- return factory.GetDriver(reference);
+ return factory.GetDriver(reference);
#endif
+ }
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Drivers/IDriverService.cs b/src/NUnitEngine/nunit.engine.core/Drivers/IDriverService.cs
index d077673f2..fb3c26d3f 100644
--- a/src/NUnitEngine/nunit.engine.core/Drivers/IDriverService.cs
+++ b/src/NUnitEngine/nunit.engine.core/Drivers/IDriverService.cs
@@ -19,6 +19,6 @@ public interface IDriverService
/// The value of any TargetFrameworkAttribute on the assembly, or null
/// True if non-test assemblies should simply be skipped rather than reporting an error
///
- IFrameworkDriver GetDriver(AppDomain domain, string assemblyPath, string targetFramework, bool skipNonTestAssemblies);
+ IFrameworkDriver GetDriver(AppDomain domain, string assemblyPath, string? targetFramework, bool skipNonTestAssemblies);
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Drivers/NUnit2DriverFactory.cs b/src/NUnitEngine/nunit.engine.core/Drivers/NUnit2DriverFactory.cs
index 6bc490cc8..df4fb3688 100644
--- a/src/NUnitEngine/nunit.engine.core/Drivers/NUnit2DriverFactory.cs
+++ b/src/NUnitEngine/nunit.engine.core/Drivers/NUnit2DriverFactory.cs
@@ -13,10 +13,10 @@ public class NUnit2DriverFactory : IDriverFactory
{
private const string NUNIT_FRAMEWORK = "nunit.framework";
private const string NUNITLITE_FRAMEWORK = "nunitlite";
- private ExtensionNode _driverNode;
+ private readonly ExtensionNode _driverNode;
// TODO: This should be a central service but for now it's local
- private ProvidedPathsAssemblyResolver _resolver;
+ private readonly ProvidedPathsAssemblyResolver _resolver;
bool _resolverInstalled;
public NUnit2DriverFactory(ExtensionNode driverNode)
@@ -32,8 +32,8 @@ public NUnit2DriverFactory(ExtensionNode driverNode)
/// An AssemblyName referring to the possible test framework.
public bool IsSupportedTestFramework(AssemblyName reference)
{
- return NUNIT_FRAMEWORK.Equals(reference.Name, StringComparison.OrdinalIgnoreCase) && reference.Version.Major == 2
- || NUNITLITE_FRAMEWORK.Equals(reference.Name, StringComparison.OrdinalIgnoreCase) && reference.Version.Major == 1;
+ return NUNIT_FRAMEWORK.Equals(reference.Name, StringComparison.OrdinalIgnoreCase) && reference.Version?.Major == 2
+ || NUNITLITE_FRAMEWORK.Equals(reference.Name, StringComparison.OrdinalIgnoreCase) && reference.Version?.Major == 1;
}
///
@@ -55,7 +55,7 @@ public IFrameworkDriver GetDriver(AppDomain domain, AssemblyName reference)
_resolver.AddPathFromFile(_driverNode.AssemblyPath);
}
- return _driverNode.CreateExtensionObject(domain) as IFrameworkDriver;
+ return (IFrameworkDriver)_driverNode.CreateExtensionObject(domain);
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Drivers/NUnit3DriverFactory.cs b/src/NUnitEngine/nunit.engine.core/Drivers/NUnit3DriverFactory.cs
index 03b0bb5ae..5186570b0 100644
--- a/src/NUnitEngine/nunit.engine.core/Drivers/NUnit3DriverFactory.cs
+++ b/src/NUnitEngine/nunit.engine.core/Drivers/NUnit3DriverFactory.cs
@@ -11,7 +11,7 @@ namespace NUnit.Engine.Drivers
public class NUnit3DriverFactory : IDriverFactory
{
internal const string NUNIT_FRAMEWORK = "nunit.framework";
- static ILogger log = InternalTrace.GetLogger(typeof(NUnit3DriverFactory));
+ static readonly ILogger log = InternalTrace.GetLogger(typeof(NUnit3DriverFactory));
///
/// Gets a flag indicating whether a given assembly name and version
@@ -20,7 +20,7 @@ public class NUnit3DriverFactory : IDriverFactory
/// An AssemblyName referring to the possible test framework.
public bool IsSupportedTestFramework(AssemblyName reference)
{
- return NUNIT_FRAMEWORK.Equals(reference.Name, StringComparison.OrdinalIgnoreCase) && reference.Version.Major >= 3;
+ return NUNIT_FRAMEWORK.Equals(reference.Name, StringComparison.OrdinalIgnoreCase) && reference.Version?.Major >= 3;
}
#if NETFRAMEWORK
diff --git a/src/NUnitEngine/nunit.engine.core/Drivers/NUnit3FrameworkDriver.cs b/src/NUnitEngine/nunit.engine.core/Drivers/NUnit3FrameworkDriver.cs
index d89eadb8b..8084d79b0 100644
--- a/src/NUnitEngine/nunit.engine.core/Drivers/NUnit3FrameworkDriver.cs
+++ b/src/NUnitEngine/nunit.engine.core/Drivers/NUnit3FrameworkDriver.cs
@@ -9,6 +9,7 @@
using NUnit.Common;
using NUnit.Engine.Internal;
using NUnit.Engine.Extensibility;
+using System.Diagnostics.CodeAnalysis;
namespace NUnit.Engine.Drivers
{
@@ -27,13 +28,13 @@ public class NUnit3FrameworkDriver : IFrameworkDriver
private static readonly string RUN_ACTION = CONTROLLER_TYPE + "+RunTestsAction";
private static readonly string STOP_RUN_ACTION = CONTROLLER_TYPE + "+StopRunAction";
- static ILogger log = InternalTrace.GetLogger("NUnitFrameworkDriver");
+ static readonly ILogger log = InternalTrace.GetLogger("NUnitFrameworkDriver");
- AppDomain _testDomain;
- AssemblyName _reference;
- string _testAssemblyPath;
+ readonly AppDomain _testDomain;
+ readonly AssemblyName _reference;
+ string? _testAssemblyPath;
- object _frameworkController;
+ object? _frameworkController;
///
/// Construct an NUnit3FrameworkDriver
@@ -46,7 +47,7 @@ public NUnit3FrameworkDriver(AppDomain testDomain, AssemblyName reference)
_reference = reference;
}
- public string ID { get; set; }
+ public string ID { get; set; } = string.Empty;
///
/// Loads the tests in an assembly.
@@ -87,7 +88,7 @@ public string Load(string testAssemblyPath, IDictionary settings
log.Info("Loaded {0}", fileName);
- return handler.Result;
+ return handler.Result.ShouldNotBeNull();
}
public int CountTestCases(string filter)
@@ -96,9 +97,9 @@ public int CountTestCases(string filter)
CallbackHandler handler = new CallbackHandler();
- CreateObject(COUNT_ACTION, _frameworkController, filter, handler);
+ CreateObject(COUNT_ACTION, _frameworkController.ShouldNotBeNull(), filter, handler);
- return int.Parse(handler.Result);
+ return int.Parse(handler.Result.ShouldNotBeNull());
}
///
@@ -107,16 +108,16 @@ public int CountTestCases(string filter)
/// An ITestEventHandler that receives progress notices
/// A filter that controls which tests are executed
/// An Xml string representing the result
- public string Run(ITestEventListener listener, string filter)
+ public string Run(ITestEventListener? listener, string filter)
{
CheckLoadWasCalled();
var handler = new RunTestsCallbackHandler(listener);
- log.Info("Running {0} - see separate log file", Path.GetFileName(_testAssemblyPath));
- CreateObject(RUN_ACTION, _frameworkController, filter, handler);
+ log.Info("Running {0} - see separate log file", Path.GetFileName(_testAssemblyPath.ShouldNotBeNull()));
+ CreateObject(RUN_ACTION, _frameworkController.ShouldNotBeNull(), filter, handler);
- return handler.Result;
+ return handler.Result.ShouldNotBeNull();
}
///
@@ -125,7 +126,7 @@ public string Run(ITestEventListener listener, string filter)
/// If true, cancel any ongoing test threads, otherwise wait for them to complete.
public void StopRun(bool force)
{
- CreateObject(STOP_RUN_ACTION, _frameworkController, force, new CallbackHandler());
+ CreateObject(STOP_RUN_ACTION, _frameworkController.ShouldNotBeNull(), force, new CallbackHandler());
}
///
@@ -139,10 +140,10 @@ public string Explore(string filter)
CallbackHandler handler = new CallbackHandler();
- log.Info("Exploring {0} - see separate log file", Path.GetFileName(_testAssemblyPath));
- CreateObject(EXPLORE_ACTION, _frameworkController, filter, handler);
+ log.Info("Exploring {0} - see separate log file", Path.GetFileName(_testAssemblyPath.ShouldNotBeNull()));
+ CreateObject(EXPLORE_ACTION, _frameworkController.ShouldNotBeNull(), filter, handler);
- return handler.Result;
+ return handler.Result.ShouldNotBeNull();
}
private void CheckLoadWasCalled()
@@ -151,12 +152,12 @@ private void CheckLoadWasCalled()
throw new InvalidOperationException(LOAD_MESSAGE);
}
- private object CreateObject(string typeName, params object[] args)
+ private object CreateObject(string typeName, params object?[]? args)
{
try
{
return _testDomain.CreateInstanceAndUnwrap(
- _reference.FullName, typeName, false, 0, null, args, null, null );
+ _reference.FullName, typeName, false, 0, null, args, null, null )!;
}
catch (TargetInvocationException ex)
{
diff --git a/src/NUnitEngine/nunit.engine.core/Drivers/NUnitNetCore31Driver.cs b/src/NUnitEngine/nunit.engine.core/Drivers/NUnitNetCore31Driver.cs
index 60063357d..7199f9a8f 100644
--- a/src/NUnitEngine/nunit.engine.core/Drivers/NUnitNetCore31Driver.cs
+++ b/src/NUnitEngine/nunit.engine.core/Drivers/NUnitNetCore31Driver.cs
@@ -9,6 +9,7 @@
using System.Reflection;
using NUnit.Engine.Extensibility;
using System.Diagnostics;
+using NUnit.Common;
namespace NUnit.Engine.Drivers
{
@@ -35,17 +36,17 @@ public class NUnitNetCore31Driver : IFrameworkDriver
static ILogger log = InternalTrace.GetLogger(nameof(NUnitNetCore31Driver));
- Assembly _testAssembly;
- Assembly _frameworkAssembly;
- object _frameworkController;
- Type _frameworkControllerType;
- TestAssemblyLoadContext _assemblyLoadContext;
+ Assembly? _testAssembly;
+ Assembly? _frameworkAssembly;
+ object? _frameworkController;
+ Type? _frameworkControllerType;
+ TestAssemblyLoadContext? _assemblyLoadContext;
///
/// An id prefix that will be passed to the test framework and used as part of the
/// test ids created.
///
- public string ID { get; set; }
+ public string ID { get; set; } = string.Empty;
///
/// Loads the tests in an assembly.
@@ -73,7 +74,7 @@ public string Load(string assemblyPath, IDictionary settings)
}
log.Debug($"Loaded {assemblyPath}");
- var nunitRef = _testAssembly.GetReferencedAssemblies().FirstOrDefault(reference => reference.Name.Equals("nunit.framework", StringComparison.OrdinalIgnoreCase));
+ var nunitRef = _testAssembly.GetReferencedAssemblies().FirstOrDefault(reference => string.Equals(reference.Name, "nunit.framework", StringComparison.OrdinalIgnoreCase));
if (nunitRef == null)
{
log.Error(FAILED_TO_LOAD_NUNIT);
@@ -101,8 +102,8 @@ public string Load(string assemblyPath, IDictionary settings)
_frameworkControllerType = _frameworkController.GetType();
log.Debug($"Created FrameworkControler {_frameworkControllerType.Name}");
- log.Info("Loading {0} - see separate log file", _testAssembly.FullName);
- return ExecuteMethod(LOAD_METHOD) as string;
+ log.Info("Loading {0} - see separate log file", _testAssembly.FullName!);
+ return (string)ExecuteMethod(LOAD_METHOD);
}
///
@@ -113,7 +114,7 @@ public string Load(string assemblyPath, IDictionary settings)
public int CountTestCases(string filter)
{
CheckLoadWasCalled();
- object count = ExecuteMethod(COUNT_METHOD, filter);
+ object? count = ExecuteMethod(COUNT_METHOD, filter);
return count != null ? (int)count : 0;
}
@@ -123,12 +124,12 @@ public int CountTestCases(string filter)
/// An ITestEventHandler that receives progress notices
/// A filter that controls which tests are executed
/// An Xml string representing the result
- public string Run(ITestEventListener listener, string filter)
+ public string Run(ITestEventListener? listener, string filter)
{
CheckLoadWasCalled();
- log.Info("Running {0} - see separate log file", _testAssembly.FullName);
- Action callback = listener != null ? listener.OnTestEvent : (Action)null;
- return ExecuteMethod(RUN_METHOD, new[] { typeof(Action), typeof(string) }, callback, filter) as string;
+ log.Info("Running {0} - see separate log file", _testAssembly.ShouldNotBeNull().FullName!);
+ Action? callback = listener != null ? listener.OnTestEvent : (Action?)null;
+ return (string)ExecuteMethod(RUN_METHOD, new[] { typeof(Action), typeof(string) }, callback, filter);
}
///
@@ -139,7 +140,7 @@ public string Run(ITestEventListener listener, string filter)
public void RunAsync(Action callback, string filter)
{
CheckLoadWasCalled();
- log.Info("Running {0} - see separate log file", _testAssembly.FullName);
+ log.Info("Running {0} - see separate log file", _testAssembly.ShouldNotBeNull().FullName!);
ExecuteMethod(RUN_ASYNC_METHOD, new[] { typeof(Action), typeof(string) }, callback, filter);
}
@@ -161,8 +162,8 @@ public string Explore(string filter)
{
CheckLoadWasCalled();
- log.Info("Exploring {0} - see separate log file", _testAssembly.FullName);
- return ExecuteMethod(EXPLORE_METHOD, filter) as string;
+ log.Info("Exploring {0} - see separate log file", _testAssembly.ShouldNotBeNull().FullName!);
+ return (string)ExecuteMethod(EXPLORE_METHOD, filter);
}
void CheckLoadWasCalled()
@@ -171,41 +172,35 @@ void CheckLoadWasCalled()
throw new InvalidOperationException(LOAD_MESSAGE);
}
- object CreateObject(string typeName, params object[] args)
+ object CreateObject(string typeName, params object?[]? args)
{
- var typeinfo = _frameworkAssembly.DefinedTypes.FirstOrDefault(t => t.FullName == typeName);
- if (typeinfo == null)
- {
- log.Error("Could not find type {0}", typeName);
- }
- return Activator.CreateInstance(typeinfo.AsType(), args);
+ var type = _frameworkAssembly.ShouldNotBeNull().GetType(typeName, throwOnError: true)!;
+ return Activator.CreateInstance(type, args)!;
}
- object ExecuteMethod(string methodName, params object[] args)
+ object ExecuteMethod(string methodName, params object?[] args)
{
- var method = _frameworkControllerType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance);
- if (method == null)
- log.Error($"Method {methodName} was not found in {_frameworkControllerType.Name}");
- log.Debug($"Executing {method.DeclaringType}.{method.Name}");
+ var method = _frameworkControllerType.ShouldNotBeNull().GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance);
return ExecuteMethod(method, args);
}
- object ExecuteMethod(string methodName, Type[] ptypes, params object[] args)
+ object ExecuteMethod(string methodName, Type[] ptypes, params object?[] args)
{
- var method = _frameworkControllerType.GetMethod(methodName, ptypes);
+ var method = _frameworkControllerType.ShouldNotBeNull().GetMethod(methodName, ptypes);
return ExecuteMethod(method, args);
}
- object ExecuteMethod(MethodInfo method, params object[] args)
+ object ExecuteMethod(MethodInfo? method, params object?[] args)
{
if (method == null)
{
throw new NUnitEngineException(INVALID_FRAMEWORK_MESSAGE);
}
- using (_assemblyLoadContext.EnterContextualReflection())
+ using (_assemblyLoadContext.ShouldNotBeNull().EnterContextualReflection())
{
- return method.Invoke(_frameworkController, args);
+ log.Debug($"Executing {method.DeclaringType}.{method.Name}");
+ return method.Invoke(_frameworkController, args).ShouldNotBeNull();
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Drivers/NotRunnableFrameworkDriver.cs b/src/NUnitEngine/nunit.engine.core/Drivers/NotRunnableFrameworkDriver.cs
index 77250b61e..6967be78f 100644
--- a/src/NUnitEngine/nunit.engine.core/Drivers/NotRunnableFrameworkDriver.cs
+++ b/src/NUnitEngine/nunit.engine.core/Drivers/NotRunnableFrameworkDriver.cs
@@ -26,16 +26,18 @@ public abstract class NotRunnableFrameworkDriver : IFrameworkDriver
"" +
"";
- private string _name;
- private string _fullname;
- private string _message;
- private string _type;
+ private readonly string _name;
+ private readonly string _fullname;
+ private readonly string _message;
+ private readonly string _type;
protected string _runstate;
protected string _result;
protected string _label;
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
public NotRunnableFrameworkDriver(string assemblyPath, string message)
+#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
{
_name = Escape(Path.GetFileName(assemblyPath));
_fullname = Escape(Path.GetFullPath(assemblyPath));
@@ -56,7 +58,7 @@ public int CountTestCases(string filter)
return 0;
}
- public string Run(ITestEventListener listener, string filter)
+ public string Run(ITestEventListener? listener, string filter)
{
return string.Format(RUN_RESULT_FORMAT,
_type, TestID, _name, _fullname, _runstate, _result, _label, _message);
diff --git a/src/NUnitEngine/nunit.engine.core/Extensibility/AddinsFile.cs b/src/NUnitEngine/nunit.engine.core/Extensibility/AddinsFile.cs
index 6b090c318..8656de43c 100644
--- a/src/NUnitEngine/nunit.engine.core/Extensibility/AddinsFile.cs
+++ b/src/NUnitEngine/nunit.engine.core/Extensibility/AddinsFile.cs
@@ -31,19 +31,20 @@ public static AddinsFile Read(IFile file)
/// All entries contained in the file.
/// cannot be read
/// If the executing system uses backslashes ('\') to separate directories, these will be substituted with slashes ('/').
- internal static AddinsFile Read(Stream stream, string fullName = null)
+ internal static AddinsFile Read(Stream stream, string fullName = "addins file")
{
using (var reader = new StreamReader(stream))
{
var addinsFile = new AddinsFile();
int lineNumber = 0;
- while (!reader.EndOfStream)
+ string? line;
+ while ((line = reader.ReadLine()) != null)
{
- var entry = new AddinsFileEntry(++lineNumber, reader.ReadLine());
+ var entry = new AddinsFileEntry(++lineNumber, line);
if (entry.Text != "" && !entry.IsValid)
{
- string msg = $"Invalid Entry in {fullName ?? "addins file"}:\r\n {entry}";
+ string msg = $"Invalid Entry in {fullName}:\r\n {entry}";
throw new InvalidOperationException(msg);
}
@@ -64,7 +65,7 @@ public override string ToString()
return sb.ToString();
}
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
var other = obj as AddinsFile;
if (other == null) return false;
diff --git a/src/NUnitEngine/nunit.engine.core/Extensibility/AddinsFileEntry.cs b/src/NUnitEngine/nunit.engine.core/Extensibility/AddinsFileEntry.cs
index 3bf6470d5..d7ecb2d07 100644
--- a/src/NUnitEngine/nunit.engine.core/Extensibility/AddinsFileEntry.cs
+++ b/src/NUnitEngine/nunit.engine.core/Extensibility/AddinsFileEntry.cs
@@ -18,7 +18,7 @@ internal class AddinsFileEntry
public bool IsPattern => Text.Contains("*");
public bool IsValid => PathUtils.IsValidPath(Text.Replace('*', 'X'));
- public string DirectoryName => Path.GetDirectoryName(Text);
+ public string DirectoryName => Path.GetDirectoryName(Text)!;
public string FileName => Path.GetFileName(Text);
public AddinsFileEntry(int lineNumber, string rawText)
@@ -34,7 +34,7 @@ public override string ToString()
return $"{LineNumber}: {RawText}";
}
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
var other = obj as AddinsFileEntry;
if (other == null) return false;
diff --git a/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionAssembly.cs b/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionAssembly.cs
index 922038b2f..32e6b6cca 100644
--- a/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionAssembly.cs
+++ b/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionAssembly.cs
@@ -20,6 +20,7 @@ public ExtensionAssembly(string filePath, bool fromWildCard)
AssemblyVersion = Assembly.Name.Version;
}
+#if ACTUALLY_USED
// Internal constructor used for certain tests. AssemblyDefinition is not initialized.
internal ExtensionAssembly(string filePath, bool fromWildCard, string assemblyName, Version version)
{
@@ -28,6 +29,7 @@ internal ExtensionAssembly(string filePath, bool fromWildCard, string assemblyNa
AssemblyName = assemblyName;
AssemblyVersion = version;
}
+#endif
public string FilePath { get; }
public bool FromWildCard { get; }
diff --git a/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionManager.cs b/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionManager.cs
index 8163fa500..dad1e34bd 100644
--- a/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionManager.cs
+++ b/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionManager.cs
@@ -15,7 +15,7 @@ namespace NUnit.Engine.Extensibility
{
public class ExtensionManager
{
- static readonly Version CURRENT_ENGINE_VERSION = Assembly.GetExecutingAssembly().GetName().Version;
+ static readonly Version CURRENT_ENGINE_VERSION = Assembly.GetExecutingAssembly().GetName().Version ?? new Version();
static readonly Logger log = InternalTrace.GetLogger(typeof(ExtensionManager));
@@ -30,7 +30,7 @@ public class ExtensionManager
private readonly Dictionary _extensionPointIndex = new Dictionary();
// List of ExtensionNodes for all extensions discovered.
- private List _extensions = new List();
+ private readonly List _extensions = new List();
private bool _extensionsAreLoaded;
@@ -88,7 +88,7 @@ public virtual void FindExtensionPoints(params Assembly[] targetAssemblies)
{
foreach (var assembly in targetAssemblies)
{
- log.Info("FindExtensionPoints scanning {0} assembly", assembly.GetName().Name);
+ log.Info("FindExtensionPoints scanning {0} assembly", assembly.GetName().Name!);
foreach (ExtensionPointAttribute attr in assembly.GetCustomAttributes(typeof(ExtensionPointAttribute), false))
{
@@ -175,7 +175,7 @@ public void FindExtensionAssemblies(Assembly hostAssembly)
: new[] { "NUnit.Extension.*/**/tools/", "NUnit.Extension.*/**/tools/*/" };
- IDirectory startDir = _fileSystem.GetDirectory(AssemblyHelper.GetDirectoryName(hostAssembly));
+ IDirectory? startDir = _fileSystem.GetDirectory(AssemblyHelper.GetDirectoryName(hostAssembly));
while (startDir != null)
{
@@ -190,9 +190,9 @@ public void FindExtensionAssemblies(Assembly hostAssembly)
///
/// Get an ExtensionPoint based on its unique identifying path.
///
- public IExtensionPoint GetExtensionPoint(string path)
+ public IExtensionPoint? GetExtensionPoint(string path)
{
- return _extensionPointIndex.TryGetValue(path, out ExtensionPoint ep) ? ep : null;
+ return _extensionPointIndex.TryGetValue(path, out ExtensionPoint? ep) ? ep : null;
}
///
@@ -222,7 +222,7 @@ public IEnumerable GetExtensionNodes(string path)
///
/// The identifying path for an ExtensionPoint
///
- public IExtensionNode GetExtensionNode(string path)
+ public IExtensionNode? GetExtensionNode(string path)
{
EnsureExtensionsAreLoaded();
@@ -264,7 +264,7 @@ public void EnableExtension(string typeName, bool enabled)
///
/// Get an ExtensionPoint based on the required Type for extensions.
///
- public ExtensionPoint GetExtensionPoint(Type type)
+ public ExtensionPoint? GetExtensionPoint(Type type)
{
foreach (var ep in _extensionPoints)
if (ep.TypeName == type.FullName)
@@ -276,7 +276,7 @@ public ExtensionPoint GetExtensionPoint(Type type)
///
/// Get an ExtensionPoint based on a Cecil TypeReference.
///
- public ExtensionPoint GetExtensionPoint(TypeReference type)
+ public ExtensionPoint? GetExtensionPoint(TypeReference type)
{
foreach (var ep in _extensionPoints)
if (ep.TypeName == type.FullName)
@@ -290,7 +290,7 @@ public ExtensionPoint GetExtensionPoint(TypeReference type)
/// Returns null if no extension point can be found that would
/// be satisfied by the provided Type.
///
- private ExtensionPoint DeduceExtensionPointFromType(TypeReference typeRef)
+ private ExtensionPoint? DeduceExtensionPointFromType(TypeReference typeRef)
{
var ep = GetExtensionPoint(typeRef);
if (ep != null)
@@ -305,7 +305,7 @@ private ExtensionPoint DeduceExtensionPointFromType(TypeReference typeRef)
return ep;
}
- TypeReference baseType = typeDef.BaseType;
+ TypeReference? baseType = typeDef.BaseType;
return baseType != null && baseType.FullName != "System.Object"
? DeduceExtensionPointFromType(baseType)
: null;
@@ -426,7 +426,7 @@ private void ProcessCandidateAssembly(string filePath, bool fromWildCard)
// Do we already have a copy of the same assembly at a different path?
//if (_assemblies.ByName.ContainsKey(assemblyName))
- if (_assemblies.ByName.TryGetValue(assemblyName, out ExtensionAssembly existing))
+ if (_assemblies.ByName.TryGetValue(assemblyName, out ExtensionAssembly? existing))
{
if (candidateAssembly.IsBetterVersionOf(existing))
_assemblies.ByName[assemblyName] = candidateAssembly;
@@ -449,7 +449,7 @@ private void ProcessCandidateAssembly(string filePath, bool fromWildCard)
}
// Dictionary containing all directory paths already visited.
- private readonly Dictionary _visited = new Dictionary();
+ private readonly Dictionary _visited = new Dictionary();
private bool WasVisited(string path, bool fromWildcard)
{
@@ -476,8 +476,9 @@ internal void FindExtensionsInAssembly(ExtensionAssembly extensionAssembly)
return;
}
- IRuntimeFramework assemblyTargetFramework = null;
+ IRuntimeFramework? assemblyTargetFramework = null;
#if NETFRAMEWORK
+#if FIXED
// Use special properties provided by our backport of RuntimeInformation
Version currentVersion = RuntimeInformation.FrameworkVersion;
var frameworkName = extensionAssembly.FrameworkName;
@@ -494,6 +495,7 @@ internal void FindExtensionsInAssembly(ExtensionAssembly extensionAssembly)
return;
}
}
+#endif
#endif
foreach (var extensionType in extensionAssembly.Assembly.MainModule.GetTypes())
@@ -506,7 +508,7 @@ internal void FindExtensionsInAssembly(ExtensionAssembly extensionAssembly)
// TODO: This is a remnant of older code. In principle, this should be generalized
// to something like "HostVersion". However, this can safely remain until
// we separate ExtensionManager into its own assembly.
- string versionArg = extensionAttr.GetNamedArgument("EngineVersion") as string;
+ string? versionArg = extensionAttr.GetNamedArgument(nameof(ExtensionAttribute.EngineVersion)) as string;
if (versionArg != null)
{
if (new Version(versionArg) > CURRENT_ENGINE_VERSION)
@@ -516,21 +518,21 @@ internal void FindExtensionsInAssembly(ExtensionAssembly extensionAssembly)
}
}
+ string? extensionAttrPath = (string?)extensionAttr.GetNamedArgument(nameof(ExtensionAttribute.Path));
var node = new ExtensionNode(extensionAssembly.FilePath, extensionAssembly.AssemblyVersion, extensionType.FullName, assemblyTargetFramework)
{
- Path = extensionAttr.GetNamedArgument("Path") as string,
- Description = extensionAttr.GetNamedArgument("Description") as string
+ Description = (string?)extensionAttr.GetNamedArgument(nameof(ExtensionAttribute.Description)),
};
- object enabledArg = extensionAttr.GetNamedArgument("Enabled");
+ object? enabledArg = extensionAttr.GetNamedArgument(nameof(ExtensionAttribute.Enabled));
node.Enabled = enabledArg == null || (bool)enabledArg;
log.Info(" Found ExtensionAttribute on Type " + extensionType.Name);
foreach (var attr in extensionType.GetAttributes("NUnit.Engine.Extensibility.ExtensionPropertyAttribute"))
{
- string name = attr.ConstructorArguments[0].Value as string;
- string value = attr.ConstructorArguments[1].Value as string;
+ string? name = attr.ConstructorArguments[0].Value as string;
+ string? value = attr.ConstructorArguments[1].Value as string;
if (name != null && value != null)
{
@@ -541,8 +543,8 @@ internal void FindExtensionsInAssembly(ExtensionAssembly extensionAssembly)
_extensions.Add(node);
- ExtensionPoint ep;
- if (node.Path == null)
+ ExtensionPoint? ep;
+ if (extensionAttrPath == null)
{
ep = DeduceExtensionPointFromType(extensionType);
if (ep == null)
@@ -557,6 +559,8 @@ internal void FindExtensionsInAssembly(ExtensionAssembly extensionAssembly)
}
else
{
+ node.Path = extensionAttrPath;
+
// TODO: Remove need for the cast
ep = GetExtensionPoint(node.Path) as ExtensionPoint;
if (ep == null)
@@ -583,7 +587,7 @@ internal void FindExtensionsInAssembly(ExtensionAssembly extensionAssembly)
///
/// The executing runner
/// The extension we are attempting to load
- internal bool CanLoadTargetFramework(Assembly runnerAsm, ExtensionAssembly extensionAsm)
+ internal bool CanLoadTargetFramework(Assembly? runnerAsm, ExtensionAssembly extensionAsm)
{
if (runnerAsm == null)
return true;
diff --git a/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionNode.cs b/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionNode.cs
index 031b2d914..ab4b12981 100644
--- a/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionNode.cs
+++ b/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionNode.cs
@@ -2,11 +2,8 @@
using System;
using System.Collections.Generic;
-using System.Reflection;
-
-#if !NETFRAMEWORK
using System.Linq;
-#endif
+using System.Reflection;
namespace NUnit.Engine.Extensibility
{
@@ -17,8 +14,8 @@ namespace NUnit.Engine.Extensibility
///
public class ExtensionNode : IExtensionNode
{
- private object _extensionObject;
- private Dictionary> _properties = new Dictionary>();
+ private object? _extensionObject;
+ private readonly Dictionary> _properties = new Dictionary>();
///
@@ -28,7 +25,7 @@ public class ExtensionNode : IExtensionNode
/// The version of the extension assembly.
/// The full name of the Type of the extension object.
/// The target framework of the extension assembly.
- public ExtensionNode(string assemblyPath, Version assemblyVersion, string typeName, IRuntimeFramework targetFramework)
+ public ExtensionNode(string assemblyPath, Version assemblyVersion, string typeName, IRuntimeFramework? targetFramework)
{
AssemblyPath = assemblyPath;
AssemblyVersion = assemblyVersion;
@@ -45,7 +42,7 @@ public ExtensionNode(string assemblyPath, Version assemblyVersion, string typeNa
///
/// The TargetFramework of the extension assembly.
///
- public IRuntimeFramework TargetFramework { get; }
+ public IRuntimeFramework? TargetFramework { get; }
///
/// Gets or sets a value indicating whether this is enabled.
@@ -58,12 +55,12 @@ public ExtensionNode(string assemblyPath, Version assemblyVersion, string typeNa
/// this Extension is intended. This identifier may be supplied by the attribute
/// marking the extension or deduced by NUnit from the Type of the extension class.
///
- public string Path { get; set; }
+ public string Path { get; set; } = string.Empty; // TODO: Set in non-public constructor and remove public setter.
///
/// An optional description of what the extension does.
///
- public string Description { get; set; }
+ public string? Description { get; set; }
///
/// Gets a collection of the names of all this extension's properties
@@ -84,7 +81,7 @@ public IEnumerable GetValues(string name)
if (_properties.ContainsKey(name))
return _properties[name];
else
- return new string[0];
+ return Enumerable.Empty();
}
///
@@ -121,25 +118,20 @@ public object CreateExtensionObject(params object[] args)
{
#if !NETFRAMEWORK
var assembly = Assembly.LoadFrom(AssemblyPath);
- var typeinfo = assembly.DefinedTypes.FirstOrDefault(t => t.FullName == TypeName);
- if (typeinfo == null)
- {
- return null;
- }
- return Activator.CreateInstance(typeinfo.AsType(), args);
+ var type = assembly.GetType(TypeName, throwOnError: true)!;
+ return Activator.CreateInstance(type, args)!;
#else
- return AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(AssemblyPath, TypeName, false, 0, null, args, null, null);
+ return AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(AssemblyPath, TypeName, false, 0, null, args, null, null)!;
#endif
}
public void AddProperty(string name, string val)
{
- if (_properties.ContainsKey(name))
- _properties[name].Add(val);
+ if (_properties.TryGetValue(name, out List? list))
+ list.Add(val);
else
{
- var list = new List();
- list.Add(val);
+ list = new List { val };
_properties.Add(name, list);
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionPoint.cs b/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionPoint.cs
index ef1937523..5f71a0a8f 100644
--- a/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionPoint.cs
+++ b/src/NUnitEngine/nunit.engine.core/Extensibility/ExtensionPoint.cs
@@ -19,7 +19,7 @@ public class ExtensionPoint : IExtensionPoint
public ExtensionPoint(string path, Type type)
{
Path = path;
- TypeName = type.FullName;
+ TypeName = type.FullName!;
Extensions = new List();
}
@@ -31,7 +31,7 @@ public ExtensionPoint(string path, Type type)
///
/// Gets and sets the optional description of this extension point.
///
- public string Description { get; set; }
+ public string? Description { get; set; }
///
/// Gets the FullName of the Type required for any extension to be installed at this extension point.
diff --git a/src/NUnitEngine/nunit.engine.core/Guard.cs b/src/NUnitEngine/nunit.engine.core/Guard.cs
index 80da62849..4f7623bf3 100644
--- a/src/NUnitEngine/nunit.engine.core/Guard.cs
+++ b/src/NUnitEngine/nunit.engine.core/Guard.cs
@@ -1,6 +1,8 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
namespace NUnit.Common
{
@@ -21,6 +23,22 @@ public static void ArgumentNotNull(object value, string name)
throw new ArgumentNullException("Argument " + name + " must not be null", name);
}
+ ///
+ /// Throws an exception if a result is null
+ ///
+ /// The type of the to check.
+ /// The value to check.
+ /// Compiler supplied parameter for the expression.
+ /// Value of if not null, throws otherwise.
+ ///
+ public static T ShouldNotBeNull(this T? result, [CallerArgumentExpression(nameof(result))] string expression = "") where T : class
+ {
+ if (result == null)
+ throw new InvalidOperationException($"Result {expression} must not be null");
+
+ return result;
+ }
+
///
/// Throws an exception if a string argument is null or empty
///
@@ -40,7 +58,7 @@ public static void ArgumentNotNullOrEmpty(string value, string name)
/// The condition that must be met
/// The exception message to be used
/// The name of the argument
- public static void ArgumentInRange(bool condition, string message, string paramName)
+ public static void ArgumentInRange([DoesNotReturnIf(false)] bool condition, string message, string paramName)
{
if (!condition)
throw new ArgumentOutOfRangeException(paramName, message);
@@ -52,7 +70,7 @@ public static void ArgumentInRange(bool condition, string message, string paramN
/// The condition that must be met
/// The exception message to be used
/// The name of the argument
- public static void ArgumentValid(bool condition, string message, string paramName)
+ public static void ArgumentValid([DoesNotReturnIf(false)] bool condition, string message, string paramName)
{
if (!condition)
throw new ArgumentException(message, paramName);
@@ -63,7 +81,7 @@ public static void ArgumentValid(bool condition, string message, string paramNam
///
/// The condition that must be met
/// The exception message to be used
- public static void OperationValid(bool condition, string message)
+ public static void OperationValid([DoesNotReturnIf(false)] bool condition, string message)
{
if (!condition)
throw new InvalidOperationException(message);
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/AssemblyHelper.cs b/src/NUnitEngine/nunit.engine.core/Internal/AssemblyHelper.cs
index df68aadff..d88494f98 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/AssemblyHelper.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/AssemblyHelper.cs
@@ -18,7 +18,7 @@ public static class AssemblyHelper
/// The path.
public static string GetDirectoryName(Assembly assembly)
{
- return Path.GetDirectoryName(GetAssemblyPath(assembly));
+ return Path.GetDirectoryName(GetAssemblyPath(assembly))!;
}
///
@@ -30,17 +30,24 @@ public static string GetDirectoryName(Assembly assembly)
/// The path.
public static string GetAssemblyPath(Assembly assembly)
{
- string codeBase = assembly.CodeBase;
+#if NETFRAMEWORK
+ // https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.location
+ // .NET Framework only:
+ // If the loaded file was shadow-copied, the location is that of the file after being shadow-copied.
+ // To get the location before the file has been shadow-copied, use the CodeBase property.
+ string? codeBase = assembly.CodeBase;
- if (IsFileUri(codeBase))
+ if (codeBase != null && IsFileUri(codeBase))
return GetAssemblyPathFromCodeBase(codeBase);
+#endif
return assembly.Location;
}
+#if NETFRAMEWORK
private static bool IsFileUri(string uri)
{
- return uri.ToLower().StartsWith(Uri.UriSchemeFile);
+ return uri.StartsWith(Uri.UriSchemeFile, StringComparison.OrdinalIgnoreCase);
}
///
@@ -69,5 +76,6 @@ public static string GetAssemblyPathFromCodeBase(string codeBase)
return codeBase.Substring(start);
}
+#endif
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/Backports/RuntimeInformation.cs b/src/NUnitEngine/nunit.engine.core/Internal/Backports/RuntimeInformation.cs
index cd3dedf3d..9ecb10b89 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/Backports/RuntimeInformation.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/Backports/RuntimeInformation.cs
@@ -36,13 +36,14 @@ static RuntimeInformation()
{
FrameworkName = ".NET Framework";
+ RegistryKey? key = null;
switch (version.Major)
{
case 2:
- RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework");
+ key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework");
if (key != null)
{
- string installRoot = key.GetValue("InstallRoot") as string;
+ string? installRoot = key.GetValue("InstallRoot") as string;
if (installRoot != null)
{
if (Directory.Exists(System.IO.Path.Combine(installRoot, "v3.5")))
@@ -68,6 +69,8 @@ static RuntimeInformation()
}
break;
}
+
+ key?.Dispose();
}
FrameworkVersion = version;
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/CallerArgumentExpressionAttribute.cs b/src/NUnitEngine/nunit.engine.core/Internal/CallerArgumentExpressionAttribute.cs
new file mode 100644
index 000000000..f851c6a87
--- /dev/null
+++ b/src/NUnitEngine/nunit.engine.core/Internal/CallerArgumentExpressionAttribute.cs
@@ -0,0 +1,30 @@
+#if !NETCOREAPP
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Runtime.CompilerServices
+{
+ ///
+ /// Indicates that a parameter captures the expression passed for another parameter as a string.
+ ///
+ [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+ internal sealed class CallerArgumentExpressionAttribute : Attribute
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name of the parameter whose expression should be captured as a string.
+ public CallerArgumentExpressionAttribute(string parameterName)
+ {
+ ParameterName = parameterName;
+ }
+
+ ///
+ /// Gets the name of the parameter whose expression should be captured as a string.
+ ///
+ public string ParameterName { get; }
+ }
+}
+
+#endif
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/DomainDetailsBuilder.cs b/src/NUnitEngine/nunit.engine.core/Internal/DomainDetailsBuilder.cs
index b7f2d91f3..a3e3d6691 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/DomainDetailsBuilder.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/DomainDetailsBuilder.cs
@@ -22,7 +22,7 @@ internal static class DomainDetailsBuilder
///
/// Application domain to get details on.
/// An optional overall error message.
- public static string DetailsFor(AppDomain domain, string errMsg = null)
+ public static string DetailsFor(AppDomain domain, string? errMsg = null)
{
var sb = new StringBuilder();
if (errMsg != null) sb.AppendLine(errMsg);
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/ExceptionHelper.cs b/src/NUnitEngine/nunit.engine.core/Internal/ExceptionHelper.cs
index e336b7ac2..37e0f8ab7 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/ExceptionHelper.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/ExceptionHelper.cs
@@ -2,10 +2,13 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Reflection;
using System.Text;
using NUnit.Engine;
+#nullable enable
+
namespace NUnit.Common
{
internal static class ExceptionHelper
@@ -65,13 +68,15 @@ public static string BuildMessageAndStackTrace(Exception exception)
/// A string representation of the stack trace.
private static string GetSafeStackTrace(Exception exception)
{
+ const string NoStackTrace = "No stack trace available";
+
try
{
- return exception.StackTrace;
+ return exception.StackTrace ?? NoStackTrace;
}
catch (Exception)
{
- return "No stack trace available";
+ return NoStackTrace;
}
}
@@ -89,11 +94,11 @@ private static List FlattenExceptionHierarchy(Exception exception)
}
var reflectionException = exception as ReflectionTypeLoadException;
- if (reflectionException != null)
+ if (reflectionException != null && reflectionException.LoaderExceptions != null)
{
- result.AddRange(reflectionException.LoaderExceptions);
+ result.AddRange(reflectionException.LoaderExceptions.WhereNotNull());
- foreach (var innerException in reflectionException.LoaderExceptions)
+ foreach (var innerException in reflectionException.LoaderExceptions.WhereNotNull())
result.AddRange(FlattenExceptionHierarchy(innerException));
}
@@ -119,5 +124,19 @@ private static string GetExceptionMessage(Exception ex)
return ex.Message;
}
+
+ ///
+ /// Returns the specified sequence with all null references removed.
+ ///
+ /// The type of items in source.
+ /// An to filter.
+ ///
+ /// The sequence with all null references removed.
+ ///
+ private static IEnumerable WhereNotNull(this IEnumerable source)
+ where T : class
+ {
+ return source.Where(x => x is not null)!;
+ }
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/Default/Directory.cs b/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/Default/Directory.cs
index 1c0a74ad6..86864ca29 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/Default/Directory.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/Default/Directory.cs
@@ -39,7 +39,7 @@ public Directory(string path)
}
///
- public IDirectory Parent { get; private set; }
+ public IDirectory? Parent { get; private set; }
///
public string FullName => this.directory.FullName;
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/Default/File.cs b/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/Default/File.cs
index f14e12948..81a8a5cff 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/Default/File.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/Default/File.cs
@@ -1,6 +1,7 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
using System;
+using NUnit.Common;
using SIO = System.IO;
namespace NUnit.Engine.Internal.FileSystemAccess.Default
@@ -42,7 +43,7 @@ public File(string path)
throw new ArgumentException("Filename contains invalid characters.", nameof(path));
}
- var directory = SIO.Path.GetDirectoryName(path);
+ var directory = SIO.Path.GetDirectoryName(path)!;
if (directory.IndexOfAny(SIO.Path.GetInvalidPathChars()) > -1)
{
throw new ArgumentException("Directory contains invalid characters.", nameof(path));
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/IDirectory.cs b/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/IDirectory.cs
index 557fbc089..93cfc3e60 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/IDirectory.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/FileSystemAccess/IDirectory.cs
@@ -14,7 +14,7 @@ public interface IDirectory
/// Gets the parent directory.
///
/// The parent directory or if the instance denotes a root (such as '\', 'c:\' , '\\server\share').
- IDirectory Parent { get; }
+ IDirectory? Parent { get; }
///
/// Gets the full path of the directory.
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/Logging/InternalTrace.cs b/src/NUnitEngine/nunit.engine.core/Internal/Logging/InternalTrace.cs
index c688bc0d1..2fc193110 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/Logging/InternalTrace.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/Logging/InternalTrace.cs
@@ -1,6 +1,8 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
using System;
+using System.Diagnostics.CodeAnalysis;
+using NUnit.Common;
namespace NUnit.Engine.Internal
{
@@ -21,13 +23,14 @@ namespace NUnit.Engine.Internal
///
public static class InternalTrace
{
- private static InternalTraceWriter _traceWriter;
+ private static InternalTraceWriter? _traceWriter;
public static InternalTraceLevel DefaultTraceLevel { get; private set; }
///
/// Gets a flag indicating whether the InternalTrace is initialized
///
+ [MemberNotNullWhen(true, nameof(_traceWriter))]
public static bool Initialized { get; private set; }
///
@@ -60,7 +63,7 @@ public static void Initialize(string logName, InternalTraceLevel level)
///
public static Logger GetLogger(string name, InternalTraceLevel level)
{
- return new Logger(name, () => level, () => _traceWriter);
+ return new Logger(name, () => level, () => _traceWriter.ShouldNotBeNull());
}
///
@@ -68,7 +71,7 @@ public static Logger GetLogger(string name, InternalTraceLevel level)
///
public static Logger GetLogger(Type type, InternalTraceLevel level)
{
- return GetLogger(type.FullName, level);
+ return GetLogger(type.FullName ?? type.Name, level);
}
///
@@ -76,7 +79,7 @@ public static Logger GetLogger(Type type, InternalTraceLevel level)
///
public static Logger GetLogger(string name)
{
- return new Logger(name, () => DefaultTraceLevel, () => _traceWriter);
+ return new Logger(name, () => DefaultTraceLevel, () => _traceWriter.ShouldNotBeNull());
}
///
@@ -84,7 +87,7 @@ public static Logger GetLogger(string name)
///
public static Logger GetLogger(Type type)
{
- return GetLogger(type.FullName);
+ return GetLogger(type.FullName ?? type.Name);
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/Logging/InternalTraceWriter.cs b/src/NUnitEngine/nunit.engine.core/Internal/Logging/InternalTraceWriter.cs
index e114ebfb3..3eec1f901 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/Logging/InternalTraceWriter.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/Logging/InternalTraceWriter.cs
@@ -11,7 +11,7 @@ namespace NUnit.Engine.Internal
internal class InternalTraceWriter : TextWriter
{
TextWriter _writer;
- object _myLock = new object();
+ readonly object _myLock = new object();
///
/// Construct an InternalTraceWriter that writes to a file.
@@ -61,7 +61,7 @@ public override void Write(char value)
/// Writes a string to the text string or stream.
///
/// The string to write.
- public override void Write(string value)
+ public override void Write(string? value)
{
lock (_myLock)
{
@@ -73,7 +73,7 @@ public override void Write(string value)
/// Writes a string followed by a line terminator to the text string or stream.
///
/// The string to write. If is null, only the line terminator is written.
- public override void WriteLine(string value)
+ public override void WriteLine(string? value)
{
lock (_myLock)
{
@@ -93,7 +93,7 @@ protected override void Dispose(bool disposing)
{
_writer.Flush();
_writer.Dispose();
- _writer = null;
+ _writer = null!;
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/PathUtils.cs b/src/NUnitEngine/nunit.engine.core/Internal/PathUtils.cs
index 5c5aedf71..659388949 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/PathUtils.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/PathUtils.cs
@@ -38,17 +38,19 @@ public static bool IsAssemblyFileType(string path)
/// Returns the relative path from a base directory to another
/// directory or file.
///
- public static string RelativePath( string from, string to )
+ public static string? RelativePath( string from, string to )
{
if (from == null)
throw new ArgumentNullException (from);
if (to == null)
throw new ArgumentNullException (to);
- string toPathRoot = Path.GetPathRoot(to);
+ string? toPathRoot = Path.GetPathRoot(to);
if (toPathRoot == null || toPathRoot == string.Empty)
return to;
- string fromPathRoot = Path.GetPathRoot(from);
+ string? fromPathRoot = Path.GetPathRoot(from);
+ if (fromPathRoot == null || fromPathRoot == string.Empty)
+ return null;
if (!PathsEqual(toPathRoot, fromPathRoot))
return null;
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/ProcessUtils.cs b/src/NUnitEngine/nunit.engine.core/Internal/ProcessUtils.cs
index 6655ca610..055d2c99e 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/ProcessUtils.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/ProcessUtils.cs
@@ -34,7 +34,7 @@ public static class ProcessUtils
/// Escapes arbitrary values so that the process receives the exact string you intend and injection is impossible.
/// Spec: https://docs.microsoft.com/en-gb/windows/desktop/api/shellapi/nf-shellapi-commandlinetoargvw
///
- public static void EscapeProcessArgument(this StringBuilder builder, string literalValue, bool alwaysQuote = false)
+ public static void EscapeProcessArgument(this StringBuilder builder, string? literalValue, bool alwaysQuote = false)
{
if (string.IsNullOrEmpty(literalValue))
{
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/ProvidedPathsAssemblyResolver.cs b/src/NUnitEngine/nunit.engine.core/Internal/ProvidedPathsAssemblyResolver.cs
index 803775e45..8b178e7bd 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/ProvidedPathsAssemblyResolver.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/ProvidedPathsAssemblyResolver.cs
@@ -10,7 +10,7 @@ namespace NUnit.Engine.Internal
{
public class ProvidedPathsAssemblyResolver
{
- static ILogger log = InternalTrace.GetLogger(typeof(ProvidedPathsAssemblyResolver));
+ static readonly ILogger log = InternalTrace.GetLogger(typeof(ProvidedPathsAssemblyResolver));
public ProvidedPathsAssemblyResolver()
{
@@ -34,7 +34,7 @@ public void AddPath(string dirPath)
public void AddPathFromFile(string filePath)
{
- string dirPath = Path.GetDirectoryName(filePath);
+ string dirPath = Path.GetDirectoryName(filePath)!;
AddPath(dirPath);
}
@@ -45,15 +45,15 @@ public void RemovePath(string dirPath)
public void RemovePathFromFile(string filePath)
{
- string dirPath = Path.GetDirectoryName(filePath);
+ string dirPath = Path.GetDirectoryName(filePath)!;
RemovePath(dirPath);
}
- Assembly AssemblyResolve(object sender, ResolveEventArgs args)
+ Assembly? AssemblyResolve(object? sender, ResolveEventArgs args)
{
foreach (string path in _resolutionPaths)
{
- string filename = new AssemblyName(args.Name).Name + ".dll";
+ string filename = new AssemblyName(args.Name!).Name + ".dll";
string fullPath = Path.Combine(path, filename);
try
{
@@ -71,6 +71,6 @@ Assembly AssemblyResolve(object sender, ResolveEventArgs args)
return null;
}
- List _resolutionPaths;
+ readonly List _resolutionPaths;
}
}
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/ResultHelper.cs b/src/NUnitEngine/nunit.engine.core/Internal/ResultHelper.cs
index 9e68d08da..574ceefb2 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/ResultHelper.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/ResultHelper.cs
@@ -29,7 +29,7 @@ public static class ResultHelper
/// The name of the .
/// The full name of the .
/// A TestEngineResult with a single top-level element.
- public static TestEngineResult Aggregate(this TestEngineResult result, string elementName, string suiteType, string id, string name, string fullName)
+ public static TestEngineResult Aggregate(this TestEngineResult result, string elementName, string suiteType, string id, string? name, string? fullName)
{
return new TestEngineResult(Aggregate(elementName, suiteType, id, name, fullName, result.XmlNodes));
}
@@ -43,7 +43,7 @@ public static TestEngineResult Aggregate(this TestEngineResult result, string el
/// The name of the .
/// The full name of the .
/// A TestEngineResult with a single top-level element.
- public static TestEngineResult Aggregate(this TestEngineResult result, string elementName, string id, string name, string fullName)
+ public static TestEngineResult Aggregate(this TestEngineResult result, string elementName, string id, string? name, string? fullName)
{
return new TestEngineResult(Aggregate(elementName, id, name, fullName, result.XmlNodes));
}
@@ -96,7 +96,7 @@ public static TestEngineResult Merge(IList results)
/// The full name to associated with the root node.
/// A collection of XmlNodes to aggregate
/// A single XmlNode containing the aggregated list of XmlNodes.
- public static XmlNode Aggregate(string elementName, string id, string name, string fullName, IList resultNodes)
+ public static XmlNode Aggregate(string elementName, string id, string? name, string? fullName, IList resultNodes)
{
return Aggregate(elementName, null, id, name, fullName, resultNodes);
}
@@ -110,7 +110,7 @@ public static XmlNode Aggregate(string elementName, string id, string name, stri
/// The full name to associated with the root node.
/// A collection of XmlNodes to aggregate
/// A single XmlNode containing the aggregated list of XmlNodes.
- public static XmlNode Aggregate(string elementName, string testType, string id, string name, string fullName, IList resultNodes)
+ public static XmlNode Aggregate(string elementName, string? testType, string id, string? name, string? fullName, IList resultNodes)
{
XmlNode combinedNode = XmlHelper.CreateTopLevelElement(elementName);
if (testType != null)
@@ -123,8 +123,8 @@ public static XmlNode Aggregate(string elementName, string testType, string id,
combinedNode.AddAttribute("runstate", "Runnable"); // If not, we would not have gotten this far
string aggregateResult = "Inconclusive";
- string aggregateLabel = null;
- string aggregateSite = null;
+ string? aggregateLabel = null;
+ string? aggregateSite = null;
//double totalDuration = 0.0d;
int testcasecount = 0;
@@ -142,12 +142,12 @@ public static XmlNode Aggregate(string elementName, string testType, string id,
{
testcasecount += node.GetAttribute("testcasecount", 0);
- XmlAttribute resultAttribute = node.Attributes["result"];
+ XmlAttribute? resultAttribute = node.Attributes?["result"];
if (resultAttribute != null)
{
isTestRunResult = true;
- string label = node.GetAttribute("label");
+ string? label = node.GetAttribute("label");
switch (resultAttribute.Value)
{
@@ -183,8 +183,11 @@ public static XmlNode Aggregate(string elementName, string testType, string id,
asserts += node.GetAttribute("asserts", 0);
}
- XmlNode import = combinedNode.OwnerDocument.ImportNode(node, true);
- combinedNode.AppendChild(import);
+ if (combinedNode.OwnerDocument != null)
+ {
+ XmlNode import = combinedNode.OwnerDocument.ImportNode(node, true);
+ combinedNode.AppendChild(import);
+ }
}
combinedNode.AddAttribute("testcasecount", testcasecount.ToString());
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/TcpChannelUtils.ObservableServerChannelSinkProvider.cs b/src/NUnitEngine/nunit.engine.core/Internal/TcpChannelUtils.ObservableServerChannelSinkProvider.cs
index 3634cd237..750b9f084 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/TcpChannelUtils.ObservableServerChannelSinkProvider.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/TcpChannelUtils.ObservableServerChannelSinkProvider.cs
@@ -32,7 +32,7 @@ public IServerChannelSink CreateSink(IChannelReceiver channel)
return new ObservableServerChannelSink(_currentMessageCounter, Next.CreateSink(channel));
}
- public IServerChannelSinkProvider Next { get; set; }
+ public IServerChannelSinkProvider? Next { get; set; }
private sealed class ObservableServerChannelSink : IServerChannelSink
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/TcpChannelUtils.cs b/src/NUnitEngine/nunit.engine.core/Internal/TcpChannelUtils.cs
index 22527ba5f..8eefcf4ae 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/TcpChannelUtils.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/TcpChannelUtils.cs
@@ -28,7 +28,9 @@ public static partial class TcpChannelUtils
/// The rate limit of the channel to create.
/// An optional counter to provide the ability to wait for all current messages.
/// A configured with the given name and port.
- private static TcpChannel CreateTcpChannel(string name, int port, int limit, CurrentMessageCounter currentMessageCounter = null)
+#pragma warning disable IDE0060 // Remove unused parameter
+ private static TcpChannel CreateTcpChannel(string name, int port, int limit, CurrentMessageCounter? currentMessageCounter = null)
+#pragma warning restore IDE0060 // Remove unused parameter
{
var props = new Dictionary
{
@@ -58,7 +60,7 @@ private static TcpChannel CreateTcpChannel(string name, int port, int limit, Cur
///
/// An optional counter to provide the ability to wait for all current messages.
/// The specified or if it cannot be found and created.
- public static TcpChannel GetTcpChannel(CurrentMessageCounter currentMessageCounter = null)
+ public static TcpChannel? GetTcpChannel(CurrentMessageCounter? currentMessageCounter = null)
{
return GetTcpChannel("", 0, 2, currentMessageCounter);
}
@@ -72,7 +74,7 @@ public static TcpChannel GetTcpChannel(CurrentMessageCounter currentMessageCount
/// The port to use if the channel must be created.
/// An optional counter to provide the ability to wait for all current messages.
/// The specified or if it cannot be found and created.
- public static TcpChannel GetTcpChannel(string name, int port, CurrentMessageCounter currentMessageCounter = null)
+ public static TcpChannel? GetTcpChannel(string name, int port, CurrentMessageCounter? currentMessageCounter = null)
{
return GetTcpChannel(name, port, 2, currentMessageCounter);
}
@@ -87,7 +89,7 @@ public static TcpChannel GetTcpChannel(string name, int port, CurrentMessageCoun
/// The client connection limit or negative for the default.
/// An optional counter to provide the ability to wait for all current messages.
/// The specified or if it cannot be found and created.
- public static TcpChannel GetTcpChannel(string name, int port, int limit, CurrentMessageCounter currentMessageCounter = null)
+ public static TcpChannel? GetTcpChannel(string name, int port, int limit, CurrentMessageCounter? currentMessageCounter = null)
{
var existingChannel = ChannelServices.GetChannel(name) as TcpChannel;
if (existingChannel != null) return existingChannel;
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyLoadContext.cs b/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyLoadContext.cs
index c9d9661cb..54236f7b2 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyLoadContext.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyLoadContext.cs
@@ -22,14 +22,14 @@ internal sealed class TestAssemblyLoadContext : AssemblyLoadContext
public TestAssemblyLoadContext(string testAssemblyPath)
{
_resolver = new TestAssemblyResolver(this, testAssemblyPath);
- _basePath = Path.GetDirectoryName(testAssemblyPath);
+ _basePath = Path.GetDirectoryName(testAssemblyPath)!;
_runtimeResolver = new AssemblyDependencyResolver(testAssemblyPath);
#if NET8_0_OR_GREATER
AppContext.SetData("APP_CONTEXT_BASE_DIRECTORY", _basePath);
#endif
}
- protected override Assembly Load(AssemblyName name)
+ protected override Assembly? Load(AssemblyName name)
{
log.Debug("Loading {0} assembly", name);
@@ -78,7 +78,7 @@ protected override Assembly Load(AssemblyName name)
return loadedAssembly;
}
- return loadedAssembly;
+ return null;
}
protected override IntPtr LoadUnmanagedDll(string name)
@@ -92,7 +92,7 @@ protected override IntPtr LoadUnmanagedDll(string name)
return loadedDllHandle;
}
- string runtimeResolverPath = _runtimeResolver.ResolveUnmanagedDllToPath(name);
+ string? runtimeResolverPath = _runtimeResolver.ResolveUnmanagedDllToPath(name);
if (string.IsNullOrEmpty(runtimeResolverPath) == false &&
File.Exists(runtimeResolverPath))
{
@@ -101,7 +101,7 @@ protected override IntPtr LoadUnmanagedDll(string name)
if (loadedDllHandle != IntPtr.Zero)
{
- log.Info("Unmanaged DLL {0} ({1}) is loaded using the deps.json info", name, runtimeResolverPath);
+ log.Info("Unmanaged DLL {0} ({1}) is loaded using the deps.json info", name, runtimeResolverPath!);
return loadedDllHandle;
}
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyResolver.cs b/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyResolver.cs
index 60e71efeb..18ef04c96 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyResolver.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyResolver.cs
@@ -5,8 +5,10 @@
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.DependencyModel.Resolution;
using Microsoft.Win32;
+using NUnit.Common;
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -31,7 +33,7 @@ internal sealed class TestAssemblyResolver : IDisposable
static TestAssemblyResolver()
{
- INSTALL_DIR = GetDotNetInstallDirectory();
+ INSTALL_DIR = GetDotNetInstallDirectory().ShouldNotBeNull();
WINDOWS_DESKTOP_DIR = Path.Combine(INSTALL_DIR, "shared", "Microsoft.WindowsDesktop.App");
ASP_NET_CORE_DIR = Path.Combine(INSTALL_DIR, "shared", "Microsoft.AspNetCore.App");
}
@@ -45,6 +47,7 @@ public TestAssemblyResolver(AssemblyLoadContext loadContext, string testAssembly
_loadContext.Resolving += OnResolving;
}
+ [MemberNotNull(nameof(ResolutionStrategies))]
private void InitializeResolutionStrategies(AssemblyLoadContext loadContext, string testAssemblyPath)
{
// First, looking only at direct references by the test assembly, try to determine if
@@ -82,16 +85,16 @@ public void Dispose()
_loadContext.Resolving -= OnResolving;
}
- public Assembly Resolve(AssemblyLoadContext context, AssemblyName assemblyName)
+ public Assembly? Resolve(AssemblyLoadContext context, AssemblyName assemblyName)
{
return OnResolving(context, assemblyName);
}
- private Assembly OnResolving(AssemblyLoadContext loadContext, AssemblyName assemblyName)
+ private Assembly? OnResolving(AssemblyLoadContext loadContext, AssemblyName assemblyName)
{
if (loadContext == null) throw new ArgumentNullException("context");
- Assembly loadedAssembly;
+ Assembly? loadedAssembly;
foreach (var strategy in ResolutionStrategies)
if (strategy.TryToResolve(loadContext, assemblyName, out loadedAssembly))
return loadedAssembly;
@@ -105,19 +108,19 @@ private Assembly OnResolving(AssemblyLoadContext loadContext, AssemblyName assem
public abstract class ResolutionStrategy
{
public abstract bool TryToResolve(
- AssemblyLoadContext loadContext, AssemblyName assemblyName, out Assembly loadedAssembly);
+ AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly);
}
public class TrustedPlatformAssembliesStrategy : ResolutionStrategy
{
public override bool TryToResolve(
- AssemblyLoadContext loadContext, AssemblyName assemblyName, out Assembly loadedAssembly)
+ AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly)
{
return TryLoadFromTrustedPlatformAssemblies(loadContext, assemblyName, out loadedAssembly);
}
private static bool TryLoadFromTrustedPlatformAssemblies(
- AssemblyLoadContext loadContext, AssemblyName assemblyName, out Assembly loadedAssembly)
+ AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly)
{
// https://learn.microsoft.com/en-us/dotnet/core/dependency-loading/default-probing
loadedAssembly = null;
@@ -149,7 +152,7 @@ bool FileMatchesAssembly(string fileName) =>
public class RuntimeLibrariesStrategy : ResolutionStrategy
{
- private DependencyContext _dependencyContext;
+ private DependencyContext? _dependencyContext;
private readonly ICompilationAssemblyResolver _assemblyResolver;
public RuntimeLibrariesStrategy(AssemblyLoadContext loadContext, string testAssemblyPath)
@@ -158,15 +161,22 @@ public RuntimeLibrariesStrategy(AssemblyLoadContext loadContext, string testAsse
_assemblyResolver = new CompositeCompilationAssemblyResolver(new ICompilationAssemblyResolver[]
{
- new AppBaseCompilationAssemblyResolver(Path.GetDirectoryName(testAssemblyPath)),
+ new AppBaseCompilationAssemblyResolver(Path.GetDirectoryName(testAssemblyPath)!),
new ReferenceAssemblyPathResolver(),
new PackageCompilationAssemblyResolver()
});
}
public override bool TryToResolve(
- AssemblyLoadContext loadContext, AssemblyName assemblyName, out Assembly loadedAssembly)
+ AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly)
{
+ if (_dependencyContext == null)
+ {
+ // TODO: Is this the intended behavior?
+ loadedAssembly = null;
+ return false;
+ }
+
foreach (var library in _dependencyContext.RuntimeLibraries)
{
var wrapper = new CompilationLibrary(
@@ -211,7 +221,7 @@ public AdditionalDirectoryStrategy(string frameworkDirectory)
}
public override bool TryToResolve(
- AssemblyLoadContext loadContext, AssemblyName assemblyName, out Assembly loadedAssembly)
+ AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly)
{
loadedAssembly = null;
if (assemblyName.Version == null)
@@ -248,27 +258,27 @@ public override bool TryToResolve(
#region HelperMethods
- private static string GetDotNetInstallDirectory()
+ private static string? GetDotNetInstallDirectory()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// Running on Windows so use registry
if (Environment.Is64BitProcess)
{
- RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\dotnet\SetUp\InstalledVersions\x64\sharedHost\");
- return (string)key?.GetValue("Path");
+ using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\dotnet\SetUp\InstalledVersions\x64\sharedHost\"))
+ return (string?)key?.GetValue("Path");
}
else
{
- RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\dotnet\SetUp\InstalledVersions\x86\");
- return (string)key?.GetValue("InstallLocation");
+ using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\dotnet\SetUp\InstalledVersions\x86\"))
+ return (string?)key?.GetValue("InstallLocation");
}
}
else
return "/usr/shared/dotnet/";
}
- private static string FindBestVersionDir(string libraryDir, Version targetVersion)
+ private static string? FindBestVersionDir(string libraryDir, Version targetVersion)
{
string target = targetVersion.ToString();
Version bestVersion = new Version(0, 0);
diff --git a/src/NUnitEngine/nunit.engine.core/Internal/XmlHelper.cs b/src/NUnitEngine/nunit.engine.core/Internal/XmlHelper.cs
index 72bc5da1f..25c97b8b1 100644
--- a/src/NUnitEngine/nunit.engine.core/Internal/XmlHelper.cs
+++ b/src/NUnitEngine/nunit.engine.core/Internal/XmlHelper.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
+using NUnit.Common;
namespace System.Runtime.CompilerServices
{
@@ -27,14 +28,14 @@ public static XmlNode CreateTopLevelElement(string name)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml( "<" + name + "/>" );
- return doc.FirstChild;
+ return doc.FirstChild.ShouldNotBeNull();
}
public static XmlNode CreateXmlNode(string xml)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
- return doc.FirstChild;
+ return doc.FirstChild.ShouldNotBeNull();
}
///
@@ -45,9 +46,11 @@ public static XmlNode CreateXmlNode(string xml)
/// The value of the attribute.
public static void AddAttribute(this XmlNode node, string name, string value)
{
- XmlAttribute attr = node.OwnerDocument.CreateAttribute(name);
+ XmlAttribute attr = node.OwnerDocument.ShouldNotBeNull().CreateAttribute(name);
attr.Value = value;
- node.Attributes.Append(attr);
+
+ // TODO: How to create the Attributes collection if it doesn't exist?
+ node.Attributes!.Append(attr);
}
///
@@ -58,7 +61,7 @@ public static void AddAttribute(this XmlNode node, string name, string value)
/// The newly created child element
public static XmlNode AddElement(this XmlNode node, string name)
{
- XmlNode childNode = node.OwnerDocument.CreateElement(name);
+ XmlNode childNode = node.OwnerDocument.ShouldNotBeNull().CreateElement(name);
node.AppendChild(childNode);
return childNode;
}
@@ -74,7 +77,7 @@ public static XmlNode AddElement(this XmlNode node, string name)
public static XmlNode AddElementWithCDataSection(this XmlNode node, string name, string data)
{
XmlNode childNode = node.AddElement(name);
- childNode.AppendChild(node.OwnerDocument.CreateCDataSection(data));
+ childNode.AppendChild(node.OwnerDocument.ShouldNotBeNull().CreateCDataSection(data));
return childNode;
}
@@ -84,9 +87,9 @@ public static XmlNode AddElementWithCDataSection(this XmlNode node, string name,
/// The result.
/// The name.
///
- public static string GetAttribute(this XmlNode result, string name)
+ public static string? GetAttribute(this XmlNode result, string name)
{
- XmlAttribute attr = result.Attributes[name];
+ XmlAttribute? attr = result.Attributes?[name];
return attr == null ? null : attr.Value;
}
@@ -100,7 +103,7 @@ public static string GetAttribute(this XmlNode result, string name)
///
public static int GetAttribute(this XmlNode result, string name, int defaultValue)
{
- XmlAttribute attr = result.Attributes[name];
+ XmlAttribute? attr = result.Attributes?[name];
return attr == null
? defaultValue
@@ -116,7 +119,7 @@ public static int GetAttribute(this XmlNode result, string name, int defaultValu
///
public static double GetAttribute(this XmlNode result, string name, double defaultValue)
{
- XmlAttribute attr = result.Attributes[name];
+ XmlAttribute? attr = result.Attributes?[name];
return attr == null
? defaultValue
@@ -132,7 +135,7 @@ public static double GetAttribute(this XmlNode result, string name, double defau
///
public static DateTime GetAttribute(this XmlNode result, string name, DateTime defaultValue)
{
- string dateStr = GetAttribute(result, name);
+ string? dateStr = GetAttribute(result, name);
if (dateStr == null)
return defaultValue;
diff --git a/src/NUnitEngine/nunit.engine.core/RunTestsCallbackHandler.cs b/src/NUnitEngine/nunit.engine.core/RunTestsCallbackHandler.cs
index 704c81c24..1a25bde54 100644
--- a/src/NUnitEngine/nunit.engine.core/RunTestsCallbackHandler.cs
+++ b/src/NUnitEngine/nunit.engine.core/RunTestsCallbackHandler.cs
@@ -9,18 +9,18 @@ namespace NUnit.Engine
{
public class RunTestsCallbackHandler : MarshalByRefObject, ICallbackEventHandler
{
- private ITestEventListener _listener;
+ private readonly ITestEventListener _listener;
- public string Result { get; private set; }
+ public string? Result { get; private set; }
- public RunTestsCallbackHandler(ITestEventListener listener)
+ public RunTestsCallbackHandler(ITestEventListener? listener)
{
_listener = listener ?? new NullListener();
}
public override object InitializeLifetimeService()
{
- return null;
+ return null!;
}
public string GetCallbackResult()
diff --git a/src/NUnitEngine/nunit.engine.core/Runners/DomainManager.cs b/src/NUnitEngine/nunit.engine.core/Runners/DomainManager.cs
index 567326fa7..55aff9dbd 100644
--- a/src/NUnitEngine/nunit.engine.core/Runners/DomainManager.cs
+++ b/src/NUnitEngine/nunit.engine.core/Runners/DomainManager.cs
@@ -12,6 +12,7 @@
using System.Security.Principal;
using NUnit.Common;
using NUnit.Engine.Internal;
+using System.Linq;
namespace NUnit.Engine.Runners
{
@@ -21,10 +22,10 @@ namespace NUnit.Engine.Runners
///
public class DomainManager
{
- static Logger log = InternalTrace.GetLogger(typeof(DomainManager));
+ static readonly Logger log = InternalTrace.GetLogger(typeof(DomainManager));
private static readonly PropertyInfo TargetFrameworkNameProperty =
- typeof(AppDomainSetup).GetProperty("TargetFrameworkName", BindingFlags.Public | BindingFlags.Instance);
+ typeof(AppDomainSetup).GetProperty("TargetFrameworkName", BindingFlags.Public | BindingFlags.Instance)!;
///
/// Construct an application domain for running a test package
@@ -67,7 +68,7 @@ AppDomainSetup CreateAppDomainSetup(TestPackage package)
//For parallel tests, we need to use distinct application name
setup.ApplicationName = "Tests" + "_" + Environment.TickCount;
- string appBase = GetApplicationBase(package);
+ string appBase = GetApplicationBase(package).ShouldNotBeNull();
setup.ApplicationBase = appBase;
setup.ConfigurationFile = GetConfigFile(appBase, package);
setup.PrivateBinPath = GetPrivateBinPath(appBase, package);
@@ -108,8 +109,8 @@ public void Unload(AppDomain domain)
class DomainUnloader
{
private readonly AppDomain _domain;
- private Thread _unloadThread;
- private NUnitEngineException _unloadException;
+ private Thread? _unloadThread;
+ private NUnitEngineException? _unloadException;
public DomainUnloader(AppDomain domain)
{
@@ -123,7 +124,7 @@ public void Unload()
var timeout = TimeSpan.FromSeconds(30);
- if (!_unloadThread.Join((int)timeout.TotalMilliseconds))
+ if (!_unloadThread.Join(timeout))
{
var msg = DomainDetailsBuilder.DetailsFor(_domain,
$"Unable to unload application domain: unload thread timed out after {timeout.TotalSeconds} seconds.");
@@ -168,7 +169,7 @@ private void UnloadOnThread()
///
/// The package
/// The ApplicationBase
- public static string GetApplicationBase(TestPackage package)
+ public static string? GetApplicationBase(TestPackage package)
{
Guard.ArgumentNotNull(package, "package");
@@ -189,7 +190,7 @@ public static string GetApplicationBase(TestPackage package)
return appBase;
}
- public static string GetConfigFile(string appBase, TestPackage package)
+ public static string? GetConfigFile(string appBase, TestPackage package)
{
Guard.ArgumentNotNullOrEmpty(appBase, "appBase");
Guard.ArgumentNotNull(package, "package");
@@ -202,7 +203,7 @@ public static string GetConfigFile(string appBase, TestPackage package)
// The ProjectService adds any project config to the settings.
// So, at this point, we only want to handle assemblies or an
// anonymous package created from the command-line.
- string fullName = package.FullName;
+ string? fullName = package.FullName;
if (IsExecutable(fullName))
return fullName + ".config";
@@ -218,7 +219,7 @@ public static string GetConfigFile(string appBase, TestPackage package)
return null;
}
- private static bool IsExecutable(string fileName)
+ private static bool IsExecutable(string? fileName)
{
if (string.IsNullOrEmpty(fileName))
return false;
@@ -227,37 +228,39 @@ private static bool IsExecutable(string fileName)
return ext == ".dll" || ext == ".exe";
}
- public static string GetCommonAppBase(IList packages)
+ public static string? GetCommonAppBase(IList packages)
{
var assemblies = new List();
- foreach (var package in packages)
- assemblies.Add(package.FullName);
+
+ // All subpackages have full names, but this is a public method in a public class so we have no control.
+ foreach (var package in packages.Where(p => p.FullName != null))
+ assemblies.Add(package.FullName!);
return GetCommonAppBase(assemblies);
}
- public static string GetCommonAppBase(IList assemblies)
+ public static string? GetCommonAppBase(IList assemblies)
{
- string commonBase = null;
+ string? commonBase = null;
foreach (string assembly in assemblies)
{
- string dir = Path.GetDirectoryName(Path.GetFullPath(assembly));
+ string? dir = Path.GetDirectoryName(Path.GetFullPath(assembly))!;
if (commonBase == null)
commonBase = dir;
- else while (!PathUtils.SamePathOrUnder(commonBase, dir) && commonBase != null)
- commonBase = Path.GetDirectoryName(commonBase);
+ else while (commonBase != null && !PathUtils.SamePathOrUnder(commonBase, dir))
+ commonBase = Path.GetDirectoryName(commonBase)!;
}
return commonBase;
}
- public static string GetPrivateBinPath(string basePath, string fileName)
+ public static string? GetPrivateBinPath(string basePath, string fileName)
{
return GetPrivateBinPath(basePath, new string[] { fileName });
}
- public static string GetPrivateBinPath(string appBase, TestPackage package)
+ public static string? GetPrivateBinPath(string appBase, TestPackage package)
{
var binPath = package.GetSetting(EnginePackageSettings.PrivateBinPath, string.Empty);
@@ -271,25 +274,25 @@ public static string GetPrivateBinPath(string appBase, TestPackage package)
return binPath;
}
- public static string GetPrivateBinPath(string basePath, IList packages)
+ public static string? GetPrivateBinPath(string basePath, IList packages)
{
var assemblies = new List();
- foreach (var package in packages)
- assemblies.Add(package.FullName);
+ foreach (var package in packages.Where(p => p.FullName != null))
+ assemblies.Add(package.FullName!);
return GetPrivateBinPath(basePath, assemblies);
}
- public static string GetPrivateBinPath(string basePath, IList assemblies)
+ public static string? GetPrivateBinPath(string basePath, IList assemblies)
{
List dirList = new List();
StringBuilder sb = new StringBuilder(200);
foreach( string assembly in assemblies )
{
- string dir = PathUtils.RelativePath(
+ string? dir = PathUtils.RelativePath(
Path.GetFullPath(basePath),
- Path.GetDirectoryName( Path.GetFullPath(assembly) ) );
+ Path.GetDirectoryName( Path.GetFullPath(assembly) )! );
if ( dir != null && dir != string.Empty && dir != "." && !dirList.Contains( dir ) )
{
dirList.Add( dir );
diff --git a/src/NUnitEngine/nunit.engine.core/Runners/NotRunnableTestRunner.cs b/src/NUnitEngine/nunit.engine.core/Runners/NotRunnableTestRunner.cs
index 86ec11a13..a65b2d0f4 100644
--- a/src/NUnitEngine/nunit.engine.core/Runners/NotRunnableTestRunner.cs
+++ b/src/NUnitEngine/nunit.engine.core/Runners/NotRunnableTestRunner.cs
@@ -31,16 +31,18 @@ public abstract class NotRunnableTestRunner : ITestEngineRunner
"" +
"";
- private string _name;
- private string _fullname;
- private string _message;
- private string _type;
+ private readonly string _name;
+ private readonly string _fullname;
+ private readonly string _message;
+ private readonly string _type;
protected string _runstate;
protected string _result;
protected string _label;
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
public NotRunnableTestRunner(string assemblyPath, string message)
+#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
{
_name = Escape(Path.GetFileName(assemblyPath));
_fullname = Escape(Path.GetFullPath(assemblyPath));
diff --git a/src/NUnitEngine/nunit.engine.core/Runners/TestAgentRunner.cs b/src/NUnitEngine/nunit.engine.core/Runners/TestAgentRunner.cs
index 3e0bd330f..d32bd7766 100644
--- a/src/NUnitEngine/nunit.engine.core/Runners/TestAgentRunner.cs
+++ b/src/NUnitEngine/nunit.engine.core/Runners/TestAgentRunner.cs
@@ -19,12 +19,12 @@ public abstract class TestAgentRunner : ITestEngineRunner
{
private readonly List _drivers = new List();
- private readonly ProvidedPathsAssemblyResolver _assemblyResolver;
+ private readonly ProvidedPathsAssemblyResolver? _assemblyResolver;
- protected AppDomain TestDomain { get; set; }
+ protected AppDomain? TestDomain { get; set; }
// Used to inject DriverService for testing
- internal IDriverService DriverService { get; set; }
+ internal IDriverService? DriverService { get; set; }
///
/// The TestPackage for which this is the runner
@@ -34,7 +34,7 @@ public abstract class TestAgentRunner : ITestEngineRunner
///
/// The result of the last call to Load
///
- protected TestEngineResult LoadResult { get; set; }
+ protected TestEngineResult? LoadResult { get; set; }
///
/// Gets an indicator of whether the package has been loaded.
@@ -100,6 +100,9 @@ public TestEngineResult Explore(TestFilter filter)
/// A TestEngineResult.
public virtual TestEngineResult Load()
{
+ Guard.OperationValid(TestDomain != null, "TestDomain is not set");
+ AppDomain testDomain = TestDomain;
+
var result = new TestEngineResult();
// DirectRunner may be called with a single-assembly package,
@@ -115,12 +118,12 @@ public virtual TestEngineResult Load()
foreach (var subPackage in packagesToLoad)
{
- var testFile = subPackage.FullName;
+ var testFile = subPackage.FullName!; // We know it's an assembly
- string targetFramework = subPackage.GetSetting(InternalEnginePackageSettings.ImageTargetFrameworkName, (string)null);
+ string? targetFramework = subPackage.GetSetting(InternalEnginePackageSettings.ImageTargetFrameworkName, (string?)null);
bool skipNonTestAssemblies = subPackage.GetSetting(EnginePackageSettings.SkipNonTestAssemblies, false);
- if (_assemblyResolver != null && !TestDomain.IsDefaultAppDomain()
+ if (_assemblyResolver != null && !testDomain.IsDefaultAppDomain()
&& subPackage.GetSetting(InternalEnginePackageSettings.ImageRequiresDefaultAppDomainAssemblyResolver, false))
{
// It's OK to do this in the loop because the Add method
@@ -128,7 +131,7 @@ public virtual TestEngineResult Load()
_assemblyResolver.AddPathFromFile(testFile);
}
- IFrameworkDriver driver = DriverService.GetDriver(TestDomain, testFile, targetFramework, skipNonTestAssemblies);
+ IFrameworkDriver driver = DriverService.GetDriver(testDomain, testFile, targetFramework, skipNonTestAssemblies);
driver.ID = subPackage.ID;
result.Add(LoadDriver(driver, testFile, subPackage));
@@ -146,7 +149,7 @@ private static string LoadDriver(IFrameworkDriver driver, string testFile, TestP
{
return driver.Load(testFile, subPackage.Settings);
}
- catch (Exception ex) when (!(ex is NUnitEngineException))
+ catch (Exception ex) when (ex is not NUnitEngineException)
{
throw new NUnitEngineException("An exception occurred in the driver while loading tests.", ex);
}
@@ -188,7 +191,7 @@ public int CountTestCases(TestFilter filter)
///
/// A TestEngineResult giving the result of the test execution
///
- public TestEngineResult Run(ITestEventListener listener, TestFilter filter)
+ public TestEngineResult Run(ITestEventListener? listener, TestFilter filter)
{
EnsurePackageIsLoaded();
@@ -213,13 +216,13 @@ public TestEngineResult Run(ITestEventListener listener, TestFilter filter)
if (_assemblyResolver != null)
{
foreach (var package in TestPackage.Select(p => p.IsAssemblyPackage()))
- _assemblyResolver.RemovePathFromFile(package.FullName);
+ _assemblyResolver.RemovePathFromFile(package.FullName!); // IsAssemblyPackage guarantees FullName is not null
}
return result;
}
- public AsyncTestEngineResult RunAsync(ITestEventListener listener, TestFilter filter)
+ public AsyncTestEngineResult RunAsync(ITestEventListener? listener, TestFilter filter)
{
var testRun = new AsyncTestEngineResult();
diff --git a/src/NUnitEngine/nunit.engine.core/Runners/TestDomainRunner.cs b/src/NUnitEngine/nunit.engine.core/Runners/TestDomainRunner.cs
index 9087d6281..b72026ed0 100644
--- a/src/NUnitEngine/nunit.engine.core/Runners/TestDomainRunner.cs
+++ b/src/NUnitEngine/nunit.engine.core/Runners/TestDomainRunner.cs
@@ -9,7 +9,7 @@ namespace NUnit.Engine.Runners
///
public class TestDomainRunner : TestAgentRunner
{
- private DomainManager _domainManager;
+ private readonly DomainManager _domainManager;
public TestDomainRunner(TestPackage package) : base(package)
{
diff --git a/src/NUnitEngine/nunit.engine.core/TestEngineResult.cs b/src/NUnitEngine/nunit.engine.core/TestEngineResult.cs
index de1419163..ddcb5220f 100644
--- a/src/NUnitEngine/nunit.engine.core/TestEngineResult.cs
+++ b/src/NUnitEngine/nunit.engine.core/TestEngineResult.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Reflection;
using System.Xml;
+using NUnit.Common;
using NUnit.Engine.Internal;
namespace NUnit.Engine
@@ -29,7 +30,7 @@ namespace NUnit.Engine
[Serializable]
public class TestEngineResult
{
- private List _xmlText = new List();
+ private readonly List _xmlText = new List();
[NonSerialized]
private List _xmlNodes = new List();
@@ -84,7 +85,7 @@ public IList XmlNodes
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(_xmlText[i]);
- _xmlNodes.Add(doc.FirstChild);
+ _xmlNodes.Add(doc.FirstChild.ShouldNotBeNull());
}
return _xmlNodes;
diff --git a/src/NUnitEngine/nunit.engine.core/nunit.engine.core.csproj b/src/NUnitEngine/nunit.engine.core/nunit.engine.core.csproj
index 822f4d2be..5f6cc8ac1 100644
--- a/src/NUnitEngine/nunit.engine.core/nunit.engine.core.csproj
+++ b/src/NUnitEngine/nunit.engine.core/nunit.engine.core.csproj
@@ -4,13 +4,15 @@
NUnit.Engine
net462;netcoreapp3.1;net6.0;net8.0
../../../bin/$(Configuration)
- $(NoWarn);SYSLIB0011;SYSLIB0012
+ $(NoWarn);SYSLIB0011
true
..\..\nunit.snk
portable
true
+
+
NUnit Engine ($(TargetFramework))
NUnit Engine Core
diff --git a/src/NUnitEngine/nunit.engine.tests/Api/ServiceLocatorTests.cs b/src/NUnitEngine/nunit.engine.tests/Api/ServiceLocatorTests.cs
index 32de01907..9b48e2c9d 100644
--- a/src/NUnitEngine/nunit.engine.tests/Api/ServiceLocatorTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Api/ServiceLocatorTests.cs
@@ -26,7 +26,7 @@ public void TearDown()
[TestCase(typeof(ITestRunnerFactory))]
public void CanAccessService(Type serviceType)
{
- IService service = _testEngine.Services.GetService(serviceType) as IService;
+ IService? service = _testEngine.Services.GetService(serviceType) as IService;
Assert.That(service, Is.Not.Null, "GetService(Type) returned null");
Assert.That(service, Is.InstanceOf(serviceType));
Assert.That(service.Status, Is.EqualTo(ServiceStatus.Started));
diff --git a/src/NUnitEngine/nunit.engine.tests/Helpers/StackEnumerator.cs b/src/NUnitEngine/nunit.engine.tests/Helpers/StackEnumerator.cs
index a1d7470b4..e9b9e635f 100644
--- a/src/NUnitEngine/nunit.engine.tests/Helpers/StackEnumerator.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Helpers/StackEnumerator.cs
@@ -49,11 +49,11 @@ public void Recurse(params T[] newCurrent)
Recurse((IEnumerable)newCurrent);
}
- public StackEnumerator(IEnumerator initial)
+ public StackEnumerator(IEnumerator? initial)
{
current = initial ?? Enumerable.Empty().GetEnumerator();
}
- public StackEnumerator(IEnumerable initial) : this(initial?.GetEnumerator())
+ public StackEnumerator(IEnumerable? initial) : this(initial?.GetEnumerator())
{
}
public StackEnumerator(params T[] initial) : this((IEnumerable)initial)
diff --git a/src/NUnitEngine/nunit.engine.tests/Runners/WorkItemTrackerTests.cs b/src/NUnitEngine/nunit.engine.tests/Runners/WorkItemTrackerTests.cs
index 68acce754..a0ff5329f 100644
--- a/src/NUnitEngine/nunit.engine.tests/Runners/WorkItemTrackerTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Runners/WorkItemTrackerTests.cs
@@ -17,7 +17,8 @@ public class WorkItemTrackerTests : ITestEventListener
[SetUp]
public void CreateTracker()
{
- _listener = _tracker = new WorkItemTracker();
+ _tracker = new WorkItemTracker();
+ _listener = _tracker;
_pendingNotices = new List();
}
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/AgentStoreTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/AgentStoreTests.cs
index 4600e4eb9..6e5c6e2c2 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/AgentStoreTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/AgentStoreTests.cs
@@ -15,6 +15,12 @@ public static partial class AgentStoreTests
private static readonly Guid DummyAgentId = Guid.NewGuid();
private static readonly ITestAgent DummyAgent = new DummyTestAgent(DummyAgentId);
+ [OneTimeTearDown]
+ public static void OneTimeTearDown()
+ {
+ DummyProcess.Dispose();
+ }
+
[Test]
public static void IdCannotBeReused()
{
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/FakeProjectService.cs b/src/NUnitEngine/nunit.engine.tests/Services/FakeProjectService.cs
index 686e00478..aafd92ff3 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/FakeProjectService.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/FakeProjectService.cs
@@ -24,9 +24,14 @@ public void Add(string projectName, params string[] assemblies)
void IProjectService.ExpandProjectPackage(TestPackage package)
{
- if (_projects.ContainsKey(package.Name))
+ if (package.Name == null)
{
- foreach (string assembly in _projects[package.Name])
+ throw new ArgumentException("Package must have a name", nameof(package));
+ }
+
+ if (_projects.TryGetValue(package.Name, out string[]? projects))
+ {
+ foreach (string assembly in projects)
package.AddSubPackage(new TestPackage(assembly));
}
}
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/FakeService.cs b/src/NUnitEngine/nunit.engine.tests/Services/FakeService.cs
index e72f5377a..ebe408c30 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/FakeService.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/FakeService.cs
@@ -9,7 +9,7 @@ interface IFakeService
public class FakeService : IFakeService, IService
{
- IServiceLocator IService.ServiceContext { get; set; }
+ IServiceLocator? IService.ServiceContext { get; set; }
private ServiceStatus _status;
ServiceStatus IService.Status
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/ProjectServiceTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/ProjectServiceTests.cs
index 9c3cf4cd5..6c83c3c7f 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/ProjectServiceTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/ProjectServiceTests.cs
@@ -21,6 +21,12 @@ public void CreateServiceContext()
services.ServiceManager.StartServices();
}
+ [TearDown]
+ public void StopServices()
+ {
+ _projectService.Dispose();
+ }
+
[Test]
public void ServiceIsStarted()
{
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/ResultServiceTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/ResultServiceTests.cs
index f89cb9f36..7d8d41cfc 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/ResultServiceTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/ResultServiceTests.cs
@@ -21,6 +21,13 @@ public void CreateService()
services.ServiceManager.StartServices();
}
+ [TearDown]
+ public void StopService()
+ {
+ _resultService.StopService();
+ _resultService.Dispose();
+ }
+
[Test]
public void ServiceIsStarted()
{
@@ -37,7 +44,7 @@ public void AvailableFormats()
//[TestCase("nunit2", null, ExpectedResult = "NUnit2XmlResultWriter")]
[TestCase("cases", null, ExpectedResult = "TestCaseResultWriter")]
//[TestCase("user", new object[] { "TextSummary.xslt" }, ExpectedResult = "XmlTransformResultWriter")]
- public string CanGetWriter(string format, object[] args)
+ public string CanGetWriter(string format, object[]? args)
{
var writer = _resultService.GetResultWriter(format, args);
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/ResultWriters/XmlTransformResultWriterTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/ResultWriters/XmlTransformResultWriterTests.cs
index 56b8af55a..b97c59fc5 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/ResultWriters/XmlTransformResultWriterTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/ResultWriters/XmlTransformResultWriterTests.cs
@@ -11,7 +11,10 @@ namespace NUnit.Engine.Services.ResultWriters
[Ignore("Temporarily ignoring this fixture")]
public class XmlTransformResultWriterTests
{
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
+ // NUnit.Analyzer DiagnosticSuppressor doesn't check inside using statement because it cannot check if the returned item is still valid.
private XmlNode _engineResult;
+#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private const string AssemblyName = "mock-assembly.dll";
[SetUp]
@@ -43,13 +46,15 @@ public void SummaryTransformTest()
StringWriter writer = new StringWriter();
new XmlTransformResultWriter(new object[] { transformPath }).WriteResultFile(_engineResult, writer);
+ Assert.That(_engineResult.Attributes, Is.Not.Null);
+
string summary = string.Format(
"Tests Run: {0}, Passed: {1}, Failed: {2}, Inconclusive: {3}, Skipped: {4}",
- _engineResult.Attributes["total"].Value,
- _engineResult.Attributes["passed"].Value,
- _engineResult.Attributes["failed"].Value,
- _engineResult.Attributes["inconclusive"].Value,
- _engineResult.Attributes["skipped"].Value);
+ _engineResult.Attributes["total"]?.Value,
+ _engineResult.Attributes["passed"]?.Value,
+ _engineResult.Attributes["failed"]?.Value,
+ _engineResult.Attributes["inconclusive"]?.Value,
+ _engineResult.Attributes["skipped"]?.Value);
string output = writer.GetStringBuilder().ToString();
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/RuntimeFrameworkServiceTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/RuntimeFrameworkServiceTests.cs
index 8beb027fb..6d3c72ea5 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/RuntimeFrameworkServiceTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/RuntimeFrameworkServiceTests.cs
@@ -36,6 +36,7 @@ public void CreateServiceContext()
public void StopService()
{
_runtimeService.StopService();
+ _runtimeService.Dispose();
}
[Test]
@@ -70,7 +71,7 @@ public void SelectRuntimeFramework(string runtime, bool runAsX86)
public void CanGetCurrentFramework()
{
var framework = _runtimeService.CurrentFramework as RuntimeFramework;
-
+ Assert.That(framework, Is.Not.Null);
Assert.That(framework.Runtime, Is.EqualTo(_currentRuntime));
}
@@ -87,6 +88,7 @@ public void AvailableFrameworks()
public void CurrentFrameworkMustBeAvailable()
{
var current = _runtimeService.CurrentFramework;
+ Assert.That(current, Is.Not.Null);
Console.WriteLine("Current framework is {0} ({1})", current.DisplayName, current.Id);
Assert.That(_runtimeService.IsAvailable(current.Id, false), "{current} not available");
}
@@ -95,9 +97,15 @@ public void CurrentFrameworkMustBeAvailable()
public void AvailableFrameworksList_IncludesCurrentFramework()
{
var current = _runtimeService.CurrentFramework as RuntimeFramework;
+ Assert.That(current, Is.Not.Null);
+
foreach (var framework in _runtimeService.AvailableRuntimes)
- if (current.Supports(framework as RuntimeFramework))
+ {
+ RuntimeFramework? runtimeFramework = framework as RuntimeFramework;
+ Assert.That(runtimeFramework, Is.Not.Null);
+ if (current.Supports(runtimeFramework))
return;
+ }
Assert.Fail("CurrentFramework not listed as available");
}
@@ -123,7 +131,7 @@ public void EngineOptionPreferredOverImageTarget(string framework, int majorVers
package.AddSetting(EnginePackageSettings.RequestedRuntimeFramework, requested);
_runtimeService.SelectRuntimeFramework(package);
- Assert.That(package.GetSetting(EnginePackageSettings.RequestedRuntimeFramework, null), Is.EqualTo(requested));
+ Assert.That(package.GetSetting(EnginePackageSettings.RequestedRuntimeFramework, string.Empty), Is.EqualTo(requested));
}
[Test]
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/ServiceDependencyTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/ServiceDependencyTests.cs
index 33bcfa427..77db8986c 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/ServiceDependencyTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/ServiceDependencyTests.cs
@@ -20,7 +20,7 @@ public void TestRunnerFactory_ProjectServiceMissing()
{
var service = new TestRunnerFactory();
_services.Add(service);
- service.StartService();
+ Assert.That(service.StartService, Throws.Exception);
Assert.That(service.Status, Is.EqualTo(ServiceStatus.Error));
}
}
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/ServiceManagerTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/ServiceManagerTests.cs
index 1bd6ff869..a5c698d63 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/ServiceManagerTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/ServiceManagerTests.cs
@@ -20,6 +20,13 @@ public void SetUp()
_serviceManager.AddService(new ExtensionService());
}
+ [TearDown]
+ public void TearDown()
+ {
+ _serviceManager.StopServices();
+ _serviceManager.Dispose();
+ }
+
[Test]
public void InitializeServices()
{
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerResult.cs b/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerResult.cs
index 6c3eb4830..84b9fc463 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerResult.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerResult.cs
@@ -26,24 +26,19 @@ public static RunnerResult AggregatingTestRunner(int numSubRunners) =>
public static RunnerResult AggregatingTestRunner(RunnerResult subRunnerType, int numSubRunners)
{
- return new RunnerResult()
- {
- TestRunner = typeof(AggregatingTestRunner),
- SubRunners = GetSubRunners(subRunnerType, numSubRunners)
- };
+ return new RunnerResult(typeof(AggregatingTestRunner), GetSubRunners(subRunnerType, numSubRunners));
}
public static RunnerResult AggregatingTestRunner(params RunnerResult[] subRunners)
{
- return new RunnerResult()
- {
- TestRunner = typeof(AggregatingTestRunner),
- SubRunners = subRunners
- };
+ return new RunnerResult(typeof(AggregatingTestRunner), subRunners);
}
- public RunnerResult()
- { }
+ public RunnerResult(Type testRunner)
+ {
+ TestRunner = testRunner;
+ SubRunners = Array.Empty();
+ }
public RunnerResult(Type testRunner, params RunnerResult[] subRunners)
{
@@ -53,7 +48,7 @@ public RunnerResult(Type testRunner, params RunnerResult[] subRunners)
public Type TestRunner { get; set; }
- public ICollection SubRunners { get; set; } = new List();
+ public ICollection SubRunners { get; }
public override string ToString()
{
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerResultComparer.cs b/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerResultComparer.cs
index 3667fa1b0..e2080ce29 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerResultComparer.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerResultComparer.cs
@@ -10,10 +10,13 @@ internal class RunnerResultComparer : IEqualityComparer
{
public static readonly RunnerResultComparer Instance = new RunnerResultComparer();
- public bool Equals(RunnerResult x, RunnerResult y)
+ public bool Equals(RunnerResult? x, RunnerResult? y)
{
- x = x ?? throw new ArgumentNullException(nameof(x));
- y = y ?? throw new ArgumentNullException(nameof(y));
+ if (ReferenceEquals(x, y))
+ return true;
+
+ if (x is null || y is null)
+ return false;
return x.TestRunner == y.TestRunner &&
x.SubRunners.SequenceEqual(y.SubRunners, Instance);
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerSelectionTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerSelectionTests.cs
index 64052018d..e89c803d4 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerSelectionTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/TestRunnerFactoryTests/RunnerSelectionTests.cs
@@ -1,8 +1,11 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
+using System;
+using System.Collections.Generic;
using System.Linq;
using NUnit.Engine.Runners;
using NUnit.Framework;
+using NUnitLite;
namespace NUnit.Engine.Services.TestRunnerFactoryTests
{
@@ -36,6 +39,19 @@ public void SetUp()
((IService)fakeRuntimeService).StartService();
_services.Add(fakeRuntimeService);
Assert.That(((IService)fakeRuntimeService).Status, Is.EqualTo(ServiceStatus.Started));
+
+#if NETFRAMEWORK
+ var testAgency = new TestAgency();
+ _services.Add(testAgency);
+ ((IService)testAgency).StartService();
+ Assert.That(testAgency.Status, Is.EqualTo(ServiceStatus.Started));
+#endif
+ }
+
+ [OneTimeTearDown]
+ public void TearDown()
+ {
+ _factory.Dispose();
}
[TestCaseSource(typeof(TestRunnerFactoryData), nameof(TestRunnerFactoryData.TestCases))]
@@ -49,12 +65,12 @@ public void RunnerSelectionTest(TestPackage package, RunnerResult expected)
private static RunnerResult GetRunnerResult(ITestEngineRunner runner)
{
- var result = new RunnerResult(runner.GetType());
+ var runnerType = runner.GetType();
if (runner is AggregatingTestRunner aggRunner)
- result.SubRunners = aggRunner.Runners.Select(GetRunnerResult).ToList();
+ return new RunnerResult(runnerType, aggRunner.Runners.Select(GetRunnerResult).ToArray());
- return result;
+ return new RunnerResult(runnerType);
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/TestSelectionParserTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/TestSelectionParserTests.cs
index 700663750..bf9d47b99 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/TestSelectionParserTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/TestSelectionParserTests.cs
@@ -10,14 +10,6 @@ namespace NUnit.Engine.Services
{
public class TestSelectionParserTests
{
- private TestSelectionParser _parser;
-
- [SetUp]
- public void CreateParser()
- {
- _parser = new TestSelectionParser();
- }
-
[TestCase("cat=Urgent", "Urgent")]
[TestCase("cat==Urgent", "Urgent")]
[TestCase("cat!=Urgent", "Urgent")]
@@ -52,19 +44,19 @@ public void CreateParser()
[TestCase("!(cat!=Urgent)", "Urgent")]
public void TestParser(string input, string output)
{
- Assert.That(_parser.Parse(input), Is.EqualTo(output));
+ Assert.That(TestSelectionParser.Parse(input), Is.EqualTo(output));
XmlDocument doc = new XmlDocument();
Assert.DoesNotThrow(() => doc.LoadXml(output));
}
- [TestCase(null, typeof(ArgumentNullException))]
+ [TestCase(null!, typeof(ArgumentNullException))]
[TestCase("", typeof(TestSelectionParserException))]
[TestCase(" ", typeof(TestSelectionParserException))]
[TestCase(" \t\t ", typeof(TestSelectionParserException))]
public void TestParser_InvalidInput(string input, Type type)
{
- Assert.That(() => _parser.Parse(input), Throws.TypeOf(type));
+ Assert.That(() => TestSelectionParser.Parse(input), Throws.TypeOf(type));
}
}
}
diff --git a/src/NUnitEngine/nunit.engine.tests/Services/TokenizerTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/TokenizerTests.cs
index e4d5335f6..5f760f435 100644
--- a/src/NUnitEngine/nunit.engine.tests/Services/TokenizerTests.cs
+++ b/src/NUnitEngine/nunit.engine.tests/Services/TokenizerTests.cs
@@ -12,7 +12,7 @@ public class TokenizerTests
[Test]
public void NullInputThrowsException()
{
- Assert.That(() => new Tokenizer(null), Throws.ArgumentNullException);
+ Assert.That(() => new Tokenizer(null!), Throws.ArgumentNullException);
}
[Test]
diff --git a/src/NUnitEngine/nunit.engine.tests/nunit.engine.tests.csproj b/src/NUnitEngine/nunit.engine.tests/nunit.engine.tests.csproj
index 2632124c9..6a5efc1a4 100644
--- a/src/NUnitEngine/nunit.engine.tests/nunit.engine.tests.csproj
+++ b/src/NUnitEngine/nunit.engine.tests/nunit.engine.tests.csproj
@@ -12,6 +12,8 @@
1505
+
+
NUnit Engine
NUnit Engine Tests ($(TargetFramework))
@@ -24,6 +26,10 @@
+
+
+
+
diff --git a/src/NUnitEngine/nunit.engine/Communication/Transports/Remoting/TestAgencyRemotingTransport.cs b/src/NUnitEngine/nunit.engine/Communication/Transports/Remoting/TestAgencyRemotingTransport.cs
index c9d24b877..0e43d181c 100644
--- a/src/NUnitEngine/nunit.engine/Communication/Transports/Remoting/TestAgencyRemotingTransport.cs
+++ b/src/NUnitEngine/nunit.engine/Communication/Transports/Remoting/TestAgencyRemotingTransport.cs
@@ -27,7 +27,7 @@ public class TestAgencyRemotingTransport : MarshalByRefObject, ITestAgencyTransp
private string _uri;
private int _port;
- private TcpChannel _channel;
+ private TcpChannel? _channel;
private bool _isMarshalled;
private object _theLock = new object();
@@ -56,7 +56,7 @@ public bool Start()
if (_port == 0)
{
- ChannelDataStore store = this._channel.ChannelData as ChannelDataStore;
+ ChannelDataStore? store = _channel!.ChannelData as ChannelDataStore;
if (store != null)
{
string channelUri = store.ChannelUris[0];
@@ -133,7 +133,7 @@ protected virtual void Dispose(bool disposing)
///
public override object InitializeLifetimeService()
{
- return null;
+ return null!;
}
}
}
diff --git a/src/NUnitEngine/nunit.engine/Communication/Transports/Tcp/TcpServer.cs b/src/NUnitEngine/nunit.engine/Communication/Transports/Tcp/TcpServer.cs
index 705e5e60b..03cb770d9 100644
--- a/src/NUnitEngine/nunit.engine/Communication/Transports/Tcp/TcpServer.cs
+++ b/src/NUnitEngine/nunit.engine/Communication/Transports/Tcp/TcpServer.cs
@@ -15,12 +15,12 @@ public class TcpServer
private const int GUID_BUFFER_SIZE = 16;
TcpListener _tcpListener;
- Thread _listenerThread;
+ Thread? _listenerThread;
volatile bool _running;
public delegate void ConnectionEventHandler(Socket clientSocket, Guid id);
- public event ConnectionEventHandler ClientConnected;
+ public event ConnectionEventHandler? ClientConnected;
public TcpServer(int port = 0)
{
diff --git a/src/NUnitEngine/nunit.engine/Runners/AggregatingTestRunner.cs b/src/NUnitEngine/nunit.engine/Runners/AggregatingTestRunner.cs
index f88851802..78240c3b9 100644
--- a/src/NUnitEngine/nunit.engine/Runners/AggregatingTestRunner.cs
+++ b/src/NUnitEngine/nunit.engine/Runners/AggregatingTestRunner.cs
@@ -34,7 +34,7 @@ public class AggregatingTestRunner : TestEngineRunner
// TODO: Determine whether AggregatingTestRunner needs to create an XML result
// node for a project or if that responsibility can be delegated to the individual
// runners it creates.
- private List _runners;
+ private List? _runners;
// Exceptions from unloading individual runners are caught and rethrown
// on AggregatingTestRunner disposal, to allow TestResults to be
diff --git a/src/NUnitEngine/nunit.engine/Runners/MasterTestRunner.cs b/src/NUnitEngine/nunit.engine/Runners/MasterTestRunner.cs
index 24985f841..48743493f 100644
--- a/src/NUnitEngine/nunit.engine/Runners/MasterTestRunner.cs
+++ b/src/NUnitEngine/nunit.engine/Runners/MasterTestRunner.cs
@@ -32,7 +32,7 @@ public class MasterTestRunner : ITestRunner
// element, which wraps all the individual assembly and project
// results.
- private ITestEngineRunner _engineRunner;
+ private ITestEngineRunner? _engineRunner;
private readonly IServiceLocator _services;
private readonly ExtensionService _extensionService;
#if NETFRAMEWORK
@@ -77,7 +77,7 @@ public MasterTestRunner(IServiceLocator services, TestPackage package)
///
/// The result of the last call to LoadPackage
///
- protected TestEngineResult LoadResult { get; set; }
+ protected TestEngineResult? LoadResult { get; set; }
///
/// Gets an indicator of whether the package has been loaded.
@@ -145,7 +145,7 @@ public int CountTestCases(TestFilter filter)
/// An ITestEventHandler to receive events
/// A TestFilter used to select tests
/// An XmlNode giving the result of the test execution
- public XmlNode Run(ITestEventListener listener, TestFilter filter)
+ public XmlNode Run(ITestEventListener? listener, TestFilter filter)
{
return RunTests(listener, filter).Xml;
}
@@ -158,7 +158,7 @@ public XmlNode Run(ITestEventListener listener, TestFilter filter)
/// The listener that is notified as the run progresses
/// A TestFilter used to select tests
///
- public ITestRun RunAsync(ITestEventListener listener, TestFilter filter)
+ public ITestRun RunAsync(ITestEventListener? listener, TestFilter filter)
{
return RunTestsAsync(listener, filter);
}
@@ -169,6 +169,9 @@ public ITestRun RunAsync(ITestEventListener listener, TestFilter filter)
/// If true, cancel any ongoing test threads, otherwise wait for them to complete.
public void StopRun(bool force)
{
+ if (_engineRunner is null)
+ return; // No test is was even started.
+
_engineRunner.StopRun(force);
if (force)
@@ -386,8 +389,7 @@ private void ValidatePackageSettings()
private void UnloadPackage()
{
LoadResult = null;
- if (_engineRunner != null)
- _engineRunner.Unload();
+ _engineRunner?.Unload();
}
///
@@ -411,7 +413,7 @@ private int CountTests(TestFilter filter)
/// An ITestEventHandler to receive events
/// A TestFilter used to select tests
/// A TestEngineResult giving the result of the test execution
- private TestEngineResult RunTests(ITestEventListener listener, TestFilter filter)
+ private TestEngineResult RunTests(ITestEventListener? listener, TestFilter filter)
{
_workItemTracker.Clear();
_eventDispatcher.Listeners.Clear();
@@ -429,7 +431,7 @@ private TestEngineResult RunTests(ITestEventListener listener, TestFilter filter
string engineVersion;
clrVersion = Environment.Version.ToString();
- engineVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ engineVersion = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "0.0.0.0";
var startTime = DateTime.UtcNow;
var startRunNode = XmlHelper.CreateTopLevelElement("start-run");
@@ -465,7 +467,7 @@ private TestEngineResult RunTests(ITestEventListener listener, TestFilter filter
return result;
}
- private AsyncTestEngineResult RunTestsAsync(ITestEventListener listener, TestFilter filter)
+ private AsyncTestEngineResult RunTestsAsync(ITestEventListener? listener, TestFilter filter)
{
var testRun = new AsyncTestEngineResult();
diff --git a/src/NUnitEngine/nunit.engine/Runners/ParallelTaskWorkerPool.cs b/src/NUnitEngine/nunit.engine/Runners/ParallelTaskWorkerPool.cs
index ee236c5ea..41fece7d8 100644
--- a/src/NUnitEngine/nunit.engine/Runners/ParallelTaskWorkerPool.cs
+++ b/src/NUnitEngine/nunit.engine/Runners/ParallelTaskWorkerPool.cs
@@ -49,7 +49,7 @@ private void ProcessTasksProc()
{
while (true)
{
- ITestExecutionTask task = null;
+ ITestExecutionTask? task = null;
lock (_taskLock)
{
if (_tasks.Count > 0)
diff --git a/src/NUnitEngine/nunit.engine/Runners/ProcessRunner.cs b/src/NUnitEngine/nunit.engine/Runners/ProcessRunner.cs
index e9c95f0ff..f04d3b7cf 100644
--- a/src/NUnitEngine/nunit.engine/Runners/ProcessRunner.cs
+++ b/src/NUnitEngine/nunit.engine/Runners/ProcessRunner.cs
@@ -3,6 +3,7 @@
#if NETFRAMEWORK
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using NUnit.Common;
using NUnit.Engine.Internal;
using NUnit.Engine.Services;
@@ -24,9 +25,10 @@ public class ProcessRunner : TestEngineRunner
private static readonly Logger log = InternalTrace.GetLogger(typeof(ProcessRunner));
- private ITestAgent _agent;
- private ITestEngineRunner _remoteRunner;
- private TestAgency _agency;
+ private readonly TestAgency _agency;
+
+ private ITestAgent? _agent;
+ private ITestEngineRunner? _remoteRunner;
public ProcessRunner(IServiceLocator services, TestPackage package) : base(services, package)
{
@@ -204,7 +206,7 @@ protected override void Dispose(bool disposing)
{
_disposed = true;
- Exception unloadException = null;
+ Exception? unloadException = null;
try
{
@@ -241,6 +243,7 @@ protected override void Dispose(bool disposing)
}
}
+ [MemberNotNull(nameof(_agent), nameof(_remoteRunner))]
private void CreateAgentAndRunnerIfNeeded()
{
if (_agent == null)
@@ -264,8 +267,8 @@ TestEngineResult CreateFailedResult(Exception e)
var suite = XmlHelper.CreateTopLevelElement("test-suite");
XmlHelper.AddAttribute(suite, "type", "Assembly");
XmlHelper.AddAttribute(suite, "id", TestPackage.ID);
- XmlHelper.AddAttribute(suite, "name", TestPackage.Name);
- XmlHelper.AddAttribute(suite, "fullname", TestPackage.FullName);
+ XmlHelper.AddAttribute(suite, "name", TestPackage.Name ?? string.Empty);
+ XmlHelper.AddAttribute(suite, "fullname", TestPackage.FullName ?? string.Empty);
XmlHelper.AddAttribute(suite, "runstate", "NotRunnable");
XmlHelper.AddAttribute(suite, "testcasecount", "1");
XmlHelper.AddAttribute(suite, "result", "Failed");
diff --git a/src/NUnitEngine/nunit.engine/Runners/TestEngineRunner.cs b/src/NUnitEngine/nunit.engine/Runners/TestEngineRunner.cs
index b4ce0b000..521e5e36d 100644
--- a/src/NUnitEngine/nunit.engine/Runners/TestEngineRunner.cs
+++ b/src/NUnitEngine/nunit.engine/Runners/TestEngineRunner.cs
@@ -37,7 +37,7 @@ public TestEngineRunner(IServiceLocator services, TestPackage package)
///
/// The result of the last call to LoadPackage
///
- protected TestEngineResult LoadResult { get; set; }
+ protected TestEngineResult? LoadResult { get; set; }
///
/// Gets an indicator of whether the package has been loaded.
diff --git a/src/NUnitEngine/nunit.engine/Runners/TestEventDispatcher.cs b/src/NUnitEngine/nunit.engine/Runners/TestEventDispatcher.cs
index 4d5860bf7..efea913c2 100644
--- a/src/NUnitEngine/nunit.engine/Runners/TestEventDispatcher.cs
+++ b/src/NUnitEngine/nunit.engine/Runners/TestEventDispatcher.cs
@@ -37,7 +37,7 @@ public void OnTestEvent(string report)
#endif
public override object InitializeLifetimeService()
{
- return null;
+ return null!;
}
}
}
diff --git a/src/NUnitEngine/nunit.engine/Runners/TestExecutionTask.cs b/src/NUnitEngine/nunit.engine/Runners/TestExecutionTask.cs
index 3af167618..3ddcf1652 100644
--- a/src/NUnitEngine/nunit.engine/Runners/TestExecutionTask.cs
+++ b/src/NUnitEngine/nunit.engine/Runners/TestExecutionTask.cs
@@ -10,10 +10,10 @@ public class TestExecutionTask : ITestExecutionTask
private readonly ITestEngineRunner _runner;
private readonly ITestEventListener _listener;
private readonly TestFilter _filter;
- private volatile TestEngineResult _result;
+ private volatile TestEngineResult? _result;
private readonly bool _disposeRunner;
private bool _hasExecuted = false;
- private Exception _unloadException;
+ private Exception? _unloadException;
public TestExecutionTask(ITestEngineRunner runner, ITestEventListener listener, TestFilter filter, bool disposeRunner)
{
@@ -44,7 +44,7 @@ public void Execute()
}
}
- public TestEngineResult Result
+ public TestEngineResult? Result
{
get
{
@@ -56,7 +56,7 @@ public TestEngineResult Result
///
/// Stored exception thrown during test assembly unload.
///
- public Exception UnloadException
+ public Exception? UnloadException
{
get
{
diff --git a/src/NUnitEngine/nunit.engine/Runners/WorkItemTracker.cs b/src/NUnitEngine/nunit.engine/Runners/WorkItemTracker.cs
index 0084a1f28..f18231a9b 100644
--- a/src/NUnitEngine/nunit.engine/Runners/WorkItemTracker.cs
+++ b/src/NUnitEngine/nunit.engine/Runners/WorkItemTracker.cs
@@ -53,10 +53,13 @@ public InProgressItem(int order, string name, XmlReader reader)
public string Name { get; }
public Dictionary Properties { get; }
- public int CompareTo(InProgressItem other)
+ public int CompareTo(InProgressItem? other)
{
// for signaling purposes, return in reverse order
- return _order.CompareTo(other._order) * -1;
+ if (other == null)
+ return -1;
+
+ return _order.CompareTo(other._order) * -1;
}
}
@@ -159,7 +162,9 @@ void ITestEventListener.OnTestEvent(string report)
case "test-case":
case "test-suite":
- RemoveItem(reader.GetAttribute("id"));
+ string? id = reader.GetAttribute("id");
+ if (id != null) // TODO: Should we throw if id is null?
+ RemoveItem(id);
if (_itemsInProcess.Count == 0)
_allItemsComplete.Set();
diff --git a/src/NUnitEngine/nunit.engine/Runtime.cs b/src/NUnitEngine/nunit.engine/Runtime.cs
index 80b4c51e7..bf60da154 100644
--- a/src/NUnitEngine/nunit.engine/Runtime.cs
+++ b/src/NUnitEngine/nunit.engine/Runtime.cs
@@ -73,6 +73,8 @@ public virtual bool Supports(Version runtime, Version target)
return runtime.Major == target.Major && runtime.Minor >= target.Minor;
}
+ public abstract override string ToString();
+
#endregion
#region Nested Runtime Classes
diff --git a/src/NUnitEngine/nunit.engine/RuntimeFramework.cs b/src/NUnitEngine/nunit.engine/RuntimeFramework.cs
index 1c408ca8f..75078880a 100644
--- a/src/NUnitEngine/nunit.engine/RuntimeFramework.cs
+++ b/src/NUnitEngine/nunit.engine/RuntimeFramework.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.Versioning;
@@ -37,7 +38,7 @@ public RuntimeFramework(Runtime runtime, Version version)
/// A Runtime instance.
/// The Version of the framework.
/// A string representing the profile of the framework. Null if unspecified.
- public RuntimeFramework(Runtime runtime, Version version, string profile)
+ public RuntimeFramework(Runtime runtime, Version version, string? profile)
{
Guard.ArgumentNotNull(runtime, nameof(runtime));
Guard.ArgumentValid(IsValidFrameworkVersion(version), $"{version} is not a valid framework version", nameof(version));
@@ -85,7 +86,7 @@ private bool IsValidFrameworkVersion(Version v)
/// May be null and will have different sets of
/// values for each Runtime.
///
- public string Profile { get; private set; }
+ public string? Profile { get; private set; }
///
/// Returns the Display name for this framework
@@ -114,7 +115,7 @@ public static RuntimeFramework Parse(string s)
return new RuntimeFramework(runtime, version);
}
- public static bool TryParse(string s, out RuntimeFramework runtimeFramework)
+ public static bool TryParse(string s, [NotNullWhen(true)] out RuntimeFramework? runtimeFramework)
{
try
{
@@ -168,7 +169,7 @@ public bool CanLoad(IRuntimeFramework requested)
return FrameworkVersion >= requested.FrameworkVersion;
}
- private static string GetDefaultDisplayName(Runtime runtime, Version version, string profile)
+ private static string GetDefaultDisplayName(Runtime runtime, Version version, string? profile)
{
string displayName = $"{runtime.DisplayName} {version}";
@@ -187,7 +188,7 @@ private static string GetMonoPrefixFromAssembly(Assembly assembly)
// files have been copied to some non-standard place, we check.
for (int i = 0; i < 4; i++)
{
- string dir = Path.GetDirectoryName(prefix);
+ string? dir = Path.GetDirectoryName(prefix);
if (string.IsNullOrEmpty(dir)) break;
prefix = dir;
diff --git a/src/NUnitEngine/nunit.engine/Services/AgentProcess.cs b/src/NUnitEngine/nunit.engine/Services/AgentProcess.cs
index 47ead8bf0..681ac4340 100644
--- a/src/NUnitEngine/nunit.engine/Services/AgentProcess.cs
+++ b/src/NUnitEngine/nunit.engine/Services/AgentProcess.cs
@@ -73,7 +73,11 @@ public AgentProcess(TestAgency agency, TestPackage package, Guid agentId)
if (Path.DirectorySeparatorChar != '\\')
throw new Exception("Running .NET Core as X86 is currently only supported on Windows");
- var x86_dotnet_exe = Path.Combine(DotNet.GetX86InstallDirectory(), "dotnet.exe");
+ string? installDirectory = DotNet.GetX86InstallDirectory();
+ if (installDirectory == null)
+ throw new Exception("The X86 version of dotnet.exe is not installed");
+
+ var x86_dotnet_exe = Path.Combine(installDirectory, "dotnet.exe");
if (!File.Exists(x86_dotnet_exe))
throw new Exception("The X86 version of dotnet.exe is not installed");
@@ -155,7 +159,7 @@ public static string GetTestAgentExePath(RuntimeFramework targetRuntime, bool re
break;
default:
log.Error($"Unknown runtime type: {targetRuntime.Runtime}");
- return null;
+ throw new NotSupportedException($"Unknown runtime type: {targetRuntime.Runtime}");
}
return Path.Combine(agentsDir, agentSubDir, agentName + agentExtension);
diff --git a/src/NUnitEngine/nunit.engine/Services/AgentStore.AgentRecord.cs b/src/NUnitEngine/nunit.engine/Services/AgentStore.AgentRecord.cs
index c3464f1c1..27246d80f 100644
--- a/src/NUnitEngine/nunit.engine/Services/AgentStore.AgentRecord.cs
+++ b/src/NUnitEngine/nunit.engine/Services/AgentStore.AgentRecord.cs
@@ -3,27 +3,31 @@
#if !NETSTANDARD2_0
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace NUnit.Engine.Services
{
internal sealed partial class AgentStore
{
- private struct AgentRecord
+ private readonly struct AgentRecord
{
- private AgentRecord(Process process, ITestAgent agent)
+ private AgentRecord(Process? process, ITestAgent? agent)
{
Process = process;
Agent = agent;
}
- public Process Process { get; }
- public ITestAgent Agent { get; }
+ public Process? Process { get; }
+ public ITestAgent? Agent { get; }
public AgentStatus Status =>
Process is null ? AgentStatus.Terminated :
Agent is null ? AgentStatus.Starting :
AgentStatus.Ready;
+ [MemberNotNullWhen(true, nameof(Process), nameof(Agent))]
+ public bool IsReady => Process is not null && Agent is not null;
+
public static AgentRecord Starting(Process process)
{
if (process is null) throw new ArgumentNullException(nameof(process));
diff --git a/src/NUnitEngine/nunit.engine/Services/AgentStore.cs b/src/NUnitEngine/nunit.engine/Services/AgentStore.cs
index cb3ca766a..6c7bd51f0 100644
--- a/src/NUnitEngine/nunit.engine/Services/AgentStore.cs
+++ b/src/NUnitEngine/nunit.engine/Services/AgentStore.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace NUnit.Engine.Services
{
@@ -41,12 +42,11 @@ public void Register(ITestAgent agent)
}
}
- public bool IsReady(Guid agentId, out ITestAgent agent)
+ public bool IsReady(Guid agentId, [NotNullWhen(true)] out ITestAgent? agent)
{
lock (_agentsById)
{
- if (_agentsById.TryGetValue(agentId, out var record)
- && record.Status == AgentStatus.Ready)
+ if (_agentsById.TryGetValue(agentId, out var record) && record.IsReady)
{
agent = record.Agent;
return true;
@@ -57,7 +57,7 @@ public bool IsReady(Guid agentId, out ITestAgent agent)
}
}
- public bool IsAgentProcessActive(Guid agentId, out Process process)
+ public bool IsAgentProcessActive(Guid agentId, [NotNullWhen(true)] out Process? process)
{
lock (_agentsById)
{
diff --git a/src/NUnitEngine/nunit.engine/Services/ExtensionService.cs b/src/NUnitEngine/nunit.engine/Services/ExtensionService.cs
index 405d95dc0..330fa9dad 100644
--- a/src/NUnitEngine/nunit.engine/Services/ExtensionService.cs
+++ b/src/NUnitEngine/nunit.engine/Services/ExtensionService.cs
@@ -61,7 +61,7 @@ public void FindExtensionAssemblies(string initialDirectory)
///
/// Get an ExtensionPoint based on its unique identifying path.
///
- IExtensionPoint IExtensionService.GetExtensionPoint(string path)
+ IExtensionPoint? IExtensionService.GetExtensionPoint(string path)
{
return _extensionManager.GetExtensionPoint(path);
}
@@ -82,7 +82,7 @@ public void EnableExtension(string typeName, bool enabled)
public IEnumerable GetExtensions() => _extensionManager.GetExtensions();
- public IExtensionNode GetExtensionNode(string path) => _extensionManager.GetExtensionNode(path);
+ public IExtensionNode? GetExtensionNode(string path) => _extensionManager.GetExtensionNode(path);
public IEnumerable GetExtensionNodes() => _extensionManager.GetExtensionNodes();
diff --git a/src/NUnitEngine/nunit.engine/Services/ProjectService.cs b/src/NUnitEngine/nunit.engine/Services/ProjectService.cs
index 10d0628f5..eaef24323 100644
--- a/src/NUnitEngine/nunit.engine/Services/ProjectService.cs
+++ b/src/NUnitEngine/nunit.engine/Services/ProjectService.cs
@@ -1,5 +1,6 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
+using System;
using System.Collections.Generic;
using System.IO;
using NUnit.Common;
@@ -16,11 +17,10 @@ public class ProjectService : Service, IProjectService
public bool CanLoadFrom(string path)
{
- ExtensionNode node = GetNodeForPath(path);
+ ExtensionNode? node = GetNodeForPath(path);
if (node != null)
{
- var loader = node.ExtensionObject as IProjectLoader;
- if (loader.CanLoadFrom(path))
+ if (node.ExtensionObject is IProjectLoader loader && loader.CanLoadFrom(path))
return true;
}
@@ -39,14 +39,13 @@ public void ExpandProjectPackage(TestPackage package)
Guard.ArgumentNotNull(package, "package");
Guard.ArgumentValid(package.SubPackages.Count == 0, "Package is already expanded", "package");
- string path = package.FullName;
+ string path = package.FullName!;
if (!File.Exists(path))
return;
- IProject project = LoadFrom(path);
- Guard.ArgumentValid(project != null, "Unable to load project " + path, "package");
+ IProject project = LoadFrom(path).ShouldNotBeNull("Unable to load project " + path);
- string activeConfig = package.GetSetting(EnginePackageSettings.ActiveConfig, (string)null);
+ string? activeConfig = package.GetSetting(EnginePackageSettings.ActiveConfig, (string?)null);
if (activeConfig == null)
activeConfig = project.ActiveConfigName;
else
@@ -84,6 +83,9 @@ public override void StartService()
{
try
{
+ if (ServiceContext == null)
+ throw new InvalidOperationException("Only services that have a ServiceContext can be started.");
+
var extensionService = ServiceContext.GetService();
if (extensionService == null)
@@ -118,15 +120,14 @@ public override void StartService()
}
}
- private IProject LoadFrom(string path)
+ private IProject? LoadFrom(string path)
{
if (File.Exists(path))
{
- ExtensionNode node = GetNodeForPath(path);
+ ExtensionNode? node = GetNodeForPath(path);
if (node != null)
{
- var loader = node.ExtensionObject as IProjectLoader;
- if (loader.CanLoadFrom(path))
+ if (node.ExtensionObject is IProjectLoader loader && loader.CanLoadFrom(path))
return loader.LoadFrom(path);
}
}
@@ -134,14 +135,14 @@ private IProject LoadFrom(string path)
return null;
}
- private ExtensionNode GetNodeForPath(string path)
+ private ExtensionNode? GetNodeForPath(string path)
{
var ext = Path.GetExtension(path);
- if (string.IsNullOrEmpty(ext) || !_extensionIndex.ContainsKey(ext))
+ if (string.IsNullOrEmpty(ext) || !_extensionIndex.TryGetValue(ext, out ExtensionNode? node))
return null;
- return _extensionIndex[ext];
+ return node;
}
}
}
diff --git a/src/NUnitEngine/nunit.engine/Services/ResultService.cs b/src/NUnitEngine/nunit.engine/Services/ResultService.cs
index 4746c663c..cc842c458 100644
--- a/src/NUnitEngine/nunit.engine/Services/ResultService.cs
+++ b/src/NUnitEngine/nunit.engine/Services/ResultService.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using NUnit.Engine.Extensibility;
namespace NUnit.Engine.Services
@@ -9,9 +10,11 @@ namespace NUnit.Engine.Services
public class ResultService : Service, IResultService
{
private readonly string[] BUILT_IN_FORMATS = new string[] { "nunit3", "cases", "user" };
- private IEnumerable _extensionNodes;
+ private IEnumerable? _extensionNodes;
- private string[] _formats;
+ private string[]? _formats;
+
+ [MemberNotNull(nameof(_formats))]
public string[] Formats
{
get
@@ -20,9 +23,10 @@ public string[] Formats
{
var formatList = new List(BUILT_IN_FORMATS);
- foreach (var node in _extensionNodes)
- foreach (var format in node.GetValues("Format"))
- formatList.Add(format);
+ if (_extensionNodes != null)
+ foreach (var node in _extensionNodes)
+ foreach (var format in node.GetValues("Format"))
+ formatList.Add(format);
_formats = formatList.ToArray();
}
@@ -37,7 +41,7 @@ public string[] Formats
/// The name of the format to be used
/// A set of arguments to be used in constructing the writer or null if non arguments are needed
/// An IResultWriter
- public IResultWriter GetResultWriter(string format, object[] args)
+ public IResultWriter GetResultWriter(string format, params object?[]? args)
{
switch (format)
{
@@ -46,14 +50,15 @@ public IResultWriter GetResultWriter(string format, object[] args)
case "cases":
return new TestCaseResultWriter();
case "user":
- return new XmlTransformResultWriter(args);
+ return new XmlTransformResultWriter(args!);
default:
- foreach (var node in _extensionNodes)
- foreach (var supported in node.GetValues("Format"))
- if (supported == format)
- return node.ExtensionObject as IResultWriter;
- return null;
+ if (_extensionNodes != null)
+ foreach (var node in _extensionNodes)
+ foreach (var supported in node.GetValues("Format"))
+ if (supported == format)
+ return (IResultWriter)node.ExtensionObject;
+ throw new NUnitEngineException("ResultWriter not found for format: " + format);
}
}
@@ -61,10 +66,15 @@ public override void StartService()
{
try
{
+ if (ServiceContext == null)
+ throw new InvalidOperationException("Only services that have a ServiceContext can be started.");
+
var extensionService = ServiceContext.GetService();
- if (extensionService != null && extensionService.Status == ServiceStatus.Started)
- _extensionNodes = extensionService.GetExtensionNodes();
+ if (extensionService.Status != ServiceStatus.Started)
+ throw new NUnitEngineException("ExtensionService must be added before ResultService");
+
+ _extensionNodes = extensionService.GetExtensionNodes();
// If there is no extension service, we start anyway using builtin writers
Status = ServiceStatus.Started;
diff --git a/src/NUnitEngine/nunit.engine/Services/ResultWriters/TestCaseResultWriter.cs b/src/NUnitEngine/nunit.engine/Services/ResultWriters/TestCaseResultWriter.cs
index d92211f94..ccfb98f22 100644
--- a/src/NUnitEngine/nunit.engine/Services/ResultWriters/TestCaseResultWriter.cs
+++ b/src/NUnitEngine/nunit.engine/Services/ResultWriters/TestCaseResultWriter.cs
@@ -28,8 +28,10 @@ public void WriteResultFile(XmlNode resultNode, string outputPath)
public void WriteResultFile(XmlNode resultNode, TextWriter writer)
{
- foreach (XmlNode node in resultNode.SelectNodes("//test-case"))
- writer.WriteLine(node.Attributes["fullname"].Value);
+ XmlNodeList? testCases = resultNode.SelectNodes("//test-case");
+ if (testCases != null)
+ foreach (XmlNode node in testCases)
+ writer.WriteLine(node.Attributes?["fullname"]?.Value);
}
}
}
diff --git a/src/NUnitEngine/nunit.engine/Services/ResultWriters/XmlTransformResultWriter.cs b/src/NUnitEngine/nunit.engine/Services/ResultWriters/XmlTransformResultWriter.cs
index 5de2f322e..c07e850c2 100644
--- a/src/NUnitEngine/nunit.engine/Services/ResultWriters/XmlTransformResultWriter.cs
+++ b/src/NUnitEngine/nunit.engine/Services/ResultWriters/XmlTransformResultWriter.cs
@@ -12,13 +12,13 @@ namespace NUnit.Engine.Services
{
public class XmlTransformResultWriter : IResultWriter
{
- private string _xsltFile;
+ private string? _xsltFile;
private readonly XslCompiledTransform _transform = new XslCompiledTransform();
- public XmlTransformResultWriter(object[] args)
+ public XmlTransformResultWriter(object?[] args)
{
Guard.ArgumentNotNull(args, "args");
- _xsltFile = args[0] as string;
+ _xsltFile = (string?)args[0];
Guard.ArgumentValid(
!string.IsNullOrEmpty(_xsltFile),
diff --git a/src/NUnitEngine/nunit.engine/Services/RuntimeFrameworkService.cs b/src/NUnitEngine/nunit.engine/Services/RuntimeFrameworkService.cs
index c117d328e..f155a3a63 100644
--- a/src/NUnitEngine/nunit.engine/Services/RuntimeFrameworkService.cs
+++ b/src/NUnitEngine/nunit.engine/Services/RuntimeFrameworkService.cs
@@ -3,6 +3,7 @@
#if NETFRAMEWORK
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.Versioning;
@@ -25,9 +26,9 @@ public class RuntimeFrameworkService : Service, IRuntimeFrameworkService, IAvail
/// Gets a RuntimeFramework instance representing the runtime under
/// which the code is currently running.
///
- public IRuntimeFramework CurrentFramework { get; private set; }
+ public IRuntimeFramework? CurrentFramework { get; private set; }
- private static string MonoPrefix;
+ private static string? MonoPrefix;
///
/// The path to the mono executable, if we are running on Mono.
@@ -56,7 +57,7 @@ public bool IsAvailable(string name, bool needX86)
{
Guard.ArgumentNotNullOrEmpty(name, nameof(name));
- if (!RuntimeFramework.TryParse(name, out RuntimeFramework requestedFramework))
+ if (!RuntimeFramework.TryParse(name, out RuntimeFramework? requestedFramework))
throw new NUnitEngineException("Invalid or unknown framework requested: " + name);
var runtimes = needX86 ? _availableX86Runtimes : _availableRuntimes;
@@ -119,6 +120,9 @@ public string SelectRuntimeFramework(TestPackage package)
private RuntimeFramework SelectRuntimeFrameworkInner(TestPackage package)
{
+ if (CurrentFramework == null)
+ throw new InvalidOperationException("Service not Started");
+
foreach (var subPackage in package.SubPackages)
{
SelectRuntimeFrameworkInner(subPackage);
@@ -133,7 +137,7 @@ private RuntimeFramework SelectRuntimeFrameworkInner(TestPackage package)
if (frameworkSetting.Length > 0)
{
- if (!RuntimeFramework.TryParse(frameworkSetting, out RuntimeFramework requestedFramework))
+ if (!RuntimeFramework.TryParse(frameworkSetting, out RuntimeFramework? requestedFramework))
throw new NUnitEngineException("Invalid or unknown framework requested: " + frameworkSetting);
log.Debug($"Requested framework for {package.Name} is {requestedFramework}");
@@ -178,7 +182,6 @@ private RuntimeFramework SelectRuntimeFrameworkInner(TestPackage package)
targetVersion = new Version(3, 1);
break;
case "Unmanaged":
- return null;
default:
throw new NUnitEngineException("Unsupported Target Framework: " + imageTargetFrameworkNameSetting);
}
@@ -204,29 +207,29 @@ public override void StartService()
{
SetCurrentFramework();
FindAvailableRuntimes();
+
+ Status = ServiceStatus.Started;
}
catch
{
Status = ServiceStatus.Error;
throw;
}
-
- Status = ServiceStatus.Started;
}
+ [MemberNotNull(nameof(CurrentFramework))]
private void SetCurrentFramework()
{
- Type monoRuntimeType = Type.GetType("Mono.Runtime", false);
- bool isMono = monoRuntimeType != null;
+ Type? monoRuntimeType = Type.GetType("Mono.Runtime", throwOnError: false);
- Runtime runtime = isMono
+ Runtime runtime = monoRuntimeType != null
? Runtime.Mono
: Runtime.Net;
int major = Environment.Version.Major;
int minor = Environment.Version.Minor;
- if (isMono)
+ if (monoRuntimeType != null)
{
switch (major)
{
@@ -242,10 +245,10 @@ private void SetCurrentFramework()
else /* It's windows */
if (major == 2)
{
- RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework");
+ using RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework");
if (key != null)
{
- string installRoot = key.GetValue("InstallRoot") as string;
+ string? installRoot = key.GetValue("InstallRoot") as string;
if (installRoot != null)
{
if (Directory.Exists(Path.Combine(installRoot, "v3.5")))
@@ -268,15 +271,15 @@ private void SetCurrentFramework()
var currentFramework = new RuntimeFramework(runtime, new Version(major, minor));
- if (isMono)
+ if (monoRuntimeType != null)
{
MonoPrefix = GetMonoPrefixFromAssembly(monoRuntimeType.Assembly);
- MethodInfo getDisplayNameMethod = monoRuntimeType.GetMethod(
+ MethodInfo? getDisplayNameMethod = monoRuntimeType.GetMethod(
"GetDisplayName", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.ExactBinding);
if (getDisplayNameMethod != null)
{
- string displayName = (string)getDisplayNameMethod.Invoke(null, new object[0]);
+ string displayName = (string)getDisplayNameMethod.Invoke(null, new object[0])!;
int space = displayName.IndexOf(' ');
if (space >= 3) // Minimum length of a version
@@ -303,7 +306,7 @@ private static string GetMonoPrefixFromAssembly(Assembly assembly)
// files have been copied to some non-standard place, we check.
for (int i = 0; i < 4; i++)
{
- string dir = Path.GetDirectoryName(prefix);
+ string? dir = Path.GetDirectoryName(prefix);
if (string.IsNullOrEmpty(dir)) break;
prefix = dir;
@@ -336,10 +339,10 @@ private void FindAvailableRuntimes()
///
private static void ApplyImageData(TestPackage package)
{
- string packageName = package.FullName;
+ string packageName = package.FullName ?? string.Empty;
Version targetVersion = new Version(0, 0);
- string frameworkName = null;
+ string? frameworkName = null;
bool requiresX86 = false;
bool requiresAssemblyResolver = false;
diff --git a/src/NUnitEngine/nunit.engine/Services/RuntimeLocators/NetCoreRuntimeLocator.cs b/src/NUnitEngine/nunit.engine/Services/RuntimeLocators/NetCoreRuntimeLocator.cs
index 0a0629dce..22115b78e 100644
--- a/src/NUnitEngine/nunit.engine/Services/RuntimeLocators/NetCoreRuntimeLocator.cs
+++ b/src/NUnitEngine/nunit.engine/Services/RuntimeLocators/NetCoreRuntimeLocator.cs
@@ -38,7 +38,7 @@ public static IEnumerable FindRuntimes(bool forX86)
private static IEnumerable GetRuntimeDirectories(bool x86)
{
- string installDir = DotNet.GetInstallDirectory(x86);
+ string? installDir = DotNet.GetInstallDirectory(x86);
if (installDir != null && Directory.Exists(installDir) &&
File.Exists(Path.Combine(installDir, "dotnet.exe")))
@@ -77,9 +77,9 @@ private static IEnumerable GetRuntimeList()
const string PREFIX = "Microsoft.NETCore.App ";
const int VERSION_START = 22;
- while (!process.StandardOutput.EndOfStream)
+ string? line;
+ while ((line = process.StandardOutput.ReadLine()) != null)
{
- var line = process.StandardOutput.ReadLine();
if (line.StartsWith(PREFIX))
yield return line.Substring(VERSION_START);
}
diff --git a/src/NUnitEngine/nunit.engine/Services/RuntimeLocators/NetFxRuntimeLocator.cs b/src/NUnitEngine/nunit.engine/Services/RuntimeLocators/NetFxRuntimeLocator.cs
index 1c7c6cd2a..bcadfa8de 100644
--- a/src/NUnitEngine/nunit.engine/Services/RuntimeLocators/NetFxRuntimeLocator.cs
+++ b/src/NUnitEngine/nunit.engine/Services/RuntimeLocators/NetFxRuntimeLocator.cs
@@ -18,7 +18,7 @@ public static IEnumerable FindRuntimes()
foreach (var framework in FindExtremelyOldDotNetFrameworkVersions())
yield return framework;
- RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\NET Framework Setup\NDP");
+ using RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\NET Framework Setup\NDP");
if (key != null)
{
foreach (string name in key.GetSubKeyNames())
@@ -48,7 +48,8 @@ public static IEnumerable FindRuntimes()
private static IEnumerable FindExtremelyOldDotNetFrameworkVersions()
{
- RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\.NETFramework\policy\v1.0");
+ using RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\.NETFramework\policy\v1.0");
+
if (key == null)
yield break;
diff --git a/src/NUnitEngine/nunit.engine/Services/Service.cs b/src/NUnitEngine/nunit.engine/Services/Service.cs
index 814dbbb28..1eb897c34 100644
--- a/src/NUnitEngine/nunit.engine/Services/Service.cs
+++ b/src/NUnitEngine/nunit.engine/Services/Service.cs
@@ -16,7 +16,7 @@ public abstract class Service : IService, IDisposable
///
/// The ServiceContext
///
- public IServiceLocator ServiceContext { get; set; }
+ public IServiceLocator? ServiceContext { get; set; }
///
/// Gets the ServiceStatus of this service
diff --git a/src/NUnitEngine/nunit.engine/Services/ServiceContext.cs b/src/NUnitEngine/nunit.engine/Services/ServiceContext.cs
index 902d000ec..728a1edea 100644
--- a/src/NUnitEngine/nunit.engine/Services/ServiceContext.cs
+++ b/src/NUnitEngine/nunit.engine/Services/ServiceContext.cs
@@ -17,7 +17,7 @@ public ServiceContext()
ServiceManager = new ServiceManager();
}
- public ServiceManager ServiceManager { get; private set; }
+ public ServiceManager ServiceManager { get; }
public int ServiceCount { get { return ServiceManager.ServiceCount; } }
@@ -29,7 +29,7 @@ public void Add(IService service)
public T GetService() where T : class
{
- return ServiceManager.GetService(typeof(T)) as T;
+ return (T)ServiceManager.GetService(typeof(T));
}
public object GetService(Type serviceType)
diff --git a/src/NUnitEngine/nunit.engine/Services/ServiceManager.cs b/src/NUnitEngine/nunit.engine/Services/ServiceManager.cs
index 639b4515c..547d458da 100644
--- a/src/NUnitEngine/nunit.engine/Services/ServiceManager.cs
+++ b/src/NUnitEngine/nunit.engine/Services/ServiceManager.cs
@@ -24,7 +24,7 @@ public class ServiceManager : IDisposable
public IService GetService( Type serviceType )
{
- IService theService = null;
+ IService? theService = null;
if (_serviceIndex.ContainsKey(serviceType))
theService = _serviceIndex[serviceType];
@@ -40,9 +40,13 @@ public IService GetService( Type serviceType )
}
if (theService == null)
- log.Error(string.Format("Requested service {0} was not found", serviceType.FullName));
- else
- log.Debug(string.Format("Request for service {0} satisfied by {1}", serviceType.Name, theService.GetType().Name));
+ {
+ string message = $"Requested service {serviceType.FullName} was not found";
+ log.Error(message);
+ throw new NUnitEngineException(message);
+ }
+
+ log.Debug(string.Format("Request for service {0} satisfied by {1}", serviceType.Name, theService.GetType().Name));
return theService;
}
@@ -127,8 +131,7 @@ protected virtual void Dispose(bool disposing)
if (disposing)
foreach (IService service in _services)
{
- IDisposable disposable = service as IDisposable;
- if (disposable != null)
+ if (service is IDisposable disposable)
disposable.Dispose();
}
diff --git a/src/NUnitEngine/nunit.engine/Services/TestAgency.cs b/src/NUnitEngine/nunit.engine/Services/TestAgency.cs
index 1a7a1e0d2..c235735bc 100644
--- a/src/NUnitEngine/nunit.engine/Services/TestAgency.cs
+++ b/src/NUnitEngine/nunit.engine/Services/TestAgency.cs
@@ -8,6 +8,7 @@
using NUnit.Engine.Internal;
using NUnit.Engine.Communication.Transports.Remoting;
using NUnit.Engine.Communication.Transports.Tcp;
+using System.Diagnostics.CodeAnalysis;
namespace NUnit.Engine.Services
{
@@ -28,8 +29,8 @@ public partial class TestAgency : ITestAgency, IService
private readonly AgentStore _agentStore = new AgentStore();
- private IRuntimeFrameworkService _runtimeService;
- private IAvailableRuntimes _availableRuntimeService;
+ private IRuntimeFrameworkService? _runtimeService;
+ private IAvailableRuntimes? _availableRuntimeService;
// Transports used for various target runtimes
private TestAgencyRemotingTransport _remotingTransport; // .NET Framework
@@ -51,8 +52,11 @@ public void Register(ITestAgent agent)
_agentStore.Register(agent);
}
- public ITestAgent GetAgent(TestPackage package)
+ public ITestAgent? GetAgent(TestPackage package)
{
+ if (_runtimeService == null || _availableRuntimeService == null)
+ throw new InvalidOperationException("TestAgency needs to be Started first");
+
// Target Runtime must be specified by this point
string runtimeSetting = package.GetSetting(EnginePackageSettings.TargetRuntimeFramework, "");
Guard.OperationValid(runtimeSetting.Length > 0, "LaunchAgentProcess called with no runtime specified");
@@ -75,7 +79,7 @@ public ITestAgent GetAgent(TestPackage package)
var agentName = targetRuntime.Id + (runAsX86 ? "-x86" : "") + "-agent";
package.AddSetting("SelectedAgentName", agentName);
- agentProcess.Exited += (sender, e) => OnAgentExit((Process)sender, agentId);
+ agentProcess.Exited += (sender, e) => OnAgentExit((Process)sender!, agentId);
agentProcess.Start();
log.Debug("Launched Agent process {0} - see nunit-agent_{0}.log", agentProcess.Id);
@@ -110,7 +114,7 @@ public ITestAgent GetAgent(TestPackage package)
return null;
}
- internal bool IsAgentProcessActive(Guid agentId, out Process process)
+ internal bool IsAgentProcessActive(Guid agentId, out Process? process)
{
return _agentStore.IsAgentProcessActive(agentId, out process);
}
@@ -162,7 +166,7 @@ private void OnAgentExit(Process process, Guid agentId)
throw new NUnitEngineException(errorMsg);
}
- public IServiceLocator ServiceContext { get; set; }
+ public IServiceLocator? ServiceContext { get; set; }
public ServiceStatus Status { get; private set; }
@@ -181,19 +185,17 @@ public void StopService()
}
}
+ [MemberNotNull(nameof(_runtimeService), nameof(_availableRuntimeService))]
public void StartService()
{
- _runtimeService = ServiceContext.GetService();
- _availableRuntimeService = ServiceContext.GetService();
-
- if (_runtimeService == null || _availableRuntimeService == null)
- {
- Status = ServiceStatus.Error;
- return;
- }
-
try
{
+ if (ServiceContext == null)
+ throw new InvalidOperationException("ServiceContext is required for TestAgency");
+
+ _runtimeService = ServiceContext.GetService();
+ _availableRuntimeService = ServiceContext.GetService();
+
_remotingTransport.Start();
_tcpTransport.Start();
Status = ServiceStatus.Started;
diff --git a/src/NUnitEngine/nunit.engine/Services/TestFilterBuilder.cs b/src/NUnitEngine/nunit.engine/Services/TestFilterBuilder.cs
index 6dc437898..cc2cb4612 100644
--- a/src/NUnitEngine/nunit.engine/Services/TestFilterBuilder.cs
+++ b/src/NUnitEngine/nunit.engine/Services/TestFilterBuilder.cs
@@ -11,7 +11,7 @@ namespace NUnit.Engine
public class TestFilterBuilder : ITestFilterBuilder
{
private List _testList = new List();
- private string _whereClause;
+ private string? _whereClause;
///
/// Add a test to be selected
@@ -51,7 +51,7 @@ public TestFilter GetFilter()
if (_whereClause != null)
- filter.Append(new TestSelectionParser().Parse(_whereClause));
+ filter.Append(TestSelectionParser.Parse(_whereClause));
filter.Append("");
diff --git a/src/NUnitEngine/nunit.engine/Services/TestRunnerFactory.cs b/src/NUnitEngine/nunit.engine/Services/TestRunnerFactory.cs
index 0a5c92edd..6a0790453 100644
--- a/src/NUnitEngine/nunit.engine/Services/TestRunnerFactory.cs
+++ b/src/NUnitEngine/nunit.engine/Services/TestRunnerFactory.cs
@@ -1,5 +1,7 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
+using System;
+using System.Diagnostics.CodeAnalysis;
using NUnit.Engine.Internal;
using NUnit.Engine.Runners;
@@ -12,17 +14,28 @@ namespace NUnit.Engine.Services
///
public class TestRunnerFactory : Service, ITestRunnerFactory
{
- private IProjectService _projectService;
+ private IProjectService? _projectService;
public override void StartService()
{
- // TestRunnerFactory requires the ProjectService
- _projectService = ServiceContext.GetService();
+ try
+ {
+ if (ServiceContext == null)
+ throw new InvalidOperationException("Only services that have a ServiceContext can be started.");
+
+ // TestRunnerFactory requires the ProjectService
+ _projectService = ServiceContext.GetService();
- // Anything returned from ServiceContext is known to be an IService
- Status = _projectService != null && ((IService)_projectService).Status == ServiceStatus.Started
- ? ServiceStatus.Started
- : ServiceStatus.Error;
+ // Anything returned from ServiceContext is known to be an IService
+ Status = ((IService)_projectService).Status == ServiceStatus.Started
+ ? ServiceStatus.Started
+ : ServiceStatus.Error;
+ }
+ catch
+ {
+ Status = ServiceStatus.Error;
+ throw;
+ }
}
///
@@ -35,6 +48,9 @@ public override void StartService()
/// A TestRunner
public ITestEngineRunner MakeTestRunner(TestPackage package)
{
+ if (ServiceContext == null)
+ throw new InvalidOperationException("ServiceContext not set.");
+
#if !NETFRAMEWORK
if (package.SubPackages.Count > 1)
return new AggregatingTestRunner(ServiceContext, package);
@@ -53,7 +69,7 @@ public ITestEngineRunner MakeTestRunner(TestPackage package)
}
#else
if (package.GetSetting(InternalEnginePackageSettings.ImageTargetFrameworkName, "").StartsWith("Unmanaged,"))
- return new UnmanagedExecutableTestRunner(package.FullName);
+ return new UnmanagedExecutableTestRunner(package.FullName ?? "Package Suite");
bool isNested = false;
foreach (TestPackage subPackage in package.SubPackages)
diff --git a/src/NUnitEngine/nunit.engine/Services/TestSelectionParser.cs b/src/NUnitEngine/nunit.engine/Services/TestSelectionParser.cs
index 387836edf..f90109e5d 100644
--- a/src/NUnitEngine/nunit.engine/Services/TestSelectionParser.cs
+++ b/src/NUnitEngine/nunit.engine/Services/TestSelectionParser.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Text;
// Missing XML Docs
@@ -11,7 +12,7 @@ namespace NUnit.Engine
{
public class TestSelectionParser
{
- private Tokenizer _tokenizer;
+ private readonly Tokenizer _tokenizer;
private static readonly Token LPAREN = new Token(TokenKind.Symbol, "(");
private static readonly Token RPAREN = new Token(TokenKind.Symbol, ")");
@@ -38,10 +39,20 @@ public class TestSelectionParser
private static readonly Token EOF = new Token(TokenKind.Eof);
- public string Parse(string input)
+ public static string Parse(string input)
{
- _tokenizer = new Tokenizer(input);
+ var parser = new TestSelectionParser(new Tokenizer(input));
+ return parser.Parse();
+ }
+
+ private TestSelectionParser(Tokenizer tokenizer)
+ {
+ _tokenizer = tokenizer;
+ }
+
+ private string Parse()
+ {
if (_tokenizer.LookAhead == EOF)
throw new TestSelectionParserException("No input provided for test selection.");
@@ -55,7 +66,7 @@ public string Parse(string input)
/// Parse a single term or an or expression, returning the xml
///
///
- public string ParseFilterExpression()
+ private string ParseFilterExpression()
{
var terms = new List();
terms.Add(ParseFilterTerm());
@@ -82,7 +93,7 @@ public string ParseFilterExpression()
///
/// Parse a single element or an and expression and return the xml
///
- public string ParseFilterTerm()
+ private string ParseFilterTerm()
{
var elements = new List();
elements.Add(ParseFilterElement());
@@ -110,7 +121,7 @@ public string ParseFilterTerm()
/// Parse a single filter element such as a category expression
/// and return the xml representation of the filter.
///
- public string ParseFilterElement()
+ private string ParseFilterElement()
{
if (LookingAt(LPAREN, NOT_OP))
return ParseExpressionInParentheses();
@@ -144,7 +155,7 @@ public string ParseFilterElement()
private static string EmitFilterElement(Token lhs, Token op, Token rhs)
{
- string fmt = null;
+ string? fmt = null;
if (op == EQ_OP1 || op == EQ_OP2)
fmt = "<{0}>{1}{0}>";
@@ -162,7 +173,7 @@ private static string EmitFilterElement(Token lhs, Token op, Token rhs)
private static string EmitPropertyElement(Token lhs, Token op, Token rhs)
{
- string fmt = null;
+ string? fmt = null;
if (op == EQ_OP1 || op == EQ_OP2)
fmt = "{1}";
diff --git a/src/NUnitEngine/nunit.engine/Services/Tokenizer.cs b/src/NUnitEngine/nunit.engine/Services/Tokenizer.cs
index e8d4fd4c5..062fcdbe4 100644
--- a/src/NUnitEngine/nunit.engine/Services/Tokenizer.cs
+++ b/src/NUnitEngine/nunit.engine/Services/Tokenizer.cs
@@ -34,9 +34,9 @@ public Token(TokenKind kind, string text)
public int Pos { get; set; }
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
- return obj is Token && this == (Token)obj;
+ return obj is Token token && this == token;
}
public override int GetHashCode()
@@ -51,15 +51,12 @@ public override string ToString()
: Kind.ToString();
}
- public static bool operator ==(Token t1, Token t2)
+ public static bool operator ==(Token? t1, Token? t2)
{
- bool t1Null = ReferenceEquals(t1, null);
- bool t2Null = ReferenceEquals(t2, null);
-
- if (t1Null && t2Null)
+ if (ReferenceEquals(t1, t2))
return true;
- if (t1Null || t2Null)
+ if (t1 is null || t2 is null)
return false;
return t1.Kind == t2.Kind && t1.Text == t2.Text;
@@ -86,7 +83,7 @@ public class Tokenizer
private const string WORD_BREAK_CHARS = "=!()&|";
private readonly string[] DOUBLE_CHAR_SYMBOLS = new string[] { "==", "=~", "!=", "!~", "&&", "||" };
- private Token _lookahead;
+ private Token? _lookahead;
public Tokenizer(string input)
{
diff --git a/src/NUnitEngine/nunit.engine/nunit.engine.csproj b/src/NUnitEngine/nunit.engine/nunit.engine.csproj
index d699651e1..0e58a3f5f 100644
--- a/src/NUnitEngine/nunit.engine/nunit.engine.csproj
+++ b/src/NUnitEngine/nunit.engine/nunit.engine.csproj
@@ -10,6 +10,8 @@
true
+
+
NUnit Engine
NUnit Engine ($(TargetFramework))
diff --git a/src/Nullable.props b/src/Nullable.props
new file mode 100644
index 000000000..08f930068
--- /dev/null
+++ b/src/Nullable.props
@@ -0,0 +1,25 @@
+
+
+
+ enable
+
+ true
+
+
+
+
+ 8.0.0
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/TestData/FakeExtensions/FakeExtensions.cs b/src/TestData/FakeExtensions/FakeExtensions.cs
index fa76265d2..f0ac2be6e 100644
--- a/src/TestData/FakeExtensions/FakeExtensions.cs
+++ b/src/TestData/FakeExtensions/FakeExtensions.cs
@@ -135,7 +135,7 @@ public string Load(string testAssemblyPath, IDictionary settings
throw new NotImplementedException();
}
- public string Run(ITestEventListener listener, string filter)
+ public string Run(ITestEventListener? listener, string filter)
{
throw new NotImplementedException();
}
diff --git a/src/TestData/FakeExtensions/FakeExtensions.csproj b/src/TestData/FakeExtensions/FakeExtensions.csproj
index 066d31608..135b138f8 100644
--- a/src/TestData/FakeExtensions/FakeExtensions.csproj
+++ b/src/TestData/FakeExtensions/FakeExtensions.csproj
@@ -8,6 +8,8 @@
..\..\..\bin\$(Configuration)\fakes
+
+