[XM] Add hybrid/standard AOT option and improve AOT code (#1650)

* [XM] Seperate parsing from compilation in AOT code

- Parsing command line options was too entangled with actually compiling
- Refactor test code to centralize Compile, reducing some complexity of tests
- Groundwork for hybrid vs non-hybrid AOT work

* Add hybrid/standard AOT support

* Add xammac_tests to makefile/jenkins

* Add flag to force AOT

* Disable MonoTouchFixtures.Contacts.ContactStoreTest.GetUnifiedContacts on XM due to prompts on Jenkins
This commit is contained in:
Chris Hamons 2017-02-08 13:40:48 -06:00 коммит произвёл GitHub
Родитель 9c79a7102d
Коммит 2c835c5294
9 изменённых файлов: 293 добавлений и 166 удалений

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

@ -567,7 +567,7 @@ int xamarin_main (int argc, char **argv, bool is_extension)
int env_argc = 0;
char **env_argv = get_mono_env_options (&env_argc);
int new_argc = env_argc + 2 /* --debug executable */ + argc ;
if (xamarin_mac_aot)
if (xamarin_mac_hybrid_aot)
new_argc += 1;
char **new_argv = (char **) malloc (sizeof (char *) * (new_argc + 1 /* null terminated */));
const char **ptr = (const char **) new_argv;
@ -586,7 +586,7 @@ int xamarin_main (int argc, char **argv, bool is_extension)
// executable assembly
*ptr++ = exe_path;
if (xamarin_mac_aot)
if (xamarin_mac_hybrid_aot)
*ptr++ = "--hybrid-aot";
// the rest

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

@ -45,7 +45,7 @@ bool xamarin_gc_pump = false;
#if MONOMAC
// FIXME: implement release mode for monomac.
bool xamarin_debug_mode = true;
bool xamarin_mac_aot = false;
bool xamarin_mac_hybrid_aot = false;
#else
bool xamarin_debug_mode = false;
#endif

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

@ -48,7 +48,7 @@ extern bool xamarin_gc_pump;
extern bool xamarin_debug_mode;
extern bool xamarin_disable_lldb_attach;
#if MONOMAC
extern bool xamarin_mac_aot;
extern bool xamarin_mac_hybrid_aot;
#endif
extern bool xamarin_init_mono_debug;
extern int xamarin_log_level;

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

@ -34,7 +34,9 @@ namespace MonoTouchFixtures.Contacts {
TestRuntime.AssertXcodeVersion (7, 0);
}
#if !MONOMAC // Unlike XI, XM does not have infrastructure yet to disable prompts
[Test]
#endif
public void GetUnifiedContacts ()
{
string identifier = null;

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

@ -16,7 +16,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<OutputPath>bin\x86\Debug</OutputPath>
<DefineConstants>__UNIFIED__;DEBUG;MONOMAC;XAMCORE_2_0</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@ -37,7 +37,7 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<OutputPath>bin\x86\Release</OutputPath>
<DefineConstants></DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>

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

@ -279,7 +279,7 @@ namespace xharness
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "introspection", "Mac", "introspection-mac.csproj")), skipXMVariations : true));
var hard_coded_test_suites = new string[] { "mmptest", "msbuild-mac" };
var hard_coded_test_suites = new string[] { "mmptest", "msbuild-mac", "xammac_tests" };
foreach (var p in hard_coded_test_suites)
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".csproj")), generateVariations: false));

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

@ -56,7 +56,7 @@ namespace Xamarin.Bundler {
public delegate int RunCommandDelegate (string path, string args, string[] env = null, StringBuilder output = null, bool suppressPrintOnErrors = false);
public enum MonoType {
public enum AOTCompilerType {
Invalid,
Bundled64,
Bundled32,
@ -64,24 +64,115 @@ namespace Xamarin.Bundler {
System32,
}
public enum AOTCompilationType {
Default,
None,
All,
Core,
SDK,
Explicit
}
public enum AOTKind {
Default,
Standard,
Hybrid
}
public class AOTOptions
{
public bool IsAOT => CompilationType != AOTCompilationType.Default && CompilationType != AOTCompilationType.None;
public bool IsHybridAOT => IsAOT && Kind == AOTKind.Hybrid;
public AOTCompilationType CompilationType { get; private set; } = AOTCompilationType.Default;
public AOTKind Kind { get; private set; } = AOTKind.Standard;
public List <string> IncludedAssemblies { get; private set; } = new List <string> ();
public List <string> ExcludedAssemblies { get; private set; } = new List <string> ();
public AOTOptions (string options)
{
// Syntax - all,core,sdk,none or "" if explicit then optional list of +/-'ed assemblies
// Sections seperated by ,
string [] optionParts = options.Split (',');
for (int i = 0 ; i < optionParts.Length ; ++i) {
string option = optionParts [i];
AOTKind kind = AOTKind.Default;
// Technically '|' is valid in a file name, so |hybrid.dll would be as well.
// So check the left hand side for a valid option and pass if not
if (option.Contains ("|")) {
string [] optionTypeParts = option.Split ('|');
if (optionTypeParts.Length != 2)
throw new MonoMacException (20, true, "The valid options for '{0}' are '{1}'.", "--aot", "{none, all, core, sdk}{|hybrid}, then an optional explicit list of assemblies.");
switch (optionTypeParts [0]) {
case "none":
case "core":
case "sdk":
case "all": {
option = optionTypeParts [0];
switch (optionTypeParts [1]) {
case "hybrid":
kind = AOTKind.Hybrid;
break;
case "standard":
kind = AOTKind.Standard;
break;
default:
throw new MonoMacException (20, true, "The valid options for '{0}' are '{1}'.", "--aot", "{none, all, core, sdk}{|hybrid}, then an optional explicit list of assemblies.");
}
break;
}
default:
break;
}
}
switch (option) {
case "none":
CompilationType = AOTCompilationType.None;
if (kind != AOTKind.Default)
Kind = kind;
continue;
case "all":
CompilationType = AOTCompilationType.All;
if (kind != AOTKind.Default)
Kind = kind;
continue;
case "sdk":
CompilationType = AOTCompilationType.SDK;
if (kind != AOTKind.Default)
Kind = kind;
continue;
case "core":
CompilationType = AOTCompilationType.Core;
if (kind != AOTKind.Default)
Kind = kind;
continue;
}
if (option.StartsWith ("+", StringComparison.Ordinal)) {
if (CompilationType == AOTCompilationType.Default)
CompilationType = AOTCompilationType.Explicit;
IncludedAssemblies.Add (option.Substring (1));
continue;
}
if (option.StartsWith ("-", StringComparison.Ordinal)) {
if (CompilationType == AOTCompilationType.Default)
CompilationType = AOTCompilationType.Explicit;
ExcludedAssemblies.Add (option.Substring (1));
continue;
}
throw new MonoMacException (20, true, "The valid options for '{0}' are '{1}'.", "--aot", "{none, all, core, sdk}{|hybrid}, then an optional explicit list of assemblies.");
}
if (CompilationType == AOTCompilationType.Default)
throw new MonoMacException (20, true, "The valid options for '{0}' are '{1}'.", "--aot", "{none, all, core, sdk}{|hybrid}, then an optional explicit list of assemblies.");
}
}
public class AOTCompiler
{
enum AotType {
Default,
None,
All,
Core,
SDK,
Explicit
}
AotType aotType = AotType.Default;
public bool IsAOT => aotType != AotType.Default && aotType != AotType.None;
// Set to Key -> True when we've seen a given include/exclude during compile to catch errors
Dictionary <string, bool> includedAssemblies = new Dictionary <string, bool> ();
Dictionary <string, bool> excludedAssemblies = new Dictionary <string, bool> ();
// Allows tests to stub out actual compilation and parallelism
public RunCommandDelegate RunCommand { get; set; } = Driver.RunCommand;
public ParallelOptions ParallelOptions { get; set; } = new ParallelOptions () { MaxDegreeOfParallelism = Driver.Concurrency };
@ -89,47 +180,46 @@ namespace Xamarin.Bundler {
public string Quote (string f) => Driver.Quote (f);
public void Parse (string options)
{
// Syntax - all,core,sdk,none or "" if explicit then optional list of +/-'ed assemblies
// Sections seperated by ,
foreach (var option in options.Split (',')) {
switch (option) {
case "none":
aotType = AotType.None;
continue;
case "all":
aotType = AotType.All;
continue;
case "sdk":
aotType = AotType.SDK;
continue;
case "core":
aotType = AotType.Core;
continue;
}
AOTOptions options;
AOTCompilerType compilerType;
if (option.StartsWith ("+", StringComparison.Ordinal)) {
if (aotType == AotType.Default)
aotType = AotType.Explicit;
includedAssemblies.Add (option.Substring (1), false);
continue;
}
if (option.StartsWith ("-", StringComparison.Ordinal)) {
if (aotType == AotType.Default)
aotType = AotType.Explicit;
excludedAssemblies.Add (option.Substring (1), false);
continue;
}
throw new MonoMacException (20, true, "The valid options for '{0}' are '{1}'.", "--aot", "none, all, core, sdk, and an explicit list of assemblies.");
}
if (aotType == AotType.Default)
throw new MonoMacException (20, true, "The valid options for '{0}' are '{1}'.", "--aot", "none, all, core, sdk, and an explicit list of assemblies.");
public AOTCompiler (AOTOptions options, AOTCompilerType compilerType)
{
this.options = options;
this.compilerType = compilerType;
}
public void Compile (string path)
{
Compile (new FileSystemEnumerator (path));
}
public void Compile (IFileEnumerator files)
{
if (!options.IsAOT)
throw ErrorHelper.CreateError (0099, "Internal error \"AOTBundle with aot: {0}\" Please file a bug report with a test case (http://bugzilla.xamarin.com).", options.CompilationType);
var monoEnv = new string [] {"MONO_PATH", files.RootDir };
Parallel.ForEach (GetFilesToAOT (files), ParallelOptions, file => {
if (RunCommand (MonoPath, String.Format ("--aot{0} {1}", options.IsHybridAOT ? "=hybrid" : "", Quote (file)), monoEnv) != 0)
throw ErrorHelper.CreateError (3001, "Could not AOT the assembly '{0}'", file);
});
}
List<string> GetFilesToAOT (IFileEnumerator files)
{
// Make a dictionary of included/excluded files to track if we've missed some at the end
Dictionary <string, bool> includedAssemblies = new Dictionary <string, bool> ();
foreach (var item in options.IncludedAssemblies)
includedAssemblies [item] = false;
Dictionary <string, bool> excludedAssemblies = new Dictionary <string, bool> ();
foreach (var item in options.ExcludedAssemblies)
excludedAssemblies [item] = false;
var aotFiles = new List<string> ();
foreach (var file in files.Files) {
string fileName = Path.GetFileName (file);
string extension = Path.GetExtension (file);
@ -137,33 +227,33 @@ namespace Xamarin.Bundler {
continue;
if (excludedAssemblies.ContainsKey (fileName)) {
excludedAssemblies[fileName] = true;
excludedAssemblies [fileName] = true;
continue;
}
if (includedAssemblies.ContainsKey (fileName)) {
includedAssemblies[fileName] = true;
includedAssemblies [fileName] = true;
aotFiles.Add (file);
continue;
}
switch (aotType) {
case AotType.All:
switch (options.CompilationType) {
case AOTCompilationType.All:
aotFiles.Add (file);
break;
case AotType.SDK:
case AOTCompilationType.SDK:
string fileNameNoExtension = Path.GetFileNameWithoutExtension (fileName);
if (Profile.IsSdkAssembly (fileNameNoExtension) || fileName == "Xamarin.Mac.dll")
aotFiles.Add (file);
break;
case AotType.Core:
case AOTCompilationType.Core:
if (fileName == "Xamarin.Mac.dll" || fileName == "System.dll" || fileName == "mscorlib.dll")
aotFiles.Add (file);
break;
case AotType.Explicit:
case AOTCompilationType.Explicit:
break; // In explicit, only included includedAssemblies included
default:
throw ErrorHelper.CreateError (0099, "Internal error \"GetFilesToAOT with aot: {0}\" Please file a bug report with a test case (http://bugzilla.xamarin.com).", aotType);
throw ErrorHelper.CreateError (0099, "Internal error \"GetFilesToAOT with aot: {0}\" Please file a bug report with a test case (http://bugzilla.xamarin.com).", options.CompilationType);
}
}
@ -178,38 +268,22 @@ namespace Xamarin.Bundler {
return aotFiles;
}
string GetMonoPath (MonoType monoType)
string MonoPath
{
switch (monoType) {
case MonoType.Bundled64:
return Path.Combine (XamarinMacPrefix, "bin/bmac-mobile-mono");
case MonoType.Bundled32:
return Path.Combine (XamarinMacPrefix, "bin/bmac-mobile-mono-32");
case MonoType.System64:
return "/Library/Frameworks/Mono.framework/Commands/mono64";
case MonoType.System32:
return "/Library/Frameworks/Mono.framework/Commands/mono32";
default:
throw ErrorHelper.CreateError (0099, "Internal error \"GetMonoPath with monoType: {0}\" Please file a bug report with a test case (http://bugzilla.xamarin.com).", monoType);
get {
switch (compilerType) {
case AOTCompilerType.Bundled64:
return Path.Combine (XamarinMacPrefix, "bin/bmac-mobile-mono");
case AOTCompilerType.Bundled32:
return Path.Combine (XamarinMacPrefix, "bin/bmac-mobile-mono-32");
case AOTCompilerType.System64:
return "/Library/Frameworks/Mono.framework/Commands/mono64";
case AOTCompilerType.System32:
return "/Library/Frameworks/Mono.framework/Commands/mono32";
default:
throw ErrorHelper.CreateError (0099, "Internal error \"MonoPath with compilerType: {0}\" Please file a bug report with a test case (http://bugzilla.xamarin.com).", compilerType);
}
}
}
public void Compile (MonoType monoType, string path)
{
Compile (monoType, new FileSystemEnumerator (path));
}
public void Compile (MonoType monoType, IFileEnumerator files)
{
if (!IsAOT)
throw ErrorHelper.CreateError (0099, "Internal error \"AOTBundle with aot: {0}\" Please file a bug report with a test case (http://bugzilla.xamarin.com).", aotType);
var monoEnv = new string [] {"MONO_PATH", files.RootDir };
Parallel.ForEach (GetFilesToAOT (files), ParallelOptions, file => {
if (RunCommand (GetMonoPath (monoType), String.Format ("--aot=hybrid {0}", Quote (file)), monoEnv) != 0)
throw ErrorHelper.CreateError (3001, "Could not AOT the assembly '{0}'", file);
});
}
}
}

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

@ -187,7 +187,7 @@ namespace Xamarin.Bundler {
static int watch_level;
static Stopwatch watch;
static AOTCompiler aot = new AOTCompiler ();
static AOTOptions aotOptions = null;
static string xm_framework_dir;
public static string MMPDirectory {
@ -362,7 +362,7 @@ namespace Xamarin.Bundler {
{ "xamarin-system-framework", "Used with --target-framework=4.5 to select XM 4.5 Target Framework", v => { IsUnifiedFullSystemFramework = true; } },
{ "aot:", "Specify assemblies that should be compiled via experimental AOT.\n- none - No AOT (default)\n- all - Every assembly in MonoBundle not ignored\n- core - Just Xamarin.Mac.dll, System.dll, and mscorlib.dll\n sdk - Xamarin.Mac.dll and all BCL assemblies\nIndividual files can be included for AOT via +FileName.dll and excluded via -FileName.dll",
v => {
aot.Parse (v);
aotOptions = new AOTOptions (v);
}
},
};
@ -380,6 +380,12 @@ namespace Xamarin.Bundler {
throw new MonoMacException (10, true, "Could not parse the command line arguments: {0}", e.Message);
}
if (aotOptions == null) {
string forceAotVariable = Environment.GetEnvironmentVariable ("XM_FORCE_AOT");
if (forceAotVariable != null)
aotOptions = new AOTOptions (forceAotVariable);
}
App.RuntimeOptions = RuntimeOptions.Create (App, http_message_provider, tls_provider);
ErrorHelper.Verbosity = verbose;
@ -808,19 +814,19 @@ namespace Xamarin.Bundler {
if (App.LinkMode != LinkMode.All && App.RuntimeOptions != null)
App.RuntimeOptions.Write (App.AppDirectory);
if (aot.IsAOT) {
if (aotOptions != null && aotOptions.IsAOT) {
if (!IsUnified)
throw new MonoMacException (98, true, "AOT compilation is only available on Unified");
MonoType monoType;
AOTCompilerType compilerType;
if (IsUnifiedMobile || IsUnifiedFullXamMacFramework)
monoType = Is64Bit ? MonoType.Bundled64 : MonoType.Bundled32;
compilerType = Is64Bit ? AOTCompilerType.Bundled64 : AOTCompilerType.Bundled32;
else if (IsUnifiedFullSystemFramework)
monoType = Is64Bit ? MonoType.System64 : MonoType.System32;
compilerType = Is64Bit ? AOTCompilerType.System64 : AOTCompilerType.System32;
else
throw ErrorHelper.CreateError (0099, "Internal error \"AOT with unexpected profile.\" Please file a bug report with a test case (http://bugzilla.xamarin.com).");
aot.Compile (monoType, mmp_dir);
AOTCompiler compiler = new AOTCompiler (aotOptions, compilerType);
compiler.Compile (mmp_dir);
Watch ("AOT Compile", 1);
}
@ -1085,8 +1091,8 @@ namespace Xamarin.Bundler {
else
sw.WriteLine ("\tsetenv (\"MONO_GC_PARAMS\", \"major=marksweep\", 1);");
if (aot.IsAOT)
sw.WriteLine ("\txamarin_mac_aot = TRUE;");
if (aotOptions != null && aotOptions.IsHybridAOT)
sw.WriteLine ("\txamarin_mac_hybrid_aot = TRUE;");
sw.WriteLine ("\treturn 0;");
sw.WriteLine ("}");

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

@ -25,20 +25,24 @@ namespace Xamarin.MMP.Tests.Unit
}
}
AOTCompiler compiler;
List<Tuple<string, string>> commandsRun;
[SetUp]
public void Init ()
{
compiler = new AOTCompiler ()
// Make sure this is cleared between every test
commandsRun = new List<Tuple<string, string>> ();
}
void Compile (AOTOptions options, TestFileEnumerator files, AOTCompilerType compilerType = AOTCompilerType.Bundled64, RunCommandDelegate onRunDelegate = null)
{
AOTCompiler compiler = new AOTCompiler (options, compilerType)
{
RunCommand = OnRunCommand,
RunCommand = onRunDelegate != null ? onRunDelegate : OnRunCommand,
ParallelOptions = new ParallelOptions () { MaxDegreeOfParallelism = 1 },
XamarinMacPrefix = Driver.WalkUpDirHierarchyLookingForLocalBuild (), // HACK - AOT test shouldn't need this from driver.cs
};
commandsRun = new List<Tuple<string, string>> ();
compiler.Compile (files);
}
void ClearCommandsRun ()
@ -54,16 +58,16 @@ namespace Xamarin.MMP.Tests.Unit
return 0;
}
string GetExpectedMonoCommand (MonoType monoType)
string GetExpectedMonoCommand (AOTCompilerType compilerType)
{
switch (monoType) {
case MonoType.Bundled64:
switch (compilerType) {
case AOTCompilerType.Bundled64:
return "bmac-mobile-mono";
case MonoType.Bundled32:
case AOTCompilerType.Bundled32:
return "bmac-mobile-mono-32";
case MonoType.System64:
case AOTCompilerType.System64:
return "mono64";
case MonoType.System32:
case AOTCompilerType.System32:
return "mono32";
default:
Assert.Fail ("GetMonoPath with invalid option");
@ -71,22 +75,26 @@ namespace Xamarin.MMP.Tests.Unit
}
}
List<string> GetFiledAOTed (MonoType monoType = MonoType.Bundled64)
List<string> GetFiledAOTed (AOTCompilerType compilerType = AOTCompilerType.Bundled64, AOTKind kind = AOTKind.Standard)
{
List<string> filesAOTed = new List<string> ();
foreach (var command in commandsRun) {
Assert.IsTrue (command.Item1.EndsWith (GetExpectedMonoCommand (monoType)), "Unexpected command: " + command.Item1);
Assert.AreEqual (command.Item2.Split (' ')[0], "--aot=hybrid", "First arg should be --aot=hybrid");
Assert.IsTrue (command.Item1.EndsWith (GetExpectedMonoCommand (compilerType)), "Unexpected command: " + command.Item1);
if (kind == AOTKind.Hybrid)
Assert.AreEqual (command.Item2.Split (' ')[0], "--aot=hybrid", "First arg should be --aot=hybrid");
else
Assert.AreEqual (command.Item2.Split (' ')[0], "--aot", "First arg should be --aot");
string fileName = command.Item2.Substring (command.Item2.IndexOf(' ') + 1).Replace ("\"", "");
filesAOTed.Add (fileName);
}
return filesAOTed;
}
void AssertFilesAOTed (IEnumerable <string> expectedFiles, MonoType monoType = MonoType.Bundled64)
void AssertFilesAOTed (IEnumerable <string> expectedFiles, AOTCompilerType compilerType = AOTCompilerType.Bundled64, AOTKind kind = AOTKind.Standard)
{
List<string> filesAOTed = GetFiledAOTed (monoType);
List<string> filesAOTed = GetFiledAOTed (compilerType, kind);
Func<string> getErrorDetails = () => $"\n {String.Join (" ", filesAOTed)} \nvs\n {String.Join (" ", expectedFiles)}";
@ -123,18 +131,18 @@ namespace Xamarin.MMP.Tests.Unit
[Test]
public void ParsingNone_DoesNoAOT ()
{
compiler.Parse ("none");
Assert.IsFalse (compiler.IsAOT, "Parsing none should not be IsAOT");
AssertThrowErrorWithCode (() => compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList)), 99);
var options = new AOTOptions ("none");
Assert.IsFalse (options.IsAOT, "Parsing none should not be IsAOT");
AssertThrowErrorWithCode (() => Compile (options, new TestFileEnumerator (FullAppFileList)), 99);
}
[Test]
public void All_AOTAllFiles ()
{
compiler.Parse ("all");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("all");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList));
Compile (options, new TestFileEnumerator (FullAppFileList));
var expectedFiles = FullAppFileList.Where (x => x.EndsWith (".exe") || x.EndsWith (".dll"));
AssertFilesAOTed (expectedFiles);
@ -143,10 +151,10 @@ namespace Xamarin.MMP.Tests.Unit
[Test]
public void Core_ParsingJustCoreFiles()
{
compiler.Parse ("core");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("core");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList));
Compile (options, new TestFileEnumerator (FullAppFileList));
AssertFilesAOTed (CoreXMFileList);
}
@ -154,22 +162,21 @@ namespace Xamarin.MMP.Tests.Unit
[Test]
public void SDK_ParsingJustSDKFiles()
{
compiler.Parse ("sdk");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("sdk");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList));
Compile (options, new TestFileEnumerator (FullAppFileList));
AssertFilesAOTed (SDKFileList);
}
[Test]
public void ExplicitAssembly_JustAOTExplicitFile ()
{
compiler.Parse ("+System.dll");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("+System.dll");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList));
Compile (options, new TestFileEnumerator (FullAppFileList));
AssertFilesAOTed (new string [] { "System.dll" });
}
@ -177,13 +184,13 @@ namespace Xamarin.MMP.Tests.Unit
[Test]
public void CoreWithInclusionAndSubtraction ()
{
compiler.Parse ("core,+Foo.dll,-Xamarin.Mac.dll");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("core,+Foo.dll,-Xamarin.Mac.dll");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
string [] testFiles = {
"Foo.dll", "Foo Bar.exe", "libMonoPosixHelper.dylib", "mscorlib.dll", "Xamarin.Mac.dll", "System.dll"
};
compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (testFiles));
Compile (options, new TestFileEnumerator (testFiles));
AssertFilesAOTed (new string [] { "Foo.dll", "mscorlib.dll", "System.dll" });
}
@ -191,54 +198,55 @@ namespace Xamarin.MMP.Tests.Unit
[Test]
public void CoreWithFullPath_GivesFullPathCommands ()
{
compiler.Parse ("core,-Xamarin.Mac.dll");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("core,-Xamarin.Mac.dll");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
Compile (options, new TestFileEnumerator (FullAppFileList.Select (x => TestRootDir + x)));
compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList.Select (x => TestRootDir + x)));
AssertFilesAOTed (new string [] { TestRootDir + "mscorlib.dll", TestRootDir + "System.dll" });
}
[Test]
public void ExplicitNegativeFileWithNonExistantFiles_ThrowError ()
{
compiler.Parse ("core,-NonExistant.dll");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("core,-NonExistant.dll");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
AssertThrowErrorWithCode (() => compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList)), 3010);
AssertThrowErrorWithCode (() => Compile (options, new TestFileEnumerator (FullAppFileList)), 3010);
}
[Test]
public void ExplicitPositiveFileWithNonExistantFiles_ThrowError ()
{
compiler.Parse ("core,+NonExistant.dll");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("core,+NonExistant.dll");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
AssertThrowErrorWithCode (() => compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList)), 3009);
AssertThrowErrorWithCode (() => Compile (options, new TestFileEnumerator (FullAppFileList)), 3009);
}
[Test]
public void ExplicitNegativeWithNoAssemblies_ShouldNoOp()
{
compiler.Parse ("-System.dll");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("-System.dll");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList));
Compile (options, new TestFileEnumerator (FullAppFileList));
AssertFilesAOTed (new string [] {});
}
[Test]
public void ParsingSimpleOptions_InvalidOption ()
{
AssertThrowErrorWithCode (() => compiler.Parse ("FooBar"), 20);
AssertThrowErrorWithCode (() => new AOTOptions ("FooBar"), 20);
}
[Test]
public void AssemblyWithSpaces_ShouldAOTWithQuotes ()
{
compiler.Parse ("+Foo Bar.dll");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("+Foo Bar.dll");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (new string [] { "Foo Bar.dll", "Xamarin.Mac.dll" }));
Compile (options, new TestFileEnumerator (new string [] { "Foo Bar.dll", "Xamarin.Mac.dll" }));
AssertFilesAOTed (new string [] {"Foo Bar.dll"});
Assert.IsTrue (commandsRun[0].Item2.EndsWith ("\"Foo Bar.dll\"", StringComparison.InvariantCulture), "Should end with quoted filename");
}
@ -246,25 +254,62 @@ namespace Xamarin.MMP.Tests.Unit
[Test]
public void WhenAOTFails_ShouldReturnError ()
{
compiler.RunCommand = (path, args, env, output, suppressPrintOnErrors) => 42;
compiler.Parse ("all");
AssertThrowErrorWithCode (() => compiler.Compile (MonoType.Bundled64, new TestFileEnumerator (FullAppFileList)), 3001);
RunCommandDelegate runThatErrors = (path, args, env, output, suppressPrintOnErrors) => 42;
var options = new AOTOptions ("all");
AssertThrowErrorWithCode (() => Compile (options, new TestFileEnumerator (FullAppFileList), onRunDelegate : runThatErrors), 3001);
}
[Test]
public void DifferentMonoTypes_ShouldInvokeCorrectMono ()
{
foreach (var monoType in new List<MonoType> (){ MonoType.Bundled64, MonoType.Bundled32, MonoType.System32, MonoType.System64 })
foreach (var compilerType in new List<AOTCompilerType> (){ AOTCompilerType.Bundled64, AOTCompilerType.Bundled32, AOTCompilerType.System32, AOTCompilerType.System64 })
{
ClearCommandsRun ();
compiler.Parse ("sdk");
Assert.IsTrue (compiler.IsAOT, "Should be IsAOT");
var options = new AOTOptions ("sdk");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
compiler.Compile (monoType, new TestFileEnumerator (FullAppFileList));
Compile (options, new TestFileEnumerator (FullAppFileList), compilerType);
AssertFilesAOTed (SDKFileList, monoType);
AssertFilesAOTed (SDKFileList, compilerType);
}
}
[Test]
public void PipeFileName_ShouldNotHybridCompiler ()
{
foreach (var testCase in new string [] { "+|hybrid.dll", "core,+|hybrid.dll,-Xamarin.Mac.dll" }){
ClearCommandsRun ();
var options = new AOTOptions (testCase);
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
Assert.IsFalse (options.IsHybridAOT, "Should not be IsHybridAOT");
Compile (options, new TestFileEnumerator (new string [] { "|hybrid.dll", "Xamarin.Mac.dll" }));
AssertFilesAOTed (new string [] {"|hybrid.dll"});
}
}
[Test]
public void InvalidHybridOptions_ShouldThrow ()
{
AssertThrowErrorWithCode (() => new AOTOptions ("|"), 20);
AssertThrowErrorWithCode (() => new AOTOptions ("|hybrid"), 20);
AssertThrowErrorWithCode (() => new AOTOptions ("core|"), 20);
AssertThrowErrorWithCode (() => new AOTOptions ("foo|hybrid"), 20);
AssertThrowErrorWithCode (() => new AOTOptions ("core|foo"), 20);
AssertThrowErrorWithCode (() => new AOTOptions ("|hybrid,+Foo.dll"), 20);
}
[Test]
public void HybridOption_ShouldInvokeHybridCompiler ()
{
var options = new AOTOptions ("sdk|hybrid");
Assert.IsTrue (options.IsAOT, "Should be IsAOT");
Assert.IsTrue (options.IsHybridAOT, "Should be IsHybridAOT");
Compile (options, new TestFileEnumerator (FullAppFileList));
AssertFilesAOTed (SDKFileList, kind : AOTKind.Hybrid);
}
}
}