[tests] Merge the msbuild-mac tests into the Xamarin.MacDev.Tests project. (#10129)

This commit is contained in:
Rolf Bjarne Kvinge 2020-12-04 13:05:51 +01:00 коммит произвёл GitHub
Родитель 4f75b9e8da
Коммит 9e20285ebb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
31 изменённых файлов: 838 добавлений и 718 удалений

Просмотреть файл

@ -193,7 +193,6 @@
/tests/xtro-sharpie @spouliot
/tests/mmptest @rolfbjarne
/tests/common/mac @rolfbjarne
/tests/msbuild-mac @rolfbjarne
/tests/bcl-tests @mandel-macaque
/tools/common @rolfbjarne @spouliot

Просмотреть файл

@ -12,6 +12,7 @@
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="Mono.Cecil" Version="0.11.2" />
<PackageReference Include="MSBuild.StructuredLogger" Version="2.1.176" />
</ItemGroup>
<ItemGroup>
@ -48,5 +49,11 @@
<Compile Include="..\..\tools\common\StringUtils.cs">
<Link>StringUtils.cs</Link>
</Compile>
<Compile Include="..\common\Tool.cs">
<Link>Tool.cs</Link>
</Compile>
<Compile Include="..\common\BinLog.cs">
<Link>BinLog.cs</Link>
</Compile>
</ItemGroup>
</Project>

Просмотреть файл

@ -1,12 +1,34 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging.StructuredLogger;
#nullable enable
namespace Xamarin.Tests
{
public class BuildLogEvent {
public BuildLogEventType Type;
public int ColumnNumber;
public int EndColumnNumber;
public int LineNumber;
public int EndLineNumber;
public string? Code;
public string? SubCategory;
public string? File;
public string? ProjectFile;
public string? Message;
}
public enum BuildLogEventType {
Message,
Warning,
Error,
}
public class BinLog {
// Returns a diagnostic build log as an enumeration of lines
@ -24,11 +46,76 @@ namespace Xamarin.Tests
if (args.Message == null)
continue;
if (args is ProjectStartedEventArgs psea) {
if (psea.Properties != null) {
yield return "Initial Properties";
foreach (var prop in psea.Properties.Cast<System.Collections.DictionaryEntry> ().OrderBy (v => v.Key))
yield return $"{prop.Key} = {prop.Value}";
}
}
foreach (var line in args.Message.Split (eols, System.StringSplitOptions.RemoveEmptyEntries))
yield return line;
}
}
public static IEnumerable<BuildLogEvent> GetBuildMessages (string path)
{
var reader = new BinLogReader ();
var eols = new char [] { '\n', '\r' };
foreach (var record in reader.ReadRecords (path)) {
if (record == null)
continue;
var args = record.Args;
if (args == null)
continue;
if (args is BuildErrorEventArgs buildError) {
var ea = buildError;
yield return new BuildLogEvent {
Type = BuildLogEventType.Error,
File = ea.File,
LineNumber = ea.LineNumber,
EndLineNumber = ea.EndLineNumber,
ColumnNumber = ea.ColumnNumber,
EndColumnNumber = ea.EndColumnNumber,
Message = ea.Message,
ProjectFile = ea.ProjectFile,
Code = ea.Code,
SubCategory = ea.Subcategory,
};
} else if (args is BuildWarningEventArgs buildWarning) {
var ea = buildWarning;
yield return new BuildLogEvent {
Type = BuildLogEventType.Warning,
File = ea.File,
LineNumber = ea.LineNumber,
EndLineNumber = ea.EndLineNumber,
ColumnNumber = ea.ColumnNumber,
EndColumnNumber = ea.EndColumnNumber,
Message = ea.Message,
ProjectFile = ea.ProjectFile,
Code = ea.Code,
SubCategory = ea.Subcategory,
};
} else if (args is BuildMessageEventArgs buildMessage) {
var ea = buildMessage;
yield return new BuildLogEvent {
Type = BuildLogEventType.Message,
File = ea.File,
LineNumber = ea.LineNumber,
EndLineNumber = ea.EndLineNumber,
ColumnNumber = ea.ColumnNumber,
EndColumnNumber = ea.EndColumnNumber,
Message = ea.Message,
ProjectFile = ea.ProjectFile,
Code = ea.Code,
SubCategory = ea.Subcategory,
};
}
}
}
// Returns a diagnostic build log as a string
public static string PrintToString (string path)
{

Просмотреть файл

@ -10,406 +10,6 @@ using Xamarin.Utils;
namespace Xamarin.Tests
{
class ToolMessage
{
public bool IsError;
public bool IsWarning { get { return !IsError; } }
public string Prefix;
public int Number;
public string PrefixedNumber { get { return Prefix + Number.ToString (); } }
public string Message;
public string FileName;
public int LineNumber;
public override string ToString ()
{
if (string.IsNullOrEmpty (FileName)) {
return String.Format ("{0} {3}{1:0000}: {2}", IsError ? "error" : "warning", Number, Message, Prefix);
} else {
return String.Format ("{3}({4}): {0} {5}{1:0000}: {2}", IsError ? "error" : "warning", Number, Message, FileName, LineNumber, Prefix);
}
}
}
abstract class Tool
{
StringBuilder output = new StringBuilder ();
List<string> output_lines;
List<ToolMessage> messages = new List<ToolMessage> ();
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;
#pragma warning restore 0649
public IEnumerable<ToolMessage> Messages { get { return messages; } }
public List<string> OutputLines {
get {
if (output_lines == null) {
output_lines = new List<string> ();
output_lines.AddRange (output.ToString ().Split ('\n'));
}
return output_lines;
}
}
public StringBuilder Output {
get {
return output;
}
}
public int Execute (IList<string> arguments)
{
return Execute (ToolPath, arguments, false);
}
public int Execute (IList<string> arguments, bool always_show_output)
{
return Execute (ToolPath, arguments, always_show_output);
}
public int Execute (string toolPath, IList<string> arguments)
{
return Execute (toolPath, arguments, false);
}
public int Execute (string toolPath, IList<string> arguments, bool always_show_output)
{
output.Clear ();
output_lines = null;
var args = new List<string> ();
args.Add ("-t");
args.Add ("--");
args.Add (toolPath);
args.AddRange (arguments);
var rv = ExecutionHelper.Execute (Configuration.XIBuildPath, args, EnvironmentVariables, output, output, workingDirectory: WorkingDirectory);
if ((rv != 0 || always_show_output) && output.Length > 0)
Console.WriteLine ("\t" + output.ToString ().Replace ("\n", "\n\t"));
ParseMessages ();
return rv;
}
static bool IndexOfAny (string line, out int start, out int end, params string [] values)
{
foreach (var value in values) {
start = line.IndexOf (value, StringComparison.Ordinal);
if (start >= 0) {
end = start + value.Length;
return true;
}
}
start = -1;
end = -1;
return false;
}
static string RemovePathAtEnd (string line)
{
if (line.TrimEnd ().EndsWith ("]", StringComparison.Ordinal)) {
var start = line.LastIndexOf ("[", StringComparison.Ordinal);
if (start >= 0) {
// we want to get the space before `[` too.
if (start > 0 && line [start - 1] == ' ')
start --;
line = line.Substring (0, start);
return line;
}
}
return line;
}
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)
{
foreach (var l in lines) {
var line = l;
var msg = new ToolMessage ();
var origin = string.Empty;
if (IndexOfAny (line, out var idxError, out var endError, ": error ", ": error ")) {
msg.IsError = true;
origin = line.Substring (0, idxError);
line = line.Substring (endError);
line = RemovePathAtEnd (line);
} else if (IndexOfAny (line, out var idxWarning, out var endWarning, ": warning ", ": warning ")) {
origin = line.Substring (0, idxWarning);
line = line.Substring (endWarning);
line = RemovePathAtEnd (line);
} else if (line.StartsWith ("error ", StringComparison.Ordinal)) {
msg.IsError = true;
line = line.Substring (6);
} else if (line.StartsWith ("warning ", StringComparison.Ordinal)) {
msg.IsError = false;
line = line.Substring (8);
} else {
// something else
continue;
}
if (line.Length < 7)
continue; // something else
msg.Prefix = line.Substring (0, 2);
if (!int.TryParse (line.Substring (2, 4), out msg.Number))
continue; // something else
line = line.Substring (8);
var toolName = messageToolName;
if (toolName != null && line.StartsWith (toolName + ": ", StringComparison.Ordinal))
line = line.Substring (toolName.Length + 2);
msg.Message = line;
if (!string.IsNullOrEmpty (origin)) {
var idx = origin.IndexOf ('(');
if (idx > 0) {
var closing = origin.IndexOf (')');
var number = 0;
if (!int.TryParse (origin.Substring (idx + 1, closing - idx - 1), out number))
continue;
msg.LineNumber = number;
msg.FileName = origin.Substring (0, idx);
} else {
msg.FileName = origin;
}
}
messages.Add (msg);
}
}
public void ParseMessages ()
{
messages.Clear ();
ParseMessages (messages, output.ToString ().Split ('\n'), MessageToolName);
}
public bool HasErrorPattern (string prefix, int number, string messagePattern)
{
foreach (var msg in messages) {
if (msg.IsError && msg.Prefix == prefix && msg.Number == number && Regex.IsMatch (msg.Message, messagePattern))
return true;
}
return false;
}
public int ErrorCount {
get {
return messages.Count ((v) => v.IsError);
}
}
public int WarningCount {
get {
return GetWarningCount (messages);
}
}
public static int GetWarningCount (IEnumerable<ToolMessage> messages)
{
return messages.Count ((v) => v.IsWarning);
}
public bool HasError (string prefix, int number, string message)
{
foreach (var msg in messages) {
if (msg.IsError && msg.Prefix == prefix && msg.Number == number && msg.Message == message)
return true;
}
return false;
}
public void AssertWarningCount (int count, string message = "warnings")
{
AssertWarningCount (messages, count, message);
}
public static void AssertWarningCount (IEnumerable<ToolMessage> messages, int count, string message = "warnings")
{
if (count != GetWarningCount (messages))
Assert.Fail ($"{message}\nExpected: {count}\nBut was: { GetWarningCount (messages)}\nWarnings:\n\t{string.Join ("\n\t", messages.Where ((v) => v.IsWarning).Select ((v) => v.ToString ()))}");
}
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)
{
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)
{
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));
// Custom pattern syntax: escape parenthesis and brackets so that they're treated like normal characters.
var processedPattern = custom_pattern_syntax ? messagePattern.Replace ("(", "[(]").Replace (")", "[)]").Replace ("[]", "[[][]]") + "$" : messagePattern;
var matches = messages.Where ((msg) => Regex.IsMatch (msg.Message, processedPattern));
if (!matches.Any ()) {
var details = messages.Where ((msg) => msg.Prefix == prefix && msg.Number == number && !Regex.IsMatch (msg.Message, processedPattern)).Select ((msg) => string.Format ("\tThe message '{0}' did not match the pattern '{1}'.", msg.Message, messagePattern));
Assert.Fail (string.Format ("The error '{0}{1:0000}: {2}' was not found in the output:\n{3}", prefix, number, messagePattern, string.Join ("\n", details.ToArray ())));
}
AssertFilename (prefix, number, messagePattern, matches, filename, linenumber);
}
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)
{
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));
var matches = messages.Where ((msg) => msg.Message == message);
if (!matches.Any ()) {
var details = messages.
Where ((msg) => msg.Prefix == prefix && msg.Number == number && msg.Message != message).
Select ((msg) => string.Format ("\tMessage #{2} did not match:\n\t\tactual: '{0}'\n\t\texpected: '{1}'", msg.Message, message, messages.IndexOf (msg) + 1));
Assert.Fail (string.Format ("The error '{0}{1:0000}: {2}' was not found in the output:\n{3}", prefix, number, message, string.Join ("\n", details.ToArray ())));
}
AssertFilename (prefix, number, message, matches, filename, 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)
{
if (filename != null) {
var hasDirectory = filename.IndexOf (Path.DirectorySeparatorChar) > -1;
if (!matches.Any ((v) => {
if (hasDirectory) {
// Check the entire path
return filename == v.FileName;
} else {
// Don't compare the directory unless one was specified.
return filename == Path.GetFileName (v.FileName);
}
})) {
var details = matches.Select ((msg) => string.Format ("\tMessage #{2} did not contain expected filename:\n\t\tactual: '{0}'\n\t\texpected: '{1}'", hasDirectory ? msg.FileName : Path.GetFileName (msg.FileName), filename, messages.IndexOf (msg) + 1));
Assert.Fail (string.Format ($"The filename '{filename}' was not found in the output for the error {prefix}{number:X4}: {message}:\n{string.Join ("\n", details.ToArray ())}"));
}
}
if (linenumber != null) {
if (!matches.Any ((v) => linenumber.Value == v.LineNumber)) {
var details = matches.Select ((msg) => string.Format ("\tMessage #{2} did not contain expected line number:\n\t\tactual: '{0}'\n\t\texpected: '{1}'", msg.LineNumber, linenumber, messages.IndexOf (msg) + 1));
Assert.Fail (string.Format ($"The linenumber '{linenumber.Value}' was not found in the output for the error {prefix}{number:X4}: {message}:\n{string.Join ("\n", details.ToArray ())}"));
}
}
}
public void AssertWarningPattern (int number, string messagePattern)
{
AssertWarningPattern (MessagePrefix, number, messagePattern);
}
public void AssertWarningPattern (string prefix, int number, string messagePattern)
{
AssertWarningPattern (messages, prefix, number, messagePattern);
}
public static void AssertWarningPattern (IEnumerable<ToolMessage> messages, string prefix, int number, string messagePattern)
{
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));
if (messages.Any ((msg) => Regex.IsMatch (msg.Message, messagePattern)))
return;
var details = messages.Where ((msg) => msg.Prefix == prefix && msg.Number == number && !Regex.IsMatch (msg.Message, messagePattern)).Select ((msg) => string.Format ("\tThe message '{0}' did not match the pattern '{1}'.", msg.Message, messagePattern));
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)
{
AssertWarning (MessagePrefix, number, message, filename, linenumber);
}
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)
{
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));
var matches = messages.Where ((msg) => msg.Message == message);
if (!matches.Any ()) {
var details = messages.Where ((msg) => msg.Prefix == prefix && msg.Number == number && msg.Message != message).Select ((msg) => string.Format ("\tMessage #{2} did not match:\n\t\tactual: '{0}'\n\t\texpected: '{1}'", msg.Message, message, messages.IndexOf (msg) + 1));
Assert.Fail (string.Format ("The warning '{0}{1:0000}: {2}' was not found in the output:\n{3}", prefix, number, message, string.Join ("\n", details.ToArray ())));
}
AssertFilename (messages, prefix, number, message, matches, filename, linenumber);
}
public void AssertNoWarnings ()
{
var warnings = messages.Where ((v) => v.IsWarning);
if (!warnings.Any ())
return;
Assert.Fail ("No warnings expected, but got:\n{0}\t", string.Join ("\n\t", warnings.Select ((v) => v.Message).ToArray ()));
}
public bool HasOutput (string line)
{
return OutputLines.Contains (line);
}
public bool HasOutputPattern (string linePattern)
{
foreach (var line in OutputLines) {
if (Regex.IsMatch (line, linePattern, RegexOptions.CultureInvariant))
return true;
}
return false;
}
public void AssertOutputPattern (string linePattern)
{
if (!HasOutputPattern (linePattern))
Assert.Fail (string.Format ("The output does not contain the line '{0}'", linePattern));
}
public void ForAllOutputLines (Action<string> action)
{
foreach (var line in OutputLines)
action (line);
}
protected abstract string ToolPath { get; }
protected abstract string MessagePrefix { get; }
protected virtual string MessageToolName { get { return null; } }
}
class XBuild
{
public static string ToolPath {

464
tests/common/Tool.cs Normal file
Просмотреть файл

@ -0,0 +1,464 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using NUnit.Framework;
using Xamarin.Utils;
namespace Xamarin.Tests
{
class ToolMessage
{
public bool IsError;
public bool IsWarning { get { return !IsError; } }
public string Prefix;
public int Number;
public string PrefixedNumber { get { return Prefix + Number.ToString (); } }
public string Message;
public string FileName;
public int LineNumber;
public override string ToString ()
{
if (string.IsNullOrEmpty (FileName)) {
return String.Format ("{0} {3}{1:0000}: {2}", IsError ? "error" : "warning", Number, Message, Prefix);
} else {
return String.Format ("{3}({4}): {0} {5}{1:0000}: {2}", IsError ? "error" : "warning", Number, Message, FileName, LineNumber, Prefix);
}
}
}
abstract class Tool
{
StringBuilder output = new StringBuilder ();
List<string> output_lines;
List<ToolMessage> messages = new List<ToolMessage> ();
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;
#pragma warning restore 0649
public IEnumerable<ToolMessage> Messages { get { return messages; } }
public List<string> OutputLines {
get {
if (output_lines == null) {
output_lines = new List<string> ();
output_lines.AddRange (output.ToString ().Split ('\n'));
}
return output_lines;
}
}
public StringBuilder Output {
get {
return output;
}
}
public int Execute (IList<string> arguments)
{
return Execute (ToolPath, arguments, false);
}
public int Execute (IList<string> arguments, bool always_show_output)
{
return Execute (ToolPath, arguments, always_show_output);
}
public int Execute (string toolPath, IList<string> arguments)
{
return Execute (toolPath, arguments, false);
}
public int Execute (string toolPath, IList<string> arguments, bool always_show_output)
{
output.Clear ();
output_lines = null;
var args = new List<string> ();
args.Add ("-t");
args.Add ("--");
args.Add (toolPath);
args.AddRange (arguments);
var rv = ExecutionHelper.Execute (Configuration.XIBuildPath, args, EnvironmentVariables, output, output, workingDirectory: WorkingDirectory);
if ((rv != 0 || always_show_output) && output.Length > 0)
Console.WriteLine ("\t" + output.ToString ().Replace ("\n", "\n\t"));
ParseMessages ();
return rv;
}
static bool IndexOfAny (string line, out int start, out int end, params string [] values)
{
foreach (var value in values) {
start = line.IndexOf (value, StringComparison.Ordinal);
if (start >= 0) {
end = start + value.Length;
return true;
}
}
start = -1;
end = -1;
return false;
}
static string RemovePathAtEnd (string line)
{
if (line.TrimEnd ().EndsWith ("]", StringComparison.Ordinal)) {
var start = line.LastIndexOf ("[", StringComparison.Ordinal);
if (start >= 0) {
// we want to get the space before `[` too.
if (start > 0 && line [start - 1] == ' ')
start --;
line = line.Substring (0, start);
return line;
}
}
return line;
}
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)
{
foreach (var l in lines) {
var line = l;
var msg = new ToolMessage ();
var origin = string.Empty;
if (IndexOfAny (line, out var idxError, out var endError, ": error ", ": error ")) {
msg.IsError = true;
origin = line.Substring (0, idxError);
line = line.Substring (endError);
line = RemovePathAtEnd (line);
} else if (IndexOfAny (line, out var idxWarning, out var endWarning, ": warning ", ": warning ")) {
origin = line.Substring (0, idxWarning);
line = line.Substring (endWarning);
line = RemovePathAtEnd (line);
} else if (line.StartsWith ("error ", StringComparison.Ordinal)) {
msg.IsError = true;
line = line.Substring (6);
} else if (line.StartsWith ("warning ", StringComparison.Ordinal)) {
msg.IsError = false;
line = line.Substring (8);
} else {
// something else
continue;
}
if (line.Length < 7)
continue; // something else
msg.Prefix = line.Substring (0, 2);
if (!int.TryParse (line.Substring (2, 4), out msg.Number))
continue; // something else
line = line.Substring (8);
var toolName = messageToolName;
if (toolName != null && line.StartsWith (toolName + ": ", StringComparison.Ordinal))
line = line.Substring (toolName.Length + 2);
msg.Message = line;
if (!string.IsNullOrEmpty (origin)) {
var idx = origin.IndexOf ('(');
if (idx > 0) {
var closing = origin.IndexOf (')');
var number = 0;
if (!int.TryParse (origin.Substring (idx + 1, closing - idx - 1), out number))
continue;
msg.LineNumber = number;
msg.FileName = origin.Substring (0, idx);
} else {
msg.FileName = origin;
}
}
messages.Add (msg);
}
}
public void ParseMessages ()
{
messages.Clear ();
ParseMessages (messages, output.ToString ().Split ('\n'), MessageToolName);
}
static bool TrySplitCode (string code, out string prefix, out int number)
{
prefix = null;
number = -1;
if (code == null)
return false;
for (var i = 0; i < code.Length; i++) {
var c = code [i];
if (c >= '0' && c <= '9') {
prefix = code.Substring (0, i);
return int.TryParse (code.Substring (i), out number);
}
}
return false;
}
public void ParseBinLog (string binlog)
{
messages.Clear ();
foreach (var buildLogEvent in BinLog.GetBuildMessages (binlog)) {
// We're only interested in warnings and errors
if (buildLogEvent.Type != BuildLogEventType.Error && buildLogEvent.Type != BuildLogEventType.Warning)
continue;
var msg = new ToolMessage ();
if (TrySplitCode (buildLogEvent.Code, out var prefix, out var number)) {
msg.Prefix = prefix;
msg.Number = number;
}
msg.IsError = buildLogEvent.Type == BuildLogEventType.Error;
msg.Message = buildLogEvent.Message;
msg.LineNumber = buildLogEvent.LineNumber;
msg.FileName = buildLogEvent.File;
messages.Add (msg);
}
}
public bool HasErrorPattern (string prefix, int number, string messagePattern)
{
foreach (var msg in messages) {
if (msg.IsError && msg.Prefix == prefix && msg.Number == number && Regex.IsMatch (msg.Message, messagePattern))
return true;
}
return false;
}
public int ErrorCount {
get {
return messages.Count ((v) => v.IsError);
}
}
public int WarningCount {
get {
return GetWarningCount (messages);
}
}
public static int GetWarningCount (IEnumerable<ToolMessage> messages)
{
return messages.Count ((v) => v.IsWarning);
}
public bool HasError (string prefix, int number, string message)
{
foreach (var msg in messages) {
if (msg.IsError && msg.Prefix == prefix && msg.Number == number && msg.Message == message)
return true;
}
return false;
}
public void AssertWarningCount (int count, string message = "warnings")
{
AssertWarningCount (messages, count, message);
}
public static void AssertWarningCount (IEnumerable<ToolMessage> messages, int count, string message = "warnings")
{
if (count != GetWarningCount (messages))
Assert.Fail ($"{message}\nExpected: {count}\nBut was: { GetWarningCount (messages)}\nWarnings:\n\t{string.Join ("\n\t", messages.Where ((v) => v.IsWarning).Select ((v) => v.ToString ()))}");
}
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)
{
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)
{
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));
// Custom pattern syntax: escape parenthesis and brackets so that they're treated like normal characters.
var processedPattern = custom_pattern_syntax ? messagePattern.Replace ("(", "[(]").Replace (")", "[)]").Replace ("[]", "[[][]]") + "$" : messagePattern;
var matches = messages.Where ((msg) => Regex.IsMatch (msg.Message, processedPattern));
if (!matches.Any ()) {
var details = messages.Where ((msg) => msg.Prefix == prefix && msg.Number == number && !Regex.IsMatch (msg.Message, processedPattern)).Select ((msg) => string.Format ("\tThe message '{0}' did not match the pattern '{1}'.", msg.Message, messagePattern));
Assert.Fail (string.Format ("The error '{0}{1:0000}: {2}' was not found in the output:\n{3}", prefix, number, messagePattern, string.Join ("\n", details.ToArray ())));
}
AssertFilename (prefix, number, messagePattern, matches, filename, linenumber);
}
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)
{
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));
var matches = messages.Where ((msg) => msg.Message == message);
if (!matches.Any ()) {
var details = messages.
Where ((msg) => msg.Prefix == prefix && msg.Number == number && msg.Message != message).
Select ((msg) => string.Format ("\tMessage #{2} did not match:\n\t\tactual: '{0}'\n\t\texpected: '{1}'", msg.Message, message, messages.IndexOf (msg) + 1));
Assert.Fail (string.Format ("The error '{0}{1:0000}: {2}' was not found in the output:\n{3}", prefix, number, message, string.Join ("\n", details.ToArray ())));
}
AssertFilename (prefix, number, message, matches, filename, 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)
{
if (filename != null) {
var hasDirectory = filename.IndexOf (Path.DirectorySeparatorChar) > -1;
if (!matches.Any ((v) => {
if (hasDirectory) {
// Check the entire path
return filename == v.FileName;
} else {
// Don't compare the directory unless one was specified.
return filename == Path.GetFileName (v.FileName);
}
})) {
var details = matches.Select ((msg) => string.Format ("\tMessage #{2} did not contain expected filename:\n\t\tactual: '{0}'\n\t\texpected: '{1}'", hasDirectory ? msg.FileName : Path.GetFileName (msg.FileName), filename, messages.IndexOf (msg) + 1));
Assert.Fail (string.Format ($"The filename '{filename}' was not found in the output for the error {prefix}{number:X4}: {message}:\n{string.Join ("\n", details.ToArray ())}"));
}
}
if (linenumber != null) {
if (!matches.Any ((v) => linenumber.Value == v.LineNumber)) {
var details = matches.Select ((msg) => string.Format ("\tMessage #{2} did not contain expected line number:\n\t\tactual: '{0}'\n\t\texpected: '{1}'", msg.LineNumber, linenumber, messages.IndexOf (msg) + 1));
Assert.Fail (string.Format ($"The linenumber '{linenumber.Value}' was not found in the output for the error {prefix}{number:X4}: {message}:\n{string.Join ("\n", details.ToArray ())}"));
}
}
}
public void AssertWarningPattern (int number, string messagePattern)
{
AssertWarningPattern (MessagePrefix, number, messagePattern);
}
public void AssertWarningPattern (string prefix, int number, string messagePattern)
{
AssertWarningPattern (messages, prefix, number, messagePattern);
}
public static void AssertWarningPattern (IEnumerable<ToolMessage> messages, string prefix, int number, string messagePattern)
{
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));
if (messages.Any ((msg) => Regex.IsMatch (msg.Message, messagePattern)))
return;
var details = messages.Where ((msg) => msg.Prefix == prefix && msg.Number == number && !Regex.IsMatch (msg.Message, messagePattern)).Select ((msg) => string.Format ("\tThe message '{0}' did not match the pattern '{1}'.", msg.Message, messagePattern));
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)
{
AssertWarning (MessagePrefix, number, message, filename, linenumber);
}
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)
{
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));
var matches = messages.Where ((msg) => msg.Message == message);
if (!matches.Any ()) {
var details = messages.Where ((msg) => msg.Prefix == prefix && msg.Number == number && msg.Message != message).Select ((msg) => string.Format ("\tMessage #{2} did not match:\n\t\tactual: '{0}'\n\t\texpected: '{1}'", msg.Message, message, messages.IndexOf (msg) + 1));
Assert.Fail (string.Format ("The warning '{0}{1:0000}: {2}' was not found in the output:\n{3}", prefix, number, message, string.Join ("\n", details.ToArray ())));
}
AssertFilename (messages, prefix, number, message, matches, filename, linenumber);
}
public void AssertNoWarnings ()
{
var warnings = messages.Where ((v) => v.IsWarning);
if (!warnings.Any ())
return;
Assert.Fail ("No warnings expected, but got:\n{0}\t", string.Join ("\n\t", warnings.Select ((v) => v.Message).ToArray ()));
}
public void AssertNoMessage (int number)
{
var msgs = messages.Where ((v) => v.Number == number);
if (!msgs.Any ())
return;
Assert.Fail ("No messages with number {0} expected, but got:\n{1}\t", number, string.Join ("\n\t", msgs.Select ((v) => v.Message).ToArray ()));
}
public bool HasOutput (string line)
{
return OutputLines.Contains (line);
}
public bool HasOutputPattern (string linePattern)
{
foreach (var line in OutputLines) {
if (Regex.IsMatch (line, linePattern, RegexOptions.CultureInvariant))
return true;
}
return false;
}
public void AssertOutputPattern (string linePattern)
{
if (!HasOutputPattern (linePattern))
Assert.Fail (string.Format ("The output does not contain the line '{0}'", linePattern));
}
public void ForAllOutputLines (Action<string> action)
{
foreach (var line in OutputLines)
action (line);
}
protected abstract string ToolPath { get; }
protected abstract string MessagePrefix { get; }
protected virtual string MessageToolName { get { return null; } }
}
}

Просмотреть файл

@ -12,35 +12,85 @@ using Xamarin.Tests;
namespace Xamarin.MMP.Tests
{
internal class MessageTool : Tool {
public MessageTool ()
{
}
public MessageTool (string text)
{
Output.Append (text);
}
protected override string ToolPath => throw new NotImplementedException ();
protected override string MessagePrefix => "MM";
}
public class OutputText
{
public string BuildOutput { get; private set; }
public BuildResult BuildResult { get; private set; }
public string RunOutput { get; private set; }
public OutputText (string buildOutput, string runOutput)
public OutputText (BuildResult buildOutput, string runOutput)
{
BuildOutput = buildOutput;
BuildResult = buildOutput;
RunOutput = runOutput;
}
internal MessageTool Messages {
get {
return BuildResult.Messages;
}
}
}
public class BuildResult {
public readonly string BinLogPath;
string build_output;
public string BuildOutput {
get {
if (build_output == null)
build_output = string.Join ("\n", BuildOutputLines);
return build_output;
}
}
string [] build_output_lines;
public IList<string> BuildOutputLines {
get {
if (build_output_lines == null)
build_output_lines = BinLog.PrintToLines (BinLogPath).ToArray ();
return build_output_lines;
}
}
public BuildResult (string binLogPath)
{
BinLogPath = binLogPath;
}
public bool HasMessage (int code)
{
return Messages.Messages.Any (v => v.Number == code);
}
public bool HasMessage (int code, string message)
{
return Messages.Messages.Any (v => v.Number == code && v.Message == message);
}
MessageTool messages;
internal MessageTool Messages {
get {
if (messages == null) {
messages = new MessageTool ();
messages.Output.Append (BuildOutput);
messages.ParseMessages ();
messages.ParseBinLog (BinLogPath);
}
return messages;
}
}
internal class MessageTool : Tool
{
protected override string ToolPath => throw new NotImplementedException ();
protected override string MessagePrefix => "MM";
}
}
static class FrameworkBuilder
@ -214,41 +264,38 @@ namespace Xamarin.MMP.Tests
StringBuilder output = new StringBuilder ();
environment ??= new Dictionary<string, string> ();
environment ["MONO_PATH"] = null;
int compileResult = Xamarin.Bundler.Driver.RunCommand (exe, args, environment, output, suppressPrintOnErrors: shouldFail);
if (!shouldFail && compileResult != 0 && Xamarin.Bundler.Driver.Verbosity < 1) {
Console.WriteLine ($"Execution failed; exit code: {compileResult}");
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 ($"{exe} {StringUtils.FormatArguments (args)}");
Console.WriteLine (output);
}
Func<string> getInfo = () => getAdditionalFailInfo != null ? getAdditionalFailInfo () : "";
bool passed = shouldFail ? compileResult != 0 : compileResult == 0;
if (!passed) {
string outputLine = PrintRedirectIfLong ($"{exe} {StringUtils.FormatArguments (args)} Output: {output} {getInfo ()}");
Assert.Fail ($@"{stepName} {(shouldFail ? "passed" : "failed")} unexpectedly: {outputLine}");
}
if (!passed)
Assert.Fail ($@"{stepName} {(shouldFail ? "passed" : "failed")} unexpectedly. Exit code: {compileResult}.");
return output.ToString ();
}
public static string PrintRedirectIfLong (string outputLine)
{
if (outputLine.Length > 5000) {
Console.WriteLine (outputLine);
outputLine = "(Additional info redirected to console)";
}
return outputLine;
}
// In most cases we generate projects in tmp and this is not needed. But nuget and test projects can make that hard
public static void CleanUnifiedProject (string csprojTarget)
{
RunAndAssert (Configuration.XIBuildPath, new [] { "--", csprojTarget, "/t:clean" }, "Clean", environment: Configuration.GetBuildEnvironment (ApplePlatform.MacOSX));
}
public static string 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> ();
buildArgs.Add ("/verbosity:diagnostic");
var binlog = Path.Combine (Path.GetDirectoryName (csprojTarget), $"log-{DateTime.Now:yyyyMMdd_HHmmss}.binlog");
buildArgs.Add ($"/bl:{binlog}");
Console.WriteLine ($"Binlog: {binlog}");
// Restore any package references
buildArgs.Add ("/r");
@ -271,7 +318,9 @@ namespace Xamarin.MMP.Tests
};
buildArgs.Insert (0, "--");
return RunAndAssert (Configuration.XIBuildPath, buildArgs, "Compile", shouldFail, getBuildProjectErrorInfo, environment);
RunAndAssert (Configuration.XIBuildPath, buildArgs, "Compile", shouldFail, getBuildProjectErrorInfo, environment);
return new BuildResult (binlog);
}
static string ProjectTextReplacement (UnifiedTestConfig config, string text)
@ -410,7 +459,7 @@ namespace Xamarin.MMP.Tests
return GenerateEXEProject (config);
}
public static string 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);
@ -425,7 +474,7 @@ namespace Xamarin.MMP.Tests
{
AddGUIDTestCode (config);
string buildOutput = GenerateAndBuildUnifiedExecutable (config, shouldFail, environment);
var buildOutput = GenerateAndBuildUnifiedExecutable (config, shouldFail, environment);
if (shouldFail)
return new OutputText (buildOutput, "");
@ -451,7 +500,7 @@ namespace Xamarin.MMP.Tests
config.ProjectName = $"{projectName}.csproj";
string csprojTarget = GenerateSystemMonoEXEProject (config);
string buildOutput = BuildProject (csprojTarget, shouldFail: shouldFail, release: config.Release);
var buildOutput = BuildProject (csprojTarget, shouldFail: shouldFail, release: config.Release);
if (shouldFail)
return new OutputText (buildOutput, "");
@ -492,7 +541,7 @@ namespace Xamarin.MMP.Tests
public static void CopyDirectory (string src, string target)
{
Xamarin.Bundler.Driver.RunCommand ("/bin/cp", new [] { "-r", src, target });
Assert.AreEqual (0, ExecutionHelper.Execute ("/bin/cp", new [] { "-r", src, target }));
}
public static string CopyFileWithSubstitutions (string src, string target, Func<string, string > replacementAction)

Просмотреть файл

@ -33,6 +33,7 @@
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit.ConsoleRunner" Version="3.11.1" />
<PackageReference Include="Mono.Cecil" Version="0.11.1" />
<PackageReference Include="MSBuild.StructuredLogger" Version="2.1.176" />
</ItemGroup>
<ItemGroup>
<Compile Include="ErrorTests.cs" />
@ -55,6 +56,12 @@
<Compile Include="..\common\Profile.cs">
<Link>Profile.cs</Link>
</Compile>
<Compile Include="..\common\Tool.cs">
<Link>Tool.cs</Link>
</Compile>
<Compile Include="..\common\BinLog.cs">
<Link>BinLog.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="tests\is-direct-binding.cs" />

Просмотреть файл

@ -11,7 +11,7 @@
<RootNamespace>Xamarin.MMP.Tests</RootNamespace>
<AssemblyName>mmptest</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<LangVersion>latest</LangVersion>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
@ -39,6 +39,9 @@
<HintPath>..\..\_mac-build\Library\Frameworks\Xamarin.Mac.framework\Versions\git\lib\mmp\mmp.exe</HintPath>
</Reference>
<PackageReference Include="Mono.Cecil" Version="0.11.1" />
<PackageReference Include="MSBuild.StructuredLogger">
<Version>2.1.176</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
@ -114,6 +117,12 @@
<Link>Errors.Designer.cs</Link>
</Compile>
<Compile Include="src\NativeExtensionEmbedding.cs" />
<Compile Include="..\common\BinLog.cs">
<Link>BinLog.cs</Link>
</Compile>
<Compile Include="..\common\Tool.cs">
<Link>src\Tool.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="Info.plist" />

Просмотреть файл

@ -14,11 +14,11 @@ namespace Xamarin.MMP.Tests
[TestFixture]
public class AOTTests
{
void ValidateAOTStatus (string tmpDir, Func<FileInfo, bool> shouldAOT, string buildResults)
void ValidateAOTStatus (string tmpDir, Func<FileInfo, bool> shouldAOT)
{
foreach (var file in GetOutputDirInfo (tmpDir).EnumerateFiles ()) {
bool shouldBeAOT = shouldAOT (file);
Assert.AreEqual (shouldBeAOT, File.Exists (file.FullName + ".dylib"), "{0} should {1}be AOT.\n{2}", file.FullName, shouldBeAOT ? "" : "not ", buildResults);
Assert.AreEqual (shouldBeAOT, File.Exists (file.FullName + ".dylib"), "{0} should {1}be AOT.", file.FullName, shouldBeAOT ? "" : "not ");
}
}
@ -59,9 +59,8 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) {
CSProjConfig = GetTestConfig (TestType.Base, useProjectTags)
};
string buildResults = TI.TestUnifiedExecutable (test).BuildOutput;
ValidateAOTStatus (tmpDir, f => ShouldBaseFilesBeAOT (f), buildResults);
TI.TestUnifiedExecutable (test);
ValidateAOTStatus (tmpDir, f => ShouldBaseFilesBeAOT (f));
});
}
@ -73,15 +72,14 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) {
CSProjConfig = GetTestConfig (TestType.Hybrid, useProjectTags)
};
string buildResults = TI.TestUnifiedExecutable (test).BuildOutput;
TI.TestUnifiedExecutable (test);
foreach (var file in GetOutputDirInfo (tmpDir).EnumerateFiles ()) {
if (IsFileManagedCode (file))
TI.RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/mono-cil-strip", new [] { file.ToString () }, "Manually strip IL");
}
ValidateAOTStatus (tmpDir, IsFileManagedCode, buildResults);
ValidateAOTStatus (tmpDir, IsFileManagedCode);
TI.RunEXEAndVerifyGUID (tmpDir, test.guid, GetOutputAppPath (tmpDir));
});
@ -95,11 +93,11 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) {
CSProjConfig = GetTestConfig (TestType.Hybrid, useProjectTags)
};
string buildResults = TI.TestUnifiedExecutable (test).BuildOutput;
TI.TestUnifiedExecutable (test);
TI.RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/mono-cil-strip", new [] { Path.Combine (GetOutputBundlePath (tmpDir), "UnifiedExample.exe") }, "Manually strip IL");
ValidateAOTStatus (tmpDir, IsFileManagedCode, buildResults);
ValidateAOTStatus (tmpDir, IsFileManagedCode);
TI.RunEXEAndVerifyGUID (tmpDir, test.guid, GetOutputAppPath (tmpDir));
});

Просмотреть файл

@ -36,7 +36,7 @@ namespace Xamarin.MMP.Tests
var projects = BindingProjectTests.GenerateTestProject (type, tmpDir);
BindingProjectTests.SetNoEmbedding (projects.Item1);
string appBuildLog = BindingProjectTests.SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference, setupDefaultNativeReference: true).Item2;
BindingProjectTests.SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference, setupDefaultNativeReference: true);
AssertNoResourceWithName (tmpDir, projects.Item1.ProjectName, "SimpleClassDylib.dylib");
AssertFileInBundle (tmpDir, type, "MonoBundle/SimpleClassDylib.dylib");
@ -54,7 +54,7 @@ namespace Xamarin.MMP.Tests
BindingProjectTests.SetNoEmbedding (projects.Item1);
projects.Item1.ItemGroup = NativeReferenceTests.CreateSingleNativeRef (frameworkPath, "Framework");
string appBuildLog = BindingProjectTests.SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference, false).Item2;
BindingProjectTests.SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference, false);
AssertNoResourceWithName (tmpDir, projects.Item1.ProjectName, "Foo");
AssertFileInBundle (tmpDir, type, "Frameworks/Foo.framework/Foo", assertIsSymLink: true);
@ -70,8 +70,8 @@ namespace Xamarin.MMP.Tests
projects.Item1.LinkWithName = "SimpleClassDylib.dylib";
string libBuildLog = BindingProjectTests.SetupAndBuildBindingProject (projects.Item1, false, shouldFail: true);
Assert.True (libBuildLog.Contains ("Can't create a binding resource package unless there are native references in the binding project."), $"Did not fail as expected: {TI.PrintRedirectIfLong (libBuildLog)}");
var buildResult = BindingProjectTests.SetupAndBuildBindingProject (projects.Item1, false, shouldFail: true);
buildResult.Messages.AssertError (7068, "Can't create a binding resource package unless there are native references in the binding project.\n ");
});
}
@ -148,7 +148,7 @@ namespace Xamarin.MMP.Tests
var projects = BindingProjectTests.GenerateTestProject (BindingProjectType.Modern, tmpDir);
BindingProjectTests.SetNoEmbedding (projects.Item1);
string libBuildLog = BindingProjectTests.SetupAndBuildBindingProject (projects.Item1, true);
BindingProjectTests.SetupAndBuildBindingProject (projects.Item1, true);
TI.CleanUnifiedProject (Path.Combine (tmpDir, projects.Item1.ProjectName));
Assert.False (Directory.Exists (Path.Combine (tmpDir, "bin/Debug/MobileBinding.resources")), "Resource bundle was not cleaned up");

Просмотреть файл

@ -22,9 +22,9 @@ namespace Xamarin.MMP.Tests
{
internal static string RemoveCSProj (string s) => s.Remove (s.IndexOf (".csproj", StringComparison.InvariantCulture));
internal static Tuple<string, string> SetupAndBuildLinkedTestProjects (TI.UnifiedTestConfig binding, TI.UnifiedTestConfig project, string tmpDir, bool useProjectReference, bool setupDefaultNativeReference)
internal static (BuildResult BindingBuildResult, OutputText AppTestResult) SetupAndBuildLinkedTestProjects (TI.UnifiedTestConfig binding, TI.UnifiedTestConfig project, string tmpDir, bool useProjectReference, bool setupDefaultNativeReference)
{
string bindingBuildLog = SetupAndBuildBindingProject (binding, setupDefaultNativeReference);
var bindingBuildLog = SetupAndBuildBindingProject (binding, setupDefaultNativeReference);
string bindingName = RemoveCSProj (binding.ProjectName);
@ -35,12 +35,13 @@ namespace Xamarin.MMP.Tests
project.TestCode = "System.Console.WriteLine (typeof (ExampleBinding.UnifiedWithDepNativeRefLibTestClass));";
string appBuildLog = TI.TestUnifiedExecutable (project).BuildOutput;
var appBuildLog = TI.TestUnifiedExecutable (project);
return new Tuple<string, string> (bindingBuildLog, appBuildLog);
(BuildResult BindingBuildResult, OutputText AppTestResult) rv = (bindingBuildLog, appBuildLog);
return rv;
}
internal static string SetupAndBuildBindingProject (TI.UnifiedTestConfig binding, bool setupDefaultNativeReference, bool shouldFail = false)
internal static BuildResult SetupAndBuildBindingProject (TI.UnifiedTestConfig binding, bool setupDefaultNativeReference, bool shouldFail = false)
{
if (setupDefaultNativeReference)
binding.ItemGroup += NativeReferenceTests.CreateSingleNativeRef (Path.GetFullPath (NativeReferenceTests.SimpleDylibPath), "Dynamic");
@ -130,9 +131,9 @@ namespace Xamarin.MMP.Tests
var logs = SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference: false, setupDefaultNativeReference: noEmbedding);
Assert.True (logs.Item1.Contains ("csc"), "Bindings project must use csc:\n" + logs.Item1);
Assert.True (logs.BindingBuildResult.BuildOutput.Contains ("csc"), "Bindings project must use csc:\n" + logs.Item1);
var bgenInvocation = logs.Item1.SplitLines ().First (x => x.Contains ("bin/bgen"));
var bgenInvocation = logs.BindingBuildResult.BuildOutputLines.First (x => x.Contains ("bin/bgen"));
var bgenParts = bgenInvocation.Split (new char[] { ' ' });
var mscorlib = bgenParts.First (x => x.Contains ("mscorlib.dll"));
var system = bgenParts.First (x => x.Contains ("System.dll"));
@ -153,9 +154,9 @@ namespace Xamarin.MMP.Tests
throw new NotImplementedException ();
}
Assert.False (logs.Item1.Contains ("CS1685"), "Binding should not contains CS1685 multiple definition warning:\n" + logs.Item1);
Assert.False (logs.BindingBuildResult.BuildOutput.Contains ("CS1685"), "Binding should not contains CS1685 multiple definition warning.");
Assert.False (logs.Item1.Contains ("MSB9004"), "Binding should not contains MSB9004 warning:\n" + logs.Item1);
Assert.False (logs.BindingBuildResult.BuildOutput.Contains ("MSB9004"), "Binding should not contains MSB9004 warning");
string bindingName = RemoveCSProj (projects.Item1.ProjectName);
string appName = RemoveCSProj (projects.Item2.ProjectName);

Просмотреть файл

@ -13,8 +13,15 @@ namespace Xamarin.MMP.Tests
static Func<string, bool> LipoStripConditional = s => s.Contains ("lipo") && s.Contains ("-thin");
static Func<string, bool> LipoStripSkipPosixAndMonoNativeConditional = s => LipoStripConditional (s) && !s.Contains ("libMonoPosixHelper.dylib") && !s.Contains ("libmono-native.dylib");
static Func<string, bool> DidAnyLipoStrip = output => output.SplitLines ().Any (LipoStripConditional);
static Func<string, bool> DidAnyLipoStripSkipPosixAndMonoNative = output => output.SplitLines ().Any (LipoStripSkipPosixAndMonoNativeConditional);
static bool DidAnyLipoStripSkipPosixAndMonoNative (BuildResult buildResult)
{
return buildResult.BuildOutputLines.Any (LipoStripSkipPosixAndMonoNativeConditional);
}
static bool DidAnyLipoStrip (BuildResult buildResult)
{
return buildResult.BuildOutputLines.Any (LipoStripConditional);
}
static TI.UnifiedTestConfig CreateStripTestConfig (bool? strip, string tmpDir, string additionalMMPArgs = "")
{
@ -43,16 +50,16 @@ namespace Xamarin.MMP.Tests
void StripTestCore (TI.UnifiedTestConfig test, bool debugStrips, bool releaseStrips, string libPath, bool shouldWarn)
{
string buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.AreEqual (debugStrips, DidAnyLipoStrip (buildOutput), "Debug lipo usage did not match expectations");
var testResult = TI.TestUnifiedExecutable (test);
Assert.AreEqual (debugStrips, DidAnyLipoStrip (testResult.BuildResult), "Debug lipo usage did not match expectations");
AssertStrip (Path.Combine (test.TmpDir, "bin/Debug/UnifiedExample.app/", libPath), shouldStrip: debugStrips);
Assert.AreEqual (shouldWarn && debugStrips, buildOutput.Contains ("MM2108"), "Debug warning did not match expectations");
Assert.AreEqual (shouldWarn && debugStrips, testResult.BuildResult.HasMessage (2108), "Debug warning did not match expectations");
test.Release = true;
buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.AreEqual (releaseStrips, DidAnyLipoStrip (buildOutput), "Release lipo usage did not match expectations");
testResult = TI.TestUnifiedExecutable (test);
Assert.AreEqual (releaseStrips, DidAnyLipoStrip (testResult.BuildResult), "Release lipo usage did not match expectations");
AssertStrip (Path.Combine (test.TmpDir, "bin/Release/UnifiedExample.app/", libPath), shouldStrip: releaseStrips);
Assert.AreEqual (shouldWarn && releaseStrips, buildOutput.Contains ("MM2108"), "Release warning did not match expectations");
Assert.AreEqual (shouldWarn && releaseStrips, testResult.BuildResult.HasMessage (2108), "Release warning did not match expectations");
}
[TestCase (null, false, true)]
@ -93,36 +100,41 @@ namespace Xamarin.MMP.Tests
[TestCase (false, false)]
public void ExplictStripOption_ThirdPartyLibrary_AndWarnsIfSo (bool? strip, bool shouldStrip)
{
MMPTests.RunMMPTest (tmpDir =>
{
MMPTests.RunMMPTest (tmpDir => {
string originalLocation = Path.Combine (Configuration.SourceRoot, "tests", "test-libraries", "libtest-fat.macos.dylib");
string newLibraryLocation = Path.Combine (tmpDir, "libTest.dylib");
string newLibraryLocation = Path.Combine (tmpDir, "libTest.dylib");
File.Copy (originalLocation, newLibraryLocation);
TI.UnifiedTestConfig test = CreateStripTestConfig (strip, tmpDir, $" --native-reference=\"{newLibraryLocation}\"");
test.Release = true;
var testOutput = TI.TestUnifiedExecutable (test);
string buildOutput = testOutput.BuildOutput;
Assert.AreEqual (shouldStrip, DidAnyLipoStrip (buildOutput), "lipo usage did not match expectations");
var testResult = TI.TestUnifiedExecutable (test);
var bundleDylib = Path.Combine (test.BundlePath, "Contents", "MonoBundle", "libTest.dylib");
Assert.That (bundleDylib, Does.Exist, "libTest.dylib presence in app bundle");
var architectures = MachO.GetArchitectures (bundleDylib);
if (shouldStrip) {
testOutput.Messages.AssertWarning (2108, "libTest.dylib was stripped of architectures except x86_64 to comply with App Store restrictions. This could break existing codesigning signatures. Consider stripping the library with lipo or disabling with --optimize=-trim-architectures");
Assert.AreEqual (1, architectures.Count, "libTest.dylib should only contain 1 architecture");
Assert.AreEqual (Abi.x86_64, architectures [0], "libTest.dylib should be x86_64");
testResult.Messages.AssertWarning (2108, "libTest.dylib was stripped of architectures except x86_64 to comply with App Store restrictions. This could break existing codesigning signatures. Consider stripping the library with lipo or disabling with --optimize=-trim-architectures");
} else {
testOutput.Messages.AssertWarningCount (0);
Assert.AreEqual (2, architectures.Count, "libTest.dylib should contain 2+ architectures");
Assert.That (architectures, Is.EquivalentTo (new Abi [] { Abi.i386, Abi.x86_64 }), "libTest.dylib should be x86_64 + i386");
testResult.Messages.AssertWarningCount (1); // dylib ([...]/xamarin-macios/tests/mmptest/bin/Debug/tmp-test-dir/Xamarin.MMP.Tests.MMPTests.RunMMPTest47/bin/Release/UnifiedExample.app/Contents/MonoBundle/libTest.dylib) was built for newer macOS version (10.11) than being linked (10.9)
}
});
}
void AssertNoLipoOrWarning (string buildOutput, string context)
void AssertNoLipoOrWarning (BuildResult buildOutput, string context)
{
Assert.False (DidAnyLipoStrip (buildOutput), "lipo incorrectly run in context: " + context);
Assert.False (buildOutput.Contains ("MM2108"), "MM2108 incorrectly given in in context: " + context);
Assert.False (buildOutput.HasMessage (2108), "MM2108 incorrectly given in in context: " + context);
}
void AssertLipoOnlyMonoPosixAndMonoNative (string buildOutput, string context)
void AssertLipoOnlyMonoPosixAndMonoNative (BuildResult buildOutput, string context)
{
Assert.False (DidAnyLipoStripSkipPosixAndMonoNative (buildOutput), "lipo incorrectly run in context outside of libMonoPosixHelper/libmono-native: " + context);
Assert.False (buildOutput.Contains ("MM2108"), "MM2108 incorrectly given in in context: " + context);
Assert.False (buildOutput.HasMessage (2108), "MM2108 incorrectly given in in context: " + context);
}
[TestCase (false)]
@ -136,14 +148,15 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = CreateStripTestConfig (null, tmpDir, $" --native-reference=\"{frameworkPath}\"");
// Should always skip lipo/warning in Debug
string buildOutput = TI.TestUnifiedExecutable(test).BuildOutput;
AssertNoLipoOrWarning (buildOutput, "Debug");
var testResult = TI.TestUnifiedExecutable (test);
AssertNoLipoOrWarning (testResult.BuildResult, "Debug");
// Should always lipo/warn in Release
test.Release = true;
buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.True (DidAnyLipoStrip (buildOutput), $"lipo did not run in release");
Assert.True (buildOutput.Contains ("MM2108"), $"MM2108 not given in release");
testResult = TI.TestUnifiedExecutable (test);
Assert.True (DidAnyLipoStrip (testResult.BuildResult), $"lipo did not run in release");
testResult.BuildResult.Messages.AssertError (2108, $"{frameworkPath} was stripped of architectures except x86_64 to comply with App Store restrictions. This could break existing codesigning signatures. Consider stripping the library with lipo or disabling with --optimize=-trim-architectures");
// Assert.True (testResult.Contains ("MM2108"), $"MM2108 not given in release");
});
}
@ -157,12 +170,12 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = CreateStripTestConfig (null, tmpDir, $" --native-reference=\"{frameworkPath}\"");
string buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
AssertNoLipoOrWarning (buildOutput, "Debug");
var testResult = TI.TestUnifiedExecutable (test);
AssertNoLipoOrWarning (testResult.BuildResult, "Debug");
test.Release = true;
buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
AssertLipoOnlyMonoPosixAndMonoNative (buildOutput, "Release"); // libMonoPosixHelper.dylib and libmono-native.dylib will lipo in Release
testResult = TI.TestUnifiedExecutable (test);
AssertLipoOnlyMonoPosixAndMonoNative (testResult.BuildResult, "Release"); // libMonoPosixHelper.dylib and libmono-native.dylib will lipo in Release
});
}
}

Просмотреть файл

@ -78,21 +78,18 @@ namespace Xamarin.MMP.Tests
CSProjConfig = $"<MonoBundlingExtraArgs>--dynamic-symbol-mode={mode}</MonoBundlingExtraArgs>\n",
};
var output = TI.TestUnifiedExecutable (config);
string build_output;
var build_output = output.BuildResult.BuildOutput;
switch (mode) {
case "linker":
case "default":
build_output = output.BuildOutput;
Assert.That (build_output, Does.Contain ("-u "), "reference.m");
Assert.That (build_output, Does.Not.Contain ("reference.m"), "reference.m");
break;
case "code":
build_output = output.BuildOutput;
Assert.That (build_output, Does.Not.Contain ("-u "), "reference.m");
Assert.That (build_output, Does.Contain ("reference.m"), "reference.m");
break;
case "ignore":
build_output = output.BuildOutput;
Assert.That (build_output, Does.Not.Contain ("-u "), "reference.m");
Assert.That (build_output, Does.Not.Contain ("reference.m"), "reference.m");
break;
@ -117,8 +114,8 @@ namespace Xamarin.MMP.Tests
TestCode = "System.Console.WriteLine (typeof (MixedClassLibrary.Class1));",
};
var buildOutput = TI.TestUnifiedExecutable (test, shouldFail: builds_successfully).BuildOutput;
Assert.True (buildOutput.Contains ("2014") == builds_successfully, $"Building with {linker} did not give 2014 status {builds_successfully} as expected.\n\n{buildOutput}");
var buildOutput = TI.TestUnifiedExecutable (test, shouldFail: builds_successfully).BuildResult;
Assert.True (buildOutput.HasMessage (2014) == builds_successfully, $"Building with {linker} did not give 2014 status {builds_successfully} as expected.");
});
}
@ -127,8 +124,8 @@ namespace Xamarin.MMP.Tests
{
MMPTests.RunMMPTest (tmpDir => {
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "<MonoBundlingExtraArgs>-v -v --linkplatform</MonoBundlingExtraArgs>" };
string buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.IsTrue (buildOutput.Contains ("Selected Linking: 'Platform'"), $"Build Output did not contain expected selected linking line: {buildOutput}");
var testResult = TI.TestUnifiedExecutable (test);
Assert.IsTrue (testResult.BuildResult.BuildOutput.Contains ("Selected Linking: 'Platform'"), $"Build Output did not contain expected selected linking line: {testResult}");
});
}
@ -137,8 +134,8 @@ namespace Xamarin.MMP.Tests
{
MMPTests.RunMMPTest (tmpDir => {
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "<MonoBundlingExtraArgs>--registrar:partial --linkplatform</MonoBundlingExtraArgs>" };
string buildOutput = TI.TestUnifiedExecutable (test, shouldFail: true).BuildOutput;
Assert.True (buildOutput.Contains ("2110"), $"Building did not give the expected 2110 error.\n\n{buildOutput}");
var testResult = TI.TestUnifiedExecutable (test, shouldFail: true);
testResult.BuildResult.Messages.AssertError (2110, "Xamarin.Mac 'Partial Static' registrar does not support linking. Disable linking or use another registrar mode.");
});
}
}

Просмотреть файл

@ -24,8 +24,7 @@ namespace Xamarin.MMP.Tests
public static string [] GetUnifiedProjectClangInvocation (string tmpDir, string projectConfig = "")
{
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = projectConfig };
string buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
string [] splitBuildOutput = TI.TestUnifiedExecutable (test).BuildOutput.Split (new string[] { Environment.NewLine }, StringSplitOptions.None);
var splitBuildOutput = TI.TestUnifiedExecutable (test).BuildResult.BuildOutputLines;
string clangInvocation = splitBuildOutput.Single (x => x.Contains ("usr/bin/clang") && x.Contains ("mmacosx-version-min"));
return clangInvocation.Split (new string[] { " " }, StringSplitOptions.None);
}
@ -87,8 +86,8 @@ namespace Xamarin.MMP.Tests
{
RunMMPTest (tmpDir => {
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "<MonoBundlingExtraArgs>--new-refcount=false</MonoBundlingExtraArgs>" };
string buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.IsTrue (buildOutput.Contains ("Disabling the new refcount logic is deprecated"), "Mobile_NewRefCount_Warns did not warn as expected:\n\n", buildOutput);
var testResult = TI.TestUnifiedExecutable (test);
testResult.Messages.AssertWarning (80, "Disabling the new refcount logic is deprecated.");
});
}
@ -136,7 +135,7 @@ namespace Xamarin.MMP.Tests
test.XM45 = full;
var rv = TI.TestUnifiedExecutable (test);
Console.WriteLine (rv.BuildOutput);
Console.WriteLine (rv.BuildResult);
if (full && release) {
rv.Messages.AssertWarning (5220, "Skipping framework 'QTKit'. It is prohibited (rejected) by the Mac App Store");
// We get the MM5220 twice in the output, once from mmp and once from msbuild repeating what mmp said, so we can't assert that there's exactly 1 warning.
@ -262,9 +261,8 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) {
CSProjConfig = string.Format ("<MonoBundlingExtraArgs>--machine-config={0}</MonoBundlingExtraArgs>", invalidConfigPath)
};
string buildOutput = TI.TestUnifiedExecutable (test, shouldFail : true).BuildOutput;
Assert.IsTrue (buildOutput.Contains ("can not be found"), "Unified_InvalidMachineConfigInBundle_ThrowsError did not error as expected (1):\n\n", buildOutput);
Assert.IsTrue (buildOutput.Contains ("97"), "Unified_InvalidMachineConfigInBundle_ThrowsError did not error as expected (2):\n\n", buildOutput);
var testResult = TI.TestUnifiedExecutable (test, shouldFail : true);
testResult.Messages.AssertError (97, $"machine.config file '{invalidConfigPath}' can not be found.");
});
}
@ -339,8 +337,9 @@ namespace Xamarin.MMP.Tests
TI.GenerateUnifiedExecutableProject (test);
// And try again.
// If we fail, we'll likley fail with "did not generate an exe" before returning but let's check anyway
string secondBuildOutput = TI.BuildProject (Path.Combine (tmpDir, TI.GetUnifiedExecutableProjectName (test)));
// If we fail, we'll likely fail with "did not generate an exe" before returning but let's check anyway
var secondBuildResult = TI.BuildProject (Path.Combine (tmpDir, TI.GetUnifiedExecutableProjectName (test)));
var secondBuildOutput = secondBuildResult.BuildOutput;
Assert.IsTrue (!secondBuildOutput.Contains ("Skipping target \"_CompileToNative"), "Did not skip");
Assert.IsTrue (secondBuildOutput.Contains ("Building target \"_CompileToNative\" completely"), "Did need to build");
}
@ -397,8 +396,8 @@ namespace Xamarin.MMP.Tests
RunMMPTest (tmpDir => {
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { XM45 = xm45 };
test.Release = true;
string buildResults = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.IsFalse (buildResults.Contains ("Xamarin.Mac.registrar"), "Release build should not use partial static registrar");
var testResults = TI.TestUnifiedExecutable (test);
Assert.IsFalse (testResults.BuildResult.BuildOutput.Contains ("Xamarin.Mac.registrar"), "Release build should not use partial static registrar");
});
}
@ -410,8 +409,8 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { XM45 = xm45 };
test.Release = false;
test.CSProjConfig = "<DebugSymbols>true</DebugSymbols>";
var buildResults = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.IsTrue (buildResults.Contains ("Xamarin.Mac.registrar"), "Debug build should use partial static registrar");
var testResults = TI.TestUnifiedExecutable (test);
Assert.IsTrue (testResults.BuildResult.BuildOutput.Contains ("Xamarin.Mac.registrar"), "Debug build should use partial static registrar");
});
}
@ -423,8 +422,8 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { XM45 = xm45 };
test.Release = false;
test.CSProjConfig = "<DebugSymbols>true</DebugSymbols><MonoBundlingExtraArgs>--registrar=dynamic</MonoBundlingExtraArgs><XamMacArch>x86_64</XamMacArch>";
var buildResults = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.IsFalse (buildResults.Contains ("Xamarin.Mac.registrar"), "registrar=dynamic build should not use partial static registrar");
var testResult = TI.TestUnifiedExecutable (test);
Assert.IsFalse (testResult.BuildResult.BuildOutput.Contains ("Xamarin.Mac.registrar"), "registrar=dynamic build should not use partial static registrar");
});
}
@ -436,8 +435,8 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { XM45 = xm45 };
test.Release = false;
test.CSProjConfig = "<DebugSymbols>true</DebugSymbols><MonoBundlingExtraArgs>--registrar=partial</MonoBundlingExtraArgs><XamMacArch>x86_64</XamMacArch>";
var buildResults = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.IsTrue (buildResults.Contains ("Xamarin.Mac.registrar"), "registrar=partial build should use partial static registrar");
var testResults = TI.TestUnifiedExecutable (test);
Assert.IsTrue (testResults.BuildResult.BuildOutput.Contains ("Xamarin.Mac.registrar"), "registrar=partial build should use partial static registrar");
});
}
//https://testrail.xamarin.com/index.php?/cases/view/234141&group_by=cases:section_id&group_order=asc&group_id=51097
@ -447,7 +446,7 @@ namespace Xamarin.MMP.Tests
RunMMPTest (tmpDir => {
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { XM45 = true };
var output = TI.TestUnifiedExecutable (test);
Assert.That (output.BuildOutput, Contains.Substring ("Selected target framework: Xamarin.Mac,Version=v4.5,Profile=Full; API: Unified"));
Assert.That (output.BuildResult.BuildOutput, Contains.Substring ("Selected target framework: Xamarin.Mac,Version=v4.5,Profile=Full; API: Unified"));
});
}
@ -659,7 +658,7 @@ namespace Xamarin.MMP.Tests
string project = TI.GenerateUnifiedExecutableProject (test);
TI.NugetRestore (project);
var rv = new OutputText (TI.BuildProject (project), string.Empty);
Console.WriteLine (rv.BuildOutput);
Console.WriteLine (rv.BuildResult);
if (xm45) {
var referenced_version = tfv == null ? "2.0.0.0" : "4.0.0.0";
rv.Messages.AssertWarningPattern (176, $"The assembly 'System.Web, Version={referenced_version}, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' was resolved from the system's GAC: /Library/Frameworks/Mono.framework/Versions/.*/lib/mono/gac/System.Web/4.0.0.0__b03f5f7f11d50a3a/System.Web.dll. This could potentially be a problem in the future; to avoid such problems, please make sure to not use assemblies only available in the system's GAC.");
@ -697,15 +696,18 @@ namespace Xamarin.MMP.Tests
string project = TI.GenerateUnifiedExecutableProject (test);
string buildOutput = TI.BuildProject (project);
var buildResult = TI.BuildProject (project);
var buildOutput = buildResult.BuildOutput;
Assert.True (buildOutput.Contains (actool), $"Initial build should run actool");
buildOutput = TI.BuildProject (project);
buildResult = TI.BuildProject (project);
buildOutput = buildResult.BuildOutput;
Assert.False (buildOutput.Contains (actool), $"Second build should not run actool");
TI.RunAndAssert ("touch", new [] { Path.Combine (tmpDir, "Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png") }, "touch icon");
buildOutput = TI.BuildProject (project);
buildResult = TI.BuildProject (project);
buildOutput = buildResult.BuildOutput;
Assert.True (buildOutput.Contains (actool), $"Build after touching icon must run actool");
});
}
@ -722,7 +724,7 @@ namespace Xamarin.MMP.Tests
CSProjConfig = "<EnableCodeSigning>true</EnableCodeSigning>"
};
Func<OutputText, string> findCodesign = o => o.BuildOutput.SplitLines ().Last (x => x.Contains ("Tool /usr/bin/codesign execution started with arguments"));
Func<OutputText, string> findCodesign = o => o.BuildResult.BuildOutputLines.Last (x => x.Contains ("Tool /usr/bin/codesign execution started with arguments"));
var baseOutput = TI.TestUnifiedExecutable (test);
string baseCodesign = findCodesign (baseOutput);
@ -764,7 +766,7 @@ namespace Xamarin.MMP.Tests
CSProjConfig = "<EnableCodeSigning>true</EnableCodeSigning>"
};
TI.TestUnifiedExecutable (test);
var output = TI.BuildProject (Path.Combine (tmpDir, full ? "XM45Example.csproj" : "UnifiedExample.csproj"), release: true, extraArgs: new [] { "/p:ArchiveOnBuild=true" });
TI.BuildProject (Path.Combine (tmpDir, full ? "XM45Example.csproj" : "UnifiedExample.csproj"), release: true, extraArgs: new [] { "/p:ArchiveOnBuild=true" });
});
// TODO: Add something to validate the archive is loadable by Xcode
@ -778,7 +780,7 @@ namespace Xamarin.MMP.Tests
CSProjConfig = "<MonoBundlingExtraArgs>-link_flags=-fobjc-arc</MonoBundlingExtraArgs>"
};
TI.TestUnifiedExecutable (test);
var output = TI.BuildProject (Path.Combine (tmpDir, "UnifiedExample.csproj"));
TI.BuildProject (Path.Combine (tmpDir, "UnifiedExample.csproj"));
});
}

Просмотреть файл

@ -55,14 +55,14 @@ namespace Xamarin.MMP.Tests
return filePath;
}
void NativeReferenceTestCore (string tmpDir, TI.UnifiedTestConfig test, string testName, string libraryName, bool buildShouldBeSuccessful, bool libraryShouldNotBeCopied = false, Func<string, bool> processBuildOutput = null)
void NativeReferenceTestCore (string tmpDir, TI.UnifiedTestConfig test, string testName, string libraryName, bool buildShouldBeSuccessful, bool libraryShouldNotBeCopied = false, Func<BuildResult, bool> processBuildOutput = null)
{
// Mobile
test.XM45 = false;
string buildResults = TI.TestUnifiedExecutable (test, false).BuildOutput;
Assert.IsTrue (!buildShouldBeSuccessful || !buildResults.Contains ("MM2006"), string.Format ("{0} - Mobile had MM2006 state {1} not match expected\n{2}", testName, buildShouldBeSuccessful, buildResults));
var testResult = TI.TestUnifiedExecutable (test, false);
Assert.IsTrue (!buildShouldBeSuccessful || !testResult.BuildResult.HasMessage (2006), string.Format ("{0} - Mobile had MM2006 state {1} not match expected\n{2}", testName, buildShouldBeSuccessful, testResult));
if (processBuildOutput != null)
Assert.IsTrue (processBuildOutput (buildResults), string.Format ("{0} - Mobile - We did not see our expected item in the build output: {1}", testName, libraryName));
Assert.IsTrue (processBuildOutput (testResult.BuildResult), string.Format ("{0} - Mobile - We did not see our expected item in the build output: {1}", testName, libraryName));
string mobileBundlePath = Path.Combine (tmpDir, "bin/Debug/UnifiedExample.app/Contents/MonoBundle/");
if (libraryName != null)
@ -70,10 +70,10 @@ namespace Xamarin.MMP.Tests
// XM45
test.XM45 = true;
buildResults = TI.TestUnifiedExecutable (test, false).BuildOutput;
Assert.IsTrue (!buildShouldBeSuccessful || !buildResults.Contains ("MM2006"), string.Format ("{0} - XM45 had MM2006 state {1} not match expected\n{2}", testName, buildShouldBeSuccessful, buildResults));
testResult = TI.TestUnifiedExecutable (test, false);
Assert.IsTrue (!buildShouldBeSuccessful || !testResult.BuildResult.HasMessage (2006), string.Format ("{0} - XM45 had MM2006 state {1} not match expected\n{2}", testName, buildShouldBeSuccessful, testResult));
if (processBuildOutput != null)
Assert.IsTrue (processBuildOutput (buildResults), string.Format ("{0} - Mobile - We did not see our expected item in the build output: {1}", testName, libraryName));
Assert.IsTrue (processBuildOutput (testResult.BuildResult), string.Format ("{0} - Mobile - We did not see our expected item in the build output: {1}", testName, libraryName));
string xm45BundlePath = Path.Combine (tmpDir, "bin/Debug/XM45Example.app/Contents/MonoBundle/");
if (libraryName != null)
@ -112,7 +112,7 @@ namespace Xamarin.MMP.Tests
MMPTests.RunMMPTest (tmpDir => {
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { ItemGroup = CreateSingleNativeRef (SimpleStaticPath, "Static") };
NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_InMainProjectWorks - Static", null, true, false, s => {
var clangLines = s.Split ('\n').Where (x => x.Contains ("usr/bin/clang"));
var clangLines = s.BuildOutputLines.Where (x => x.Contains ("usr/bin/clang"));
var staticLib = clangLines.Where (x => x.Contains ("SimpleClassStatic.a"));
Assert.That (staticLib, Is.Not.Empty, "SimpleClassStatic.a:\n\t{0}", string.Join ("\n\t", clangLines));
return true;
@ -208,7 +208,7 @@ namespace Xamarin.MMP.Tests
ItemGroup = CreateSingleNativeRef ("/Library/Frameworks/Mono.framework/Libraries/libintl.dylib", "Dynamic")
};
var log = TI.TestUnifiedExecutable (test);
Console.WriteLine (log.BuildOutput);
Console.WriteLine (log.BuildResult);
Assert.True (File.Exists (Path.Combine (tmpDir, "bin/Debug/XM45Example.app/Contents/MonoBundle/libintl.dylib")));
});
}

Просмотреть файл

@ -66,8 +66,8 @@ namespace Xamarin.MMP.Tests
TI.CopyFileWithSubstitutions (main, main, s => s.Replace ("%TESTCODE%", TestCode));
TI.NugetRestore (project);
string output = TI.BuildProject (Path.Combine (tmpDir, "Today/TodayExtensionTest.csproj"));
Assert.IsTrue (!output.Contains ("MM2013"));
var buildResult = TI.BuildProject (Path.Combine (tmpDir, "Today/TodayExtensionTest.csproj"));
buildResult.Messages.AssertNoMessage (2013);
});
}
}

Просмотреть файл

@ -10,9 +10,9 @@ namespace Xamarin.MMP.Tests
{
const string MigrateCSProjTag = "<MigrateToNewXMIdentifier>true</MigrateToNewXMIdentifier>";
public bool MatchesTFI (string expected, string buildOutput)
public bool MatchesTFI (string expected, BuildResult buildOutput)
{
string tfiLine = buildOutput.SplitLines ().FirstOrDefault (x => x.StartsWith ("TargetFrameworkIdentifier =", StringComparison.Ordinal));
var tfiLine = buildOutput.BuildOutputLines.FirstOrDefault (x => x.StartsWith ("TargetFrameworkIdentifier =", StringComparison.Ordinal));
if (tfiLine == null)
return false;
return tfiLine.Contains (expected);
@ -26,9 +26,9 @@ namespace Xamarin.MMP.Tests
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) {
XM45 = xm45
};
var buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
var buildOutput = TI.TestUnifiedExecutable (test).BuildResult;
string standardTFI = xm45 ? ".NETFramework" : "Xamarin.Mac";
Assert.True (MatchesTFI (standardTFI, buildOutput), $"Build did not have expected TFI: {TI.PrintRedirectIfLong (buildOutput)}");
Assert.True (MatchesTFI (standardTFI, buildOutput), $"Build did not have expected TFI.");
});
}
@ -37,8 +37,8 @@ namespace Xamarin.MMP.Tests
{
MMPTests.RunMMPTest (tmpDir => {
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = MigrateCSProjTag };
var buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.True (MatchesTFI ("Xamarin.Mac", buildOutput), $"Build did not have expected TFI: {TI.PrintRedirectIfLong (buildOutput)}");
var buildOutput = TI.TestUnifiedExecutable (test).BuildResult;
Assert.True (MatchesTFI ("Xamarin.Mac", buildOutput), $"Build did not have expected TFI.");
});
}
@ -50,8 +50,8 @@ namespace Xamarin.MMP.Tests
XM45 = true,
CSProjConfig = MigrateCSProjTag
};
var buildOutput = TI.TestUnifiedExecutable (test).BuildOutput;
Assert.True (MatchesTFI ("Xamarin.Mac.NET", buildOutput), $"Build did not have expected TFI: {TI.PrintRedirectIfLong (buildOutput)}");
var buildOutput = TI.TestUnifiedExecutable (test).BuildResult;
Assert.True (MatchesTFI ("Xamarin.Mac.NET", buildOutput), $"Build did not have expected TFI.");
});
}
}

Просмотреть файл

@ -1,11 +0,0 @@
<!-- All msbuild target logic needs to be inside a project tag -->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildDependsOn>$(BuildDependsOn);CreateNativeLibs</BuildDependsOn>
</PropertyGroup>
<Target Name="CreateNativeLibs" Inputs="$(MSBuildThisFileDirectory)/../common/mac/SimpleClass.m" Outputs="$(MSBuildThisFileDirectory)/../mac-binding-project/bin/SimpleClassDylib.dylib">
<Exec Command="make bin/SimpleClassDylib.dylib" WorkingDirectory="$(MSBuildThisFileDirectory)/../mac-binding-project/" />
</Target>
</Project>

Просмотреть файл

@ -1,85 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\NUnit.3.11.0\build\NUnit.props" Condition="Exists('..\..\packages\NUnit.3.11.0\build\NUnit.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F8500DCE-2119-4DF9-8360-0F46DDB6930C}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>msbuildMac</RootNamespace>
<AssemblyName>msbuild-mac</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;MONOMAC</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<DefineConstants>MONOMAC;MMP_TEST</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit.ConsoleRunner" Version="3.11.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
<ItemGroup>
<Compile Include="src\MSBuild-Smoke.cs" />
<Compile Include="..\common\mac\ProjectTestHelpers.cs">
<Link>ProjectTestHelpers.cs</Link>
</Compile>
<Compile Include="..\..\tests\common\Configuration.cs">
<Link>Configuration.cs</Link>
</Compile>
<Compile Include="..\..\src\ObjCRuntime\ErrorHelper.cs">
<Link>ErrorHelper.cs</Link>
</Compile>
<Compile Include="..\..\src\ObjCRuntime\RuntimeException.cs">
<Link>RuntimeException.cs</Link>
</Compile>
<Compile Include="src\RoslynSmokeTests.cs" />
<Compile Include="src\RuntimeTests.cs" />
<Compile Include="..\..\tools\common\StringUtils.cs">
<Link>StringUtils.cs</Link>
</Compile>
<Compile Include="..\common\ExecutionHelper.cs">
<Link>ExecutionHelper.cs</Link>
</Compile>
<Compile Include="..\common\Profile.cs">
<Link>Profile.cs</Link>
</Compile>
<Compile Include="..\..\tools\common\Driver.execution.cs">
<Link>Driver.execution.cs</Link>
</Compile>
<Compile Include="..\..\tools\common\Execution.cs">
<Link>Execution.cs</Link>
</Compile>
<Compile Include="..\mtouch\Cache.cs">
<Link>Cache.cs</Link>
</Compile>
<Compile Include="..\..\tools\common\TargetFramework.cs">
<Link>TargetFramework.cs</Link>
</Compile>
<Compile Include="..\..\tools\common\ApplePlatform.cs">
<Link>ApplePlatform.cs</Link>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="CustomBuildActions.targets" />
</Project>

Просмотреть файл

@ -40,8 +40,8 @@ namespace Xamarin.MMP.Tests
void TestBCLCore (string tmpDir, string projectName)
{
File.Copy (Path.Combine (TI.AssemblyDirectory, TI.TestDirectory + "common/mac/System.Collections.Immutable.dll"), Path.Combine (tmpDir, "System.Collections.Immutable.dll"));
string reference = "<Reference Include=\"System.Collections.Immutable\"><HintPath>System.Collections.Immutable.dll</HintPath></Reference>";
var dll = Path.GetFullPath (Path.Combine (TI.TestDirectory + "common", "mac", "System.Collections.Immutable.dll"));
string reference = $"<Reference Include=\"System.Collections.Immutable\"><HintPath>{dll}</HintPath></Reference>";
string testCode = "var v = System.Collections.Immutable.ImmutableArray.CreateRange (new int [] { 42 });";
string projectPath = TI.GenerateEXEProject (new TI.UnifiedTestConfig (tmpDir) { ProjectName = projectName, References = reference, TestCode = testCode });
TI.BuildProject (projectPath);
@ -121,68 +121,63 @@ namespace Xamarin.MMP.Tests
public void BuildUnifiedProject_WithJustNativeRefNoLinkWith_Builds()
{
RunMSBuildTest (tmpDir => {
string dylibPath = Path.Combine (tmpDir, "dll/");
Directory.CreateDirectory (dylibPath);
File.Copy (Path.Combine (TI.AssemblyDirectory, TI.TestDirectory + "mac-binding-project/bin/SimpleClassDylib.dylib"), Path.Combine (dylibPath, "SimpleClassDylib.dylib"));
string itemGroup = "<ItemGroup><NativeReference Include=\".\\dll\\SimpleClassDylib.dylib\"> <IsCxx>False</IsCxx><Kind>Dynamic</Kind> </NativeReference> </ItemGroup>";
var dylib = Path.GetFullPath (Path.Combine (TI.TestDirectory, "test-libraries", ".libs", "macos", "libtest.dylib"));
string itemGroup = $"<ItemGroup><NativeReference Include=\"{dylib}\"> <IsCxx>False</IsCxx><Kind>Dynamic</Kind> </NativeReference> </ItemGroup>";
string projectPath = TI.GenerateEXEProject (new TI.UnifiedTestConfig (tmpDir) { ProjectName = "UnifiedExample.csproj", ItemGroup = itemGroup });
string buildResults = TI.BuildProject (projectPath);
Assert.IsFalse (buildResults.Contains ("MM2006"), "BuildUnifiedProject_WittJustNativeRefNoLinkWith_Builds found 2006 warning: " + buildResults);
Assert.IsTrue (File.Exists (Path.Combine (tmpDir, "bin/Debug/UnifiedExample.app/Contents/MonoBundle/SimpleClassDylib.dylib")));
var testResults = TI.BuildProject (projectPath);
testResults.Messages.AssertNoMessage (2006);
Assert.That (Path.Combine (tmpDir, $"bin", "Debug", "UnifiedExample.app", "Contents", "MonoBundle", Path.GetFileName (dylib)), Does.Exist, "dylib in app");
StringBuilder output = new StringBuilder ();
Xamarin.Bundler.Driver.RunCommand ("/usr/bin/otool", new [] { "-L", Path.Combine (tmpDir, "bin/Debug/UnifiedExample.app/Contents/MacOS/UnifiedExample") }, output);
Assert.IsTrue (output.ToString ().Contains ("SimpleClassDylib.dylib"));
Assert.AreEqual (0, ExecutionHelper.Execute ("/usr/bin/otool", new [] { "-L", Path.Combine (tmpDir, "bin/Debug/UnifiedExample.app/Contents/MacOS/UnifiedExample") }, out var output));
Assert.IsTrue (output.ToString ().Contains (Path.GetFileName (dylib)));
});
}
[Test]
public void Build_BindingLibrary_SmokeTest ()
[TestCase ("XM45Binding.csproj")]
[TestCase ("MobileBinding.csproj")]
[TestCase ("BindingProjectWithNoTag.csproj")]
public void Build_BindingLibrary_SmokeTest (string projectName)
{
RunMSBuildTest (tmpDir => {
foreach (string projectName in new []{"XM45Binding.csproj", "MobileBinding.csproj", "BindingProjectWithNoTag.csproj"}) {
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { ProjectName = projectName };
string projectPath = TI.GenerateBindingLibraryProject (test);
TI.BuildProject (projectPath);
}
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { ProjectName = projectName };
string projectPath = TI.GenerateBindingLibraryProject (test);
TI.BuildProject (projectPath);
});
}
[Test]
public void BuildingSameBindingProject_TwoTimes_ShallNotInvokeMMPTwoTimes ()
[TestCase ("XM45Binding.csproj")]
[TestCase ("MobileBinding.csproj")]
[TestCase ("BindingProjectWithNoTag.csproj")]
public void BuildingSameBindingProject_TwoTimes_ShallNotInvokeMMPTwoTimes (string project)
{
const string nativeRefItemGroup = "<ItemGroup><NativeReference Include = \"\\usr\\lib\\libz.dylib\"><Kind>Dynamic</Kind><SmartLink>False</SmartLink></NativeReference></ItemGroup>";
RunMSBuildTest (tmpDir =>
{
foreach (string project in new[] { "XM45Binding.csproj", "MobileBinding.csproj", "BindingProjectWithNoTag.csproj" })
{
var config = new TI.UnifiedTestConfig (tmpDir) { ProjectName = project, ItemGroup = nativeRefItemGroup };
string projectPath = TI.GenerateBindingLibraryProject (config);
string buildOutput = TI.BuildProject (projectPath);
Assert.IsTrue (buildOutput.Contains (@"Building target ""CoreCompile"""));
RunMSBuildTest (tmpDir => {
var config = new TI.UnifiedTestConfig (tmpDir) { ProjectName = project, ItemGroup = nativeRefItemGroup };
string projectPath = TI.GenerateBindingLibraryProject (config);
string buildOutput = TI.BuildProject (projectPath).BuildOutput;
Assert.IsTrue (buildOutput.Contains (@"Building target ""CoreCompile"""));
string secondBuildOutput = TI.BuildProject (projectPath);
Assert.IsFalse (secondBuildOutput.Contains (@"Building target ""CoreCompile"""));
}
string secondBuildOutput = TI.BuildProject (projectPath).BuildOutput;
Assert.IsFalse (secondBuildOutput.Contains (@"Building target ""CoreCompile"""));
});
}
[Test]
public void BuildingSameProject_TwoTimes_ShallNotInvokeMMPTwoTimes ()
[TestCase ("UnifiedExample.csproj")]
[TestCase ("XM45Example.csproj")]
public void BuildingSameProject_TwoTimes_ShallNotInvokeMMPTwoTimes (string project)
{
RunMSBuildTest (tmpDir =>
{
foreach (var project in new string[] { "UnifiedExample.csproj", "XM45Example.csproj" })
{
var config = new TI.UnifiedTestConfig (tmpDir) { ProjectName = project };
string projectPath = TI.GenerateEXEProject (config);
string buildOutput = TI.BuildProject (projectPath);
Assert.IsTrue (buildOutput.Contains (@"Building target ""_CompileToNative"""));
RunMSBuildTest (tmpDir => {
var config = new TI.UnifiedTestConfig (tmpDir) { ProjectName = project };
string projectPath = TI.GenerateEXEProject (config);
string buildOutput = TI.BuildProject (projectPath).BuildOutput;
Assert.IsTrue (buildOutput.Contains (@"Building target ""_CompileToNative"""));
string secondBuildOutput = TI.BuildProject (projectPath);
Assert.IsFalse (secondBuildOutput.Contains (@"Building target ""_CompileToNative"""));
}
string secondBuildOutput = TI.BuildProject (projectPath).BuildOutput;
Assert.IsFalse (secondBuildOutput.Contains (@"Building target ""_CompileToNative"""));
});
}

Просмотреть файл

@ -122,20 +122,6 @@ namespace Xamarin.Tests {
return props.LastOrDefault ()?.Value ?? string.Empty;
}
public static void PrintBinLog (string path, StringBuilder sb)
{
var reader = new BinLogReader ();
foreach (var record in reader.ReadRecords (path)) {
if (record == null)
continue;
var args = record.Args;
if (args == null)
continue;
sb.AppendLine (args.Message);
}
}
public void ParseBinLog (string log)
{
ErrorEvents.Clear ();

Просмотреть файл

@ -47,6 +47,15 @@
<Compile Include="..\..\common\Profile.cs">
<Link>external\Profile.cs</Link>
</Compile>
<Compile Include="..\..\common\mac\ProjectTestHelpers.cs">
<Link>external\ProjectTestHelpers.cs</Link>
</Compile>
<Compile Include="..\..\common\BinLog.cs">
<Link>external\BinLog.cs</Link>
</Compile>
<Compile Include="..\..\common\Tool.cs">
<Link>external\Tool.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\external\Xamarin.MacDev\Xamarin.MacDev\Xamarin.MacDev.csproj" />

Просмотреть файл

@ -28,6 +28,7 @@
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit.ConsoleRunner" Version="3.11.1" />
<PackageReference Include="Mono.Cecil" Version="0.11.1" />
<PackageReference Include="MSBuild.StructuredLogger" Version="2.1.176" />
</ItemGroup>
<ItemGroup>
<Compile Include="MTouch.cs" />
@ -115,6 +116,12 @@
<Compile Include="..\..\tools\common\FileCopier.cs">
<Link>tools\common\FileCopier.cs</Link>
</Compile>
<Compile Include="..\common\Tool.cs">
<Link>Tool.cs</Link>
</Compile>
<Compile Include="..\common\BinLog.cs">
<Link>BinLog.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\tools\mtouch\Errors.resx">

Просмотреть файл

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mmptest", "mmptest\mmptest.csproj", "{6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "msbuild-mac", "msbuild-mac\msbuild-mac.csproj", "{F8500DCE-2119-4DF9-8360-0F46DDB6930C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xammac_tests", "xammac_tests\xammac_tests.csproj", "{22BF080C-AFAD-445B-8BB5-42B9E7FDBC68}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dont link-mac", "linker\mac\dont link\dont link-mac.csproj", "{78831857-A261-8EE0-A5F6-33D2628DE5D0}"
@ -43,14 +41,6 @@ Global
{6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Debug|x86.Build.0 = Debug|x86
{6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Release|x86.ActiveCfg = Release|x86
{6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Release|x86.Build.0 = Release|x86
{F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Debug|Any CPU.ActiveCfg = Debug|x86
{F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Debug|Any CPU.Build.0 = Debug|x86
{F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Release|Any CPU.ActiveCfg = Release|x86
{F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Release|Any CPU.Build.0 = Release|x86
{F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Debug|x86.ActiveCfg = Debug|x86
{F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Debug|x86.Build.0 = Debug|x86
{F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Release|x86.ActiveCfg = Release|x86
{F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Release|x86.Build.0 = Release|x86
{22BF080C-AFAD-445B-8BB5-42B9E7FDBC68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{22BF080C-AFAD-445B-8BB5-42B9E7FDBC68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{22BF080C-AFAD-445B-8BB5-42B9E7FDBC68}.Release|Any CPU.ActiveCfg = Release|Any CPU

Просмотреть файл

@ -97,9 +97,6 @@
<Compile Include="..\EmbeddedResources\ResourcesTest.cs">
<Link>EmbeddedResources\ResourcesTest.cs</Link>
</Compile>
<Compile Include="..\common\mac\ProjectTestHelpers.cs">
<Link>ProjectTestHelpers.cs</Link>
</Compile>
<Compile Include="..\..\tools\common\StringUtils.cs">
<Link>StringUtils.cs</Link>
</Compile>

Просмотреть файл

@ -276,7 +276,6 @@ namespace Xharness {
var hard_coded_test_suites = new [] {
new { Directory = "mmptest", ProjectFile = "mmptest", Name = "mmptest", IsNUnit = true, Configurations = (string[]) null, Platform = "x86", Flavors = MacFlavors.Console, },
new { Directory = "msbuild-mac", ProjectFile = "msbuild-mac", Name = "MSBuild tests", IsNUnit = true, Configurations = (string[]) null, Platform = "x86", Flavors = MacFlavors.Console, },
new { Directory = "xammac_tests", ProjectFile = "xammac_tests", Name = "xammac tests", IsNUnit = false, Configurations = new string [] { "Debug", "Release" }, Platform = "AnyCPU", Flavors = MacFlavors.Modern, },
new { Directory = "linker/mac/link all", ProjectFile = "link all-mac", Name = "link all", IsNUnit = false, Configurations = new string [] { "Debug", "Release" }, Platform = "x86", Flavors = MacFlavors.Modern, },
new { Directory = "linker/mac/link sdk", ProjectFile = "link sdk-mac", Name = "link sdk", IsNUnit = false, Configurations = new string [] { "Debug", "Release" }, Platform = "x86", Flavors = MacFlavors.Modern, },

Просмотреть файл

@ -45,7 +45,7 @@ namespace Xharness.Jenkins {
public bool IncludetvOS = true;
public bool IncludewatchOS = true;
public bool IncludeMmpTest;
public bool IncludeiOSMSBuild = true;
public bool IncludeMSBuild = true;
public bool IncludeMtouch;
public bool IncludeBtouch;
public bool IncludeMacBindingProject;

Просмотреть файл

@ -34,9 +34,9 @@ namespace Xharness.Jenkins {
ProjectConfiguration = "Debug",
Platform = TestPlatform.iOS,
TestName = "MSBuild tests",
Mode = "iOS (tasks)",
Mode = "Tasks",
Timeout = TimeSpan.FromMinutes (60),
Ignored = !jenkins.IncludeiOSMSBuild,
Ignored = !jenkins.IncludeMSBuild,
SupportsParallelExecution = false,
};
yield return nunitExecutioniOSMSBuild;
@ -56,9 +56,9 @@ namespace Xharness.Jenkins {
ProjectConfiguration = "Debug",
Platform = TestPlatform.iOS,
TestName = "MSBuild tests",
Mode = "iOS (integration)",
Mode = "Integration",
Timeout = TimeSpan.FromMinutes (90),
Ignored = !jenkins.IncludeiOSMSBuild,
Ignored = !jenkins.IncludeMSBuild,
SupportsParallelExecution = false,
};
yield return nunitExecutioniOSMSBuildIntegration;

Просмотреть файл

@ -179,7 +179,7 @@ namespace Xharness.Jenkins {
SetEnabled (files, xtroPrefixes, "xtro", ref jenkins.IncludeXtro);
SetEnabled (files, cecilPrefixes, "cecil", ref jenkins.IncludeCecil);
SetEnabled (files, dotnetFilenames, "dotnet", ref jenkins.IncludeDotNet);
SetEnabled (files, msbuildFilenames, "ios-msbuild", ref jenkins.IncludeiOSMSBuild);
SetEnabled (files, msbuildFilenames, "msbuild", ref jenkins.IncludeMSBuild);
}
void SelectTestsByLabel (int pullRequest)
@ -248,7 +248,7 @@ namespace Xharness.Jenkins {
SetEnabled (labels, "tvos", ref jenkins.IncludetvOS);
SetEnabled (labels, "watchos", ref jenkins.IncludewatchOS);
SetEnabled (labels, "mac", ref jenkins.IncludeMac);
SetEnabled (labels, "ios-msbuild", ref jenkins.IncludeiOSMSBuild);
SetEnabled (labels, "msbuild", ref jenkins.IncludeMSBuild);
SetEnabled (labels, "ios-simulator", ref jenkins.IncludeSimulator);
SetEnabled (labels, "non-monotouch", ref jenkins.IncludeNonMonotouch);
SetEnabled (labels, "monotouch", ref jenkins.IncludeMonotouch);