Skip to content
46 changes: 24 additions & 22 deletions tests/common/Tool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@

using Xamarin.Utils;

#nullable enable

namespace Xamarin.Tests {
class ToolMessage {
public bool IsError;
public bool IsWarning { get { return !IsError; } }
public string Prefix;
public string Prefix = "";
public int Number;
public string PrefixedNumber { get { return Prefix + Number.ToString (); } }
public string Message;
public string FileName;
public string Message = "";
public string FileName = "";
public int LineNumber;

public override string ToString ()
Expand Down Expand Up @@ -72,14 +74,14 @@ public static IEnumerable<ToolMessage> FilterUnrelatedWarnings (this IEnumerable
abstract class Tool {
StringBuilder output = new StringBuilder ();

List<string> output_lines;
List<string>? output_lines;

List<ToolMessage> messages = new List<ToolMessage> ();

public Dictionary<string, string> EnvironmentVariables { get; set; }
public Dictionary<string, string>? EnvironmentVariables { get; set; }
public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds (60);
#pragma warning disable 0649 // Field 'X' is never assigned to, and will always have its default value Y
public string WorkingDirectory;
public string? WorkingDirectory;
#pragma warning restore 0649

public IEnumerable<ToolMessage> Messages { get { return messages; } }
Expand Down Expand Up @@ -158,14 +160,14 @@ static string RemovePathAtEnd (string line)
return line;
}

public static List<ToolMessage> ParseMessages (string [] lines, string messageToolName)
public static List<ToolMessage> ParseMessages (string [] lines, string? messageToolName)
{
var messages = new List<ToolMessage> ();
ParseMessages (messages, lines, messageToolName);
return messages;
}

public static void ParseMessages (List<ToolMessage> messages, string [] lines, string messageToolName)
public static void ParseMessages (List<ToolMessage> messages, string [] lines, string? messageToolName)
{
foreach (var l in lines) {
var line = l;
Expand Down Expand Up @@ -229,7 +231,7 @@ public void ParseMessages ()
ParseMessages (messages, output.ToString ().Split ('\n', '\r'), MessageToolName);
}

static bool TrySplitCode (string code, out string prefix, out int number)
static bool TrySplitCode (string? code, out string? prefix, out int number)
{
prefix = null;
number = -1;
Expand Down Expand Up @@ -259,14 +261,14 @@ public void ParseBinLog (string binlog)
var msg = new ToolMessage ();

if (TrySplitCode (buildLogEvent.Code, out var prefix, out var number)) {
msg.Prefix = prefix;
msg.Prefix = prefix ?? "";
msg.Number = number;
}

msg.IsError = buildLogEvent.Type == BuildLogEventType.Error;
msg.Message = buildLogEvent.Message;
msg.Message = buildLogEvent.Message ?? "";
msg.LineNumber = buildLogEvent.LineNumber;
msg.FileName = buildLogEvent.File;
msg.FileName = buildLogEvent.File ?? "";

messages.Add (msg);
}
Expand Down Expand Up @@ -325,12 +327,12 @@ public void AssertErrorCount (int count, string message = "errors")
Assert.AreEqual (count, ErrorCount, message);
}

public void AssertErrorPattern (int number, string messagePattern, string filename = null, int? linenumber = null, bool custom_pattern_syntax = false)
public void AssertErrorPattern (int number, string messagePattern, string? filename = null, int? linenumber = null, bool custom_pattern_syntax = false)
{
AssertErrorPattern (MessagePrefix, number, messagePattern, filename, linenumber, custom_pattern_syntax);
}

public void AssertErrorPattern (string prefix, int number, string messagePattern, string filename = null, int? linenumber = null, bool custom_pattern_syntax = false)
public void AssertErrorPattern (string prefix, int number, string messagePattern, string? filename = null, int? linenumber = null, bool custom_pattern_syntax = false)
{
if (!messages.Any ((msg) => msg.Prefix == prefix && msg.Number == number))
Assert.Fail (string.Format ("The error '{0}{1:0000}' was not found in the output.", prefix, number));
Expand All @@ -346,12 +348,12 @@ public void AssertErrorPattern (string prefix, int number, string messagePattern
AssertFilename (prefix, number, messagePattern, matches, filename, linenumber);
}

public void AssertError (int number, string message, string filename = null, int? linenumber = null)
public void AssertError (int number, string message, string? filename = null, int? linenumber = null)
{
AssertError (MessagePrefix, number, message, filename, linenumber);
}

public void AssertError (string prefix, int number, string message, string filename = null, int? linenumber = null)
public void AssertError (string prefix, int number, string message, string? filename = null, int? linenumber = null)
{
if (!messages.Any ((msg) => msg.Prefix == prefix && msg.Number == number))
Assert.Fail (string.Format ("The error '{0}{1:0000}' was not found in the output.\nFound {2}i:\n", prefix, number, string.Join ("\n", messages)));
Expand All @@ -367,12 +369,12 @@ public void AssertError (string prefix, int number, string message, string filen
AssertFilename (prefix, number, message, matches, filename, linenumber);
}

void AssertFilename (string prefix, int number, string message, IEnumerable<ToolMessage> matches, string filename, int? linenumber)
void AssertFilename (string prefix, int number, string message, IEnumerable<ToolMessage> matches, string? filename, int? linenumber)
{
AssertFilename (messages, prefix, number, message, matches, filename, linenumber);
}

static void AssertFilename (IList<ToolMessage> messages, string prefix, int number, string message, IEnumerable<ToolMessage> matches, string filename, int? linenumber)
static void AssertFilename (IList<ToolMessage> messages, string prefix, int number, string message, IEnumerable<ToolMessage> matches, string? filename, int? linenumber)
{
if (filename is not null) {
var hasDirectory = filename.IndexOf (Path.DirectorySeparatorChar) > -1;
Expand Down Expand Up @@ -420,17 +422,17 @@ public static void AssertWarningPattern (IEnumerable<ToolMessage> messages, stri
Assert.Fail (string.Format ("The warning '{0}{1:0000}: {2}' was not found in the output:\n{3}", prefix, number, messagePattern, string.Join ("\n", details.ToArray ())));
}

public void AssertWarning (int number, string message, string filename = null, int? linenumber = null)
public void AssertWarning (int number, string message, string? filename = null, int? linenumber = null)
{
AssertWarning (MessagePrefix, number, message, filename, linenumber);
}

public void AssertWarning (string prefix, int number, string message, string filename = null, int? linenumber = null)
public void AssertWarning (string prefix, int number, string message, string? filename = null, int? linenumber = null)
{
AssertWarning (messages, prefix, number, message, filename, linenumber);
}

public static void AssertWarning (IList<ToolMessage> messages, string prefix, int number, string message, string filename = null, int? linenumber = null)
public static void AssertWarning (IList<ToolMessage> messages, string prefix, int number, string message, string? filename = null, int? linenumber = null)
{
if (!messages.Any ((msg) => msg.Prefix == prefix && msg.Number == number))
Assert.Fail (string.Format ("The warning '{0}{1:0000}' was not found in the output.", prefix, number));
Expand Down Expand Up @@ -493,6 +495,6 @@ public void ForAllOutputLines (Action<string> action)

protected abstract string ToolPath { get; }
protected abstract string MessagePrefix { get; }
protected virtual string MessageToolName { get { return null; } }
protected virtual string? MessageToolName { get { return null; } }
}
}
39 changes: 21 additions & 18 deletions tests/common/mac/ProjectTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using Xamarin.Utils;
using Xamarin.Tests;

#nullable enable

namespace Xamarin.MMP.Tests {
internal class MessageTool : Tool {
public MessageTool ()
Expand Down Expand Up @@ -43,7 +45,7 @@ internal MessageTool Messages {
public class BuildResult {
public readonly string BinLogPath;

string build_output;
string? build_output;
public string BuildOutput {
get {
if (build_output is null)
Expand All @@ -52,7 +54,7 @@ public string BuildOutput {
}
}

string [] build_output_lines;
string []? build_output_lines;
public IList<string> BuildOutputLines {
get {
if (build_output_lines is null)
Expand All @@ -76,7 +78,7 @@ public bool HasMessage (int code, string message)
return Messages.Messages.Any (v => v.Number == code && v.Message == message);
}

MessageTool messages;
MessageTool? messages;
internal MessageTool Messages {
get {
if (messages is null) {
Expand Down Expand Up @@ -121,12 +123,12 @@ public class UnifiedTestConfig {
public string SystemMonoVersion { get; set; } = "";
public string TargetFrameworkVersion { get; set; } = "";
public Dictionary<string, string> PlistReplaceStrings { get; set; } = new Dictionary<string, string> ();
public Tuple<string, string> CustomProjectReplacement { get; set; } = null;
public Tuple<string, string>? CustomProjectReplacement { get; set; } = null;

// Binding project specific
public string APIDefinitionConfig { get; set; }
public string StructsAndEnumsConfig { get; set; }
public string LinkWithName { get; set; } = null; // Only generates if non-null
public string? APIDefinitionConfig { get; set; }
public string? StructsAndEnumsConfig { get; set; }
public string? LinkWithName { get; set; } = null; // Only generates if non-null

// Unified Executable Specific
public bool AssetIcons { get; set; }
Expand Down Expand Up @@ -165,17 +167,17 @@ public static string RunAndAssert (string exe, params string [] args)
return RunAndAssert (exe, args, "Command: " + exe);
}

public static string RunAndAssert (string exe, IList<string> args, string stepName, bool shouldFail = false, Func<string> getAdditionalFailInfo = null, Dictionary<string, string> environment = null)
public static string RunAndAssert (string exe, IList<string> args, string stepName, bool shouldFail = false, Func<string>? getAdditionalFailInfo = null, Dictionary<string, string?>? environment = null)
{
StringBuilder output = new StringBuilder ();
environment ??= new Dictionary<string, string> ();
environment ??= new Dictionary<string, string?> ();
environment ["DYLD_FALLBACK_LIBRARY_PATH"] = null;
int compileResult = ExecutionHelper.Execute (exe, args, environmentVariables: environment, stdout: output, stderr: output);
if (!shouldFail && compileResult != 0) {
Console.WriteLine ($"Execution of the following command failed (exit code: {compileResult}):");
Console.WriteLine ($"cd {Environment.CurrentDirectory}");
foreach (var kvp in Environment.GetEnvironmentVariables ().Cast<System.Collections.DictionaryEntry> ().OrderBy (v => v.Key))
Console.WriteLine ($"export {kvp.Key}={StringUtils.Quote (kvp.Value.ToString ())}");
Console.WriteLine ($"export {kvp.Key}={StringUtils.Quote (kvp.Value?.ToString () ?? "")}");
Console.WriteLine ($"{exe} {StringUtils.FormatArguments (args)}");
Console.WriteLine (output);
}
Expand All @@ -192,13 +194,14 @@ public static void CleanUnifiedProject (string csprojTarget)
RunAndAssert ("Legacy projects not supported anymore", new [] { "--", csprojTarget, "/t:clean" }, "Clean", environment: Configuration.GetBuildEnvironment (ApplePlatform.MacOSX));
}

public static BuildResult BuildProject (string csprojTarget, bool shouldFail = false, bool release = false, Dictionary<string, string> environment = null, IList<string> extraArgs = null)
public static BuildResult BuildProject (string csprojTarget, bool shouldFail = false, bool release = false, Dictionary<string, string?>? environment = null, IList<string>? extraArgs = null)
{
Configuration.SetBuildVariables (ApplePlatform.MacOSX, ref environment);

// This is to force build to use our mmp and not system mmp
var buildArgs = new List<string> ();
var binlog = Path.Combine (Path.GetDirectoryName (csprojTarget), $"log-{DateTime.Now:yyyyMMdd_HHmmss}.binlog");
var binlogDir = Path.GetDirectoryName (csprojTarget) ?? ".";
var binlog = Path.Combine (binlogDir, $"log-{DateTime.Now:yyyyMMdd_HHmmss}.binlog");
buildArgs.Add ($"/bl:{binlog}");
Console.WriteLine ($"Binlog: {binlog}");

Expand All @@ -217,7 +220,7 @@ public static BuildResult BuildProject (string csprojTarget, bool shouldFail = f

Func<string> getBuildProjectErrorInfo = () => {
string csprojText = "\n\n\n\tCSProj: \n" + File.ReadAllText (csprojTarget);
string csprojLocation = Path.GetDirectoryName (csprojTarget);
var csprojLocation = Path.GetDirectoryName (csprojTarget) ?? ".";
string fileList = "\n\n\tFiles: " + String.Join (" ", Directory.GetFiles (csprojLocation).Select (x => x.Replace (csprojLocation + "/", "")));
return csprojText + fileList;
};
Expand Down Expand Up @@ -293,10 +296,10 @@ public static string GenerateEXEProject (UnifiedTestConfig config)
public static string GenerateBindingLibraryProject (UnifiedTestConfig config)
{
string sourceDir = FindSourceDirectory ();
CopyFileWithSubstitutions (Path.Combine (sourceDir, "ApiDefinition.cs"), Path.Combine (config.TmpDir, "ApiDefinition.cs"), text => text.Replace ("REPLACE_CODE_REPLACE", config.APIDefinitionConfig));
CopyFileWithSubstitutions (Path.Combine (sourceDir, "StructsAndEnums.cs"), Path.Combine (config.TmpDir, "StructsAndEnums.cs"), text => text.Replace ("REPLACE_CODE_REPLACE", config.StructsAndEnumsConfig));
CopyFileWithSubstitutions (Path.Combine (sourceDir, "ApiDefinition.cs"), Path.Combine (config.TmpDir, "ApiDefinition.cs"), text => text.Replace ("REPLACE_CODE_REPLACE", config.APIDefinitionConfig ?? ""));
CopyFileWithSubstitutions (Path.Combine (sourceDir, "StructsAndEnums.cs"), Path.Combine (config.TmpDir, "StructsAndEnums.cs"), text => text.Replace ("REPLACE_CODE_REPLACE", config.StructsAndEnumsConfig ?? ""));

string linkWithName = null;
string? linkWithName = null;
if (config.LinkWithName is not null) {
string fileName = Path.GetFileNameWithoutExtension (config.LinkWithName);
linkWithName = $"{fileName}.linkwith.cs";
Expand Down Expand Up @@ -362,7 +365,7 @@ public static string GenerateUnifiedExecutableProject (UnifiedTestConfig config)
return GenerateEXEProject (config);
}

public static BuildResult GenerateAndBuildUnifiedExecutable (UnifiedTestConfig config, bool shouldFail = false, Dictionary<string, string> environment = null)
public static BuildResult GenerateAndBuildUnifiedExecutable (UnifiedTestConfig config, bool shouldFail = false, Dictionary<string, string?>? environment = null)
{
string csprojTarget = GenerateUnifiedExecutableProject (config);
return BuildProject (csprojTarget, shouldFail: shouldFail, release: config.Release, environment: environment);
Expand All @@ -373,7 +376,7 @@ public static string RunGeneratedUnifiedExecutable (UnifiedTestConfig config)
return RunEXEAndVerifyGUID (config.TmpDir, config.guid, config.ExecutablePath);
}

public static OutputText TestUnifiedExecutable (UnifiedTestConfig config, bool shouldFail = false, Dictionary<string, string> environment = null)
public static OutputText TestUnifiedExecutable (UnifiedTestConfig config, bool shouldFail = false, Dictionary<string, string?>? environment = null)
{
AddGUIDTestCode (config);

Expand Down
8 changes: 5 additions & 3 deletions tests/generator/BGenTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,11 @@ int Execute ()
if (in_process) {
int rv;
var previous_environment = new Dictionary<string, string?> ();
foreach (var kvp in EnvironmentVariables) {
previous_environment [kvp.Key] = Environment.GetEnvironmentVariable (kvp.Key);
Environment.SetEnvironmentVariable (kvp.Key, kvp.Value);
if (EnvironmentVariables is not null) {
foreach (var kvp in EnvironmentVariables) {
previous_environment [kvp.Key] = Environment.GetEnvironmentVariable (kvp.Key);
Environment.SetEnvironmentVariable (kvp.Key, kvp.Value);
}
}
ThreadStaticTextWriter.ReplaceConsole (Output);
try {
Expand Down
2 changes: 1 addition & 1 deletion tests/msbuild/Xamarin.MacDev.Tasks.Tests/AssemblySetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void AssemblyInitialization ()
const string msbuild_exe_path = "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/msbuild/15.0/bin/MSBuild.dll";
if (is_in_vsmac) {
var env = new Dictionary<string, string> {
{ "MD_APPLE_SDK_ROOT", Path.GetDirectoryName (Path.GetDirectoryName (Configuration.xcode_root)) },
{ "MD_APPLE_SDK_ROOT", Path.GetDirectoryName (Path.GetDirectoryName (Configuration.xcode_root)) ?? string.Empty },
{ "MSBUILD_EXE_PATH", msbuild_exe_path },
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ public void DefaultAppIcons (ApplePlatform platform)
ExecuteTask (actool);

Assert.IsNotNull (actool.PartialAppManifest, "PartialAppManifest");
var appIconsManifestPath = actool.PartialAppManifest.ItemSpec!;
var appIconsManifestPath = actool.PartialAppManifest?.ItemSpec ?? "";
var appIconsManifest = PDictionary.FromFile (appIconsManifestPath)!;
Assert.AreEqual (0, appIconsManifest.Count, $"Partial plist contents: {actool.PartialAppManifest.ItemSpec}");
Assert.AreEqual (0, appIconsManifest.Count, $"Partial plist contents: {actool.PartialAppManifest?.ItemSpec}");
var expectedXml =
"""
<?xml version="1.0" encoding="UTF-8"?>
Expand All @@ -122,7 +122,7 @@ public void AllAppIcons (ApplePlatform platform)

Assert.IsNotNull (actool.PartialAppManifest, "PartialAppManifest");

var appIconsManifestPath = actool.PartialAppManifest.ItemSpec!;
var appIconsManifestPath = actool.PartialAppManifest?.ItemSpec ?? "";
string expectedXml;
if (platform == ApplePlatform.TVOS) {
expectedXml =
Expand Down Expand Up @@ -295,7 +295,7 @@ public void AppIcon (ApplePlatform platform)

Assert.IsNotNull (actool.PartialAppManifest, "PartialAppManifest");

var appIconsManifestPath = actool.PartialAppManifest.ItemSpec!;
var appIconsManifestPath = actool.PartialAppManifest?.ItemSpec ?? "";
string expectedXml;
if (platform == ApplePlatform.MacOSX || platform == ApplePlatform.MacCatalyst) {
expectedXml =
Expand Down Expand Up @@ -392,7 +392,7 @@ public void AppIconAndAlternateIcons (ApplePlatform platform)

Assert.IsNotNull (actool.PartialAppManifest, "PartialAppManifest");

var appIconsManifestPath = actool.PartialAppManifest.ItemSpec!;
var appIconsManifestPath = actool.PartialAppManifest?.ItemSpec ?? "";
string expectedXml;
if (platform == ApplePlatform.MacOSX || platform == ApplePlatform.MacCatalyst) {
expectedXml =
Expand Down Expand Up @@ -547,7 +547,7 @@ public void AlternateIcons (ApplePlatform platform)
throw new NotImplementedException (platform.ToString ());
}

var appIconsManifestPath = actool.PartialAppManifest.ItemSpec!;
var appIconsManifestPath = actool.PartialAppManifest?.ItemSpec ?? "";
PListAsserts.AreStringsEqual (expectedXml, File.ReadAllText (appIconsManifestPath), "Partial plist contents");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public void Bug656983 ()
task.ProjectDir = "~/"; // not important, but required (so can't be null)
task.ResponseFilePath = Path.Combine (Cache.CreateTemporaryDirectory (), "response-file.txt");

#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
task.OutputAssembly = null; // default, but important for the bug (in case that default changes)
#pragma warning restore CS8625
task.ExtraArgs = "-invalid";
var args = task.GenerateCommandLineArguments ();
args.AddRange (File.ReadAllLines (task.ResponseFilePath));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace Xamarin.MacDev.Tasks {
[TestFixture]
public class CollectITunesArtworkTaskTests : TestBase {
string AppPath => Path.GetDirectoryName (GetType ().Assembly.Location);
string AppPath => Path.GetDirectoryName (GetType ().Assembly.Location) ?? "";

[Test]
public void UnknownImageFormat ()
Expand Down
Loading
Loading