diff --git a/src/generate-frameworks-constants/generate-frameworks-constants.csproj b/src/generate-frameworks-constants/generate-frameworks-constants.csproj index d0edfe68ae..43e3b74d91 100644 --- a/src/generate-frameworks-constants/generate-frameworks-constants.csproj +++ b/src/generate-frameworks-constants/generate-frameworks-constants.csproj @@ -9,6 +9,7 @@ generate-frameworks-constants v4.7.2 bin\$(Configuration) + default true diff --git a/tests/mtouch/Cache.cs b/tests/mtouch/Cache.cs index 75e6fd655f..5ce3bfa21c 100644 --- a/tests/mtouch/Cache.cs +++ b/tests/mtouch/Cache.cs @@ -4,6 +4,8 @@ using System.IO; using System.Runtime.InteropServices; using System.Threading; +#nullable disable + namespace Xamarin { // A class that creates temporary directories next to the test assembly, and cleans the output on startup diff --git a/tools/common/Execution.cs b/tools/common/Execution.cs index 040bdb79f0..472ad106df 100644 --- a/tools/common/Execution.cs +++ b/tools/common/Execution.cs @@ -16,6 +16,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +#nullable disable + namespace Xamarin.Utils { public class Execution { public string FileName; diff --git a/tools/common/StringUtils.cs b/tools/common/StringUtils.cs index baf9fef5df..8b09d49131 100644 --- a/tools/common/StringUtils.cs +++ b/tools/common/StringUtils.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; +#nullable disable + namespace Xamarin.Utils { internal class StringUtils { static StringUtils () diff --git a/tools/nnyeah/nnyeah.sln b/tools/nnyeah/nnyeah.sln index 0aa4738a49..0e798d57cb 100644 --- a/tools/nnyeah/nnyeah.sln +++ b/tools/nnyeah/nnyeah.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.810.18 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nnyeah", "nnyeah\nnyeah.csproj", "{772B2205-5CFA-41A0-ACB5-A98301BC86FD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nnyeah-tests", "tests\nnyeah-tests.csproj", "{0CDCFD15-98C0-4669-A00B-E5287086D606}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {772B2205-5CFA-41A0-ACB5-A98301BC86FD}.Debug|Any CPU.Build.0 = Debug|Any CPU {772B2205-5CFA-41A0-ACB5-A98301BC86FD}.Release|Any CPU.ActiveCfg = Release|Any CPU {772B2205-5CFA-41A0-ACB5-A98301BC86FD}.Release|Any CPU.Build.0 = Release|Any CPU + {0CDCFD15-98C0-4669-A00B-E5287086D606}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CDCFD15-98C0-4669-A00B-E5287086D606}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CDCFD15-98C0-4669-A00B-E5287086D606}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CDCFD15-98C0-4669-A00B-E5287086D606}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/tools/nnyeah/tests/CompileALibrary.cs b/tools/nnyeah/tests/CompileALibrary.cs new file mode 100644 index 0000000000..41ac1e669c --- /dev/null +++ b/tools/nnyeah/tests/CompileALibrary.cs @@ -0,0 +1,32 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using NUnit.Framework; + +using Xamarin; + +namespace Microsoft.MaciOS.Nnyeah.Tests.SmokeTests { + [TestFixture] + public class CompileALibrary { + [Test] + public async Task BasicLibrary () + { + var dir = Cache.CreateTemporaryDirectory ("BasicLibrary"); + var code = @" +using System; +public class Foo { + public nint Ident (nint e) => e; +} +"; + var output = await TestRunning.BuildLibrary (code, "NoName", dir); + var expectedOutputFile = Path.Combine (dir, "NoName.dll"); + Assert.IsTrue (File.Exists (expectedOutputFile)); + } + + [Test] + public void BasicExecutable () + { + var dir = Cache.CreateTemporaryDirectory ("BasicExecutable"); + } + } +} diff --git a/tools/nnyeah/tests/nnyeah-tests.csproj b/tools/nnyeah/tests/nnyeah-tests.csproj new file mode 100644 index 0000000000..fb76a5e54e --- /dev/null +++ b/tools/nnyeah/tests/nnyeah-tests.csproj @@ -0,0 +1,23 @@ + + + + net6.0 + enable + + false + + + + + + + + + + + + + + + + diff --git a/tools/nnyeah/tests/utils/Compiler.cs b/tools/nnyeah/tests/utils/Compiler.cs new file mode 100644 index 0000000000..34548f277b --- /dev/null +++ b/tools/nnyeah/tests/utils/Compiler.cs @@ -0,0 +1,88 @@ +using System; +using System.Text; +using System.IO; +using System.Threading.Tasks; + +using Xamarin; +using Xamarin.Utils; +using System.Collections.Generic; + +namespace Microsoft.MaciOS.Nnyeah.Tests { + + public enum PlatformName { + None, // desktop managed executable + macOS, // Xamarin.Mac app + iOS, + watchOS, + tvOS, + } + + public class Compiler { + const string MonoCompiler = "/Library/Frameworks/Mono.framework/Versions/Current/Commands/csc"; + + public static async Task CompileText (string text, string outputFile, PlatformName platformName, bool isLibrary) + { + var dir = Cache.CreateTemporaryDirectory (); + var outputCSFile = Path.Combine (dir, "LibraryFile.cs"); + File.WriteAllText (outputCSFile, text); + return await Compile (outputFile, platformName, isLibrary, dir, outputCSFile); + } + + public static async Task Compile (string outputFile, PlatformName platformName, bool isLibrary, string workingDirectory, params string[] sourceFiles) + { + var compilerArgs = BuildCompilerArgs (sourceFiles, outputFile, platformName, isLibrary); + Execution execution = await Execution.RunAsync(MonoCompiler, compilerArgs, mergeOutput: true, workingDirectory: workingDirectory); + return execution!.StandardOutput.ToString()!; + } + + static List BuildCompilerArgs (string[] sourceFiles, string outputFile, PlatformName platformName, + bool isLibrary) + { + var args = new List(); + + args.Add ("/unsafe"); + args.Add ("/nostdlib+"); + AppendPlatformReference (args, platformName, "mscorlib"); + AppendPlatformReference (args, platformName, XamarinLibName (platformName)); + args.Add ("/debug+"); + args.Add ("/debug:full"); + args.Add ("/optimize-"); + args.Add ("/out:" + outputFile); + args.Add ("/target:" + (isLibrary ? "library" : "exe")); + + foreach (var file in sourceFiles) { + args.Add (file); + } + + return args; + } + + static void AppendPlatformReference (List args, PlatformName platformName, string libName) + { + args.Add("/reference:" + PlatformLibPath (platformName, libName)); + } + + static string PlatformLibPath (PlatformName platformName, string libName) + { + return Path.Combine (PlatformLibDirectory (platformName), $"{libName}.dll"); + } + + static string PlatformLibDirectory (PlatformName platformName) => + platformName switch { + PlatformName.macOS => "/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/Xamarin.Mac/", + PlatformName.iOS => "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.iOS", + PlatformName.tvOS => "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.TVOS", + PlatformName.watchOS => "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.WatchOS", + _ => throw new NotImplementedException (), + }; + + static string XamarinLibName (PlatformName platformName) => + platformName switch { + PlatformName.macOS => "Xamarin.Mac", + PlatformName.iOS => "Xamarin.iOS", + PlatformName.tvOS => "Xamarin.TVOS", + PlatformName.watchOS => "Xamarin.WatchOS", + _ => throw new NotImplementedException (), + }; + } +} diff --git a/tools/nnyeah/tests/utils/TestRunning.cs b/tools/nnyeah/tests/utils/TestRunning.cs new file mode 100644 index 0000000000..94a86d50f1 --- /dev/null +++ b/tools/nnyeah/tests/utils/TestRunning.cs @@ -0,0 +1,46 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +using NUnit.Framework; + +using Xamarin; + +namespace Microsoft.MaciOS.Nnyeah.Tests { + public class TestRunning { + static string GetInvokingTestName (out string callingMethodClass, string callingMethodName) + { + var stackTrace = new System.Diagnostics.StackTrace (); + var callingMethod = stackTrace.GetFrame (2)!.GetMethod (); + Assert.NotNull (callingMethod, "unable to get calling test from stack frame."); + + if (string.IsNullOrEmpty (callingMethodName)) { + if (!callingMethod!.CustomAttributes.Any (x => x.AttributeType.Name == "TestAttribute")) { + Assert.Fail ("TestRunning expect invocations without an explicit `testName` parameter to be invoked from the [Test] method directly. Consider passing an explicit `testName`."); + } + callingMethodName = callingMethod.Name; + } + callingMethodClass = callingMethod!.DeclaringType!.Name; + return callingMethodName; + } + + public static async Task TestAndExecute (string libraryCode, string callingCode, string expectedOutput, + string callingMethodName = "") + { + var testName = GetInvokingTestName (out var nameSpace, callingMethodName); + var testClassName = "NnyeahTest" + testName; + + var initialLibraryDir = Cache.CreateTemporaryDirectory (); + var finalLibraryDir = Cache.CreateTemporaryDirectory (); + + var libCompilerOutput = await BuildLibrary (libraryCode, testName, initialLibraryDir); + } + + public static Task BuildLibrary (string libraryCode, string libName, string outputDirectory, PlatformName platformName = PlatformName.macOS) + { + var outputPath = Path.Combine (outputDirectory, $"{libName}.dll"); + return Compiler.CompileText (libraryCode, outputPath, platformName, isLibrary: true); + } + } +} diff --git a/tools/xibuild/xibuild.csproj b/tools/xibuild/xibuild.csproj index af31fa4889..70e07f2f60 100644 --- a/tools/xibuild/xibuild.csproj +++ b/tools/xibuild/xibuild.csproj @@ -8,6 +8,7 @@ xibuild xibuild v4.7 + default true