예제 #1
0
        public void BuildBasicApplicationReleaseWithCustomAotProfile()
        {
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
                AndroidEnableProfiledAot = true,
            };

            proj.SetProperty(proj.ActiveConfigurationProperties, "AndroidExtraAotOptions", "--verbose");

            byte [] custom_aot_profile;
            using (var stream = typeof(XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream("Xamarin.ProjectTools.Resources.Base.custom.aotprofile")) {
                custom_aot_profile = new byte [stream.Length];
                stream.Read(custom_aot_profile, 0, (int)stream.Length);
            }
            proj.OtherBuildItems.Add(new BuildItem("AndroidAotProfile", "custom.aotprofile")
            {
                BinaryContent = () => custom_aot_profile
            });

            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Using profile data file.*custom\.aotprofile", b.LastBuildOutput, "Should use custom AOT profile", RegexOptions.IgnoreCase);
                StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Method.*emitted at", b.LastBuildOutput, "Should contain verbose AOT compiler output", RegexOptions.IgnoreCase);
            }
        }
예제 #2
0
        public void BuildBasicApplicationReleaseProfiledAot()
        {
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
                AndroidEnableProfiledAot = true,
            };

            proj.SetProperty(proj.ActiveConfigurationProperties, "AndroidExtraAotOptions", "--verbose");
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Using profile data file.*build.Xamarin.Android.startup\.aotprofile", b.LastBuildOutput, "Should use default AOT profile", RegexOptions.IgnoreCase);
                StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Method.*emitted at", b.LastBuildOutput, "Should contain verbose AOT compiler output", RegexOptions.IgnoreCase);
            }
        }
예제 #3
0
        public void BuildAotApplicationAndÜmläüts(string supportedAbis, bool enableLLVM, bool expectedResult)
        {
            var path = Path.Combine("temp", string.Format("BuildAotApplication AndÜmläüts_{0}_{1}_{2}", supportedAbis, enableLLVM, expectedResult));
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease        = true,
                BundleAssemblies = false,
                AotAssemblies    = true,
            };

            proj.SetProperty(KnownProperties.TargetFrameworkVersion, "v5.1");
            proj.SetAndroidSupportedAbis(supportedAbis);
            proj.SetProperty("EnableLLVM", enableLLVM.ToString());
            bool checkMinLlvmPath = enableLLVM && (supportedAbis == "armeabi-v7a" || supportedAbis == "x86");

            if (checkMinLlvmPath)
            {
                // Set //uses-sdk/@android:minSdkVersion so that LLVM uses the right libc.so
                proj.AndroidManifest = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""{proj.PackageName}"">
	<uses-sdk android:minSdkVersion=""{Xamarin.Android.Tools.XABuildConfig.NDKMinimumApiAvailable}"" />
	<application android:label=""{proj.ProjectName}"">
	</application>
</manifest>";
            }
            using (var b = CreateApkBuilder(path)) {
                if (!b.CrossCompilerAvailable(supportedAbis))
                {
                    Assert.Ignore($"Cross compiler for {supportedAbis} was not available");
                }
                if (!b.GetSupportedRuntimes().Any(x => supportedAbis == x.Abi))
                {
                    Assert.Ignore($"Runtime for {supportedAbis} was not available.");
                }
                b.ThrowOnBuildFailure = false;
                Assert.AreEqual(expectedResult, b.Build(proj), "Build should have {0}.", expectedResult ? "succeeded" : "failed");
                if (!expectedResult)
                {
                    return;
                }
                //NOTE: Windows has shortened paths such as: C:\Users\myuser\ANDROI~3\ndk\PLATFO~1\AN3971~1\arch-x86\usr\lib\libc.so
                if (checkMinLlvmPath && !IsWindows)
                {
                    bool ndk22OrNewer = false;
                    if (Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainRelease(AndroidNdkPath, out Xamarin.Android.Tasks.NdkUtilOld.NdkVersion ndkVersion))
                    {
                        ndk22OrNewer = ndkVersion.Version >= 22;
                    }

                    // LLVM passes a direct path to libc.so, and we need to use the libc.so
                    // which corresponds to the *minimum* SDK version specified in AndroidManifest.xml
                    // Since we overrode minSdkVersion=16, that means we should use libc.so from android-16.
                    if (ndk22OrNewer)
                    {
                        // NDK r22 or newer store libc in [toolchain]/sysroot/usr/lib/[ARCH]/[API]/libc.so
                        StringAssertEx.ContainsRegex(@"\s*\[aot-compiler stdout].*sysroot.*.usr.lib.*16.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!");
                    }
                    else
                    {
                        StringAssertEx.ContainsRegex(@"\s*\[aot-compiler stdout].*android-16.arch-.*.usr.lib.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!");
                    }
                }
                foreach (var abi in supportedAbis.Split(new char [] { ';' }))
                {
                    var libapp = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath,
                                              "bundles", abi, "libmonodroid_bundle_app.so");
                    Assert.IsFalse(File.Exists(libapp), abi + " libmonodroid_bundle_app.so should not exist");
                    var assemblies = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath,
                                                  "aot", abi, "libaot-UnnamedProject.dll.so");
                    Assert.IsTrue(File.Exists(assemblies), "{0} libaot-UnnamedProject.dll.so does not exist", abi);
                    var apk = Path.Combine(Root, b.ProjectDirectory,
                                           proj.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk");
                    using (var zipFile = ZipHelper.OpenZip(apk)) {
                        Assert.IsNotNull(ZipHelper.ReadFileFromZip(zipFile,
                                                                   string.Format("lib/{0}/libaot-UnnamedProject.dll.so", abi)),
                                         "lib/{0}/libaot-UnnamedProject.dll.so should be in the UnnamedProject.UnnamedProject.apk", abi);
                        Assert.IsNotNull(ZipHelper.ReadFileFromZip(zipFile,
                                                                   "assemblies/UnnamedProject.dll"),
                                         "UnnamedProject.dll should be in the UnnamedProject.UnnamedProject.apk");
                    }
                }
                Assert.AreEqual(expectedResult, b.Build(proj), "Second Build should have {0}.", expectedResult ? "succeeded" : "failed");
                Assert.IsTrue(
                    b.Output.IsTargetSkipped("_CompileJava"),
                    "the _CompileJava target should be skipped");
                Assert.IsTrue(
                    b.Output.IsTargetSkipped("_BuildApkEmbed"),
                    "the _BuildApkEmbed target should be skipped");
            }
        }
예제 #4
0
        public void ApplicationRunsWithDebuggerAndBreaks(bool embedAssemblies, string fastDevType, bool allowDeltaInstall, string username)
        {
            AssertCommercialBuild();
            AssertHasDevices();

            var           path       = Path.Combine("temp", TestName);
            int           userId     = GetUserId(username);
            List <string> parameters = new List <string> ();

            if (userId >= 0)
            {
                parameters.Add($"AndroidDeviceUserId={userId}");
            }
            if (SwitchUser(username))
            {
                WaitFor(5);
                ClickButton("", "android:id/button1", "Yes continue");
            }

            var lib = new XamarinAndroidLibraryProject {
                ProjectName = "Library1",
                Sources     =
                {
                    new BuildItem.Source("Foo.cs")
                    {
                        TextContent = () =>
                                      @"public class Foo
{
	public Foo ()
	{
	}
}"
                    },
                },
            };

            var app = new XamarinFormsAndroidApplicationProject {
                ProjectName               = "App",
                IsRelease                 = false,
                EmbedAssembliesIntoApk    = embedAssemblies,
                AndroidFastDeploymentType = fastDevType
            };

            app.MainPage = app.MainPage.Replace("InitializeComponent ();", "InitializeComponent (); new Foo ();");
            app.AddReference(lib);
            app.SetAndroidSupportedAbis("armeabi-v7a", "x86");
            app.SetProperty(KnownProperties._AndroidAllowDeltaInstall, allowDeltaInstall.ToString());
            app.SetDefaultTargetDevice();
            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName)))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.True(libBuilder.Build(lib), "Library should have built.");

                    SetTargetFrameworkAndManifest(app, appBuilder);
                    Assert.True(appBuilder.Install(app, parameters: parameters.ToArray()), "App should have installed.");

                    if (!embedAssemblies)
                    {
                        // Check that we deployed .pdb files
                        StringAssertEx.ContainsRegex($@"NotifySync CopyFile.+{app.ProjectName}\.pdb", appBuilder.LastBuildOutput,
                                                     $"{app.ProjectName}.pdb should be deployed!");
                        StringAssertEx.ContainsRegex($@"NotifySync CopyFile.+{lib.ProjectName}\.pdb", appBuilder.LastBuildOutput,
                                                     $"{lib.ProjectName}.pdb should be deployed!");
                    }

                    int breakcountHitCount      = 0;
                    ManualResetEvent resetEvent = new ManualResetEvent(false);
                    var sw = new Stopwatch();
                    // setup the debugger
                    var session = new SoftDebuggerSession();
                    session.Breakpoints = new BreakpointStore {
                        { Path.Combine(Root, appBuilder.ProjectDirectory, "MainActivity.cs"), 20 },
                        { Path.Combine(Root, appBuilder.ProjectDirectory, "MainPage.xaml.cs"), 14 },
                        { Path.Combine(Root, appBuilder.ProjectDirectory, "MainPage.xaml.cs"), 19 },
                        { Path.Combine(Root, appBuilder.ProjectDirectory, "App.xaml.cs"), 12 },
                        { Path.Combine(Root, libBuilder.ProjectDirectory, "Foo.cs"), 4 },
                    };
                    session.TargetHitBreakpoint += (sender, e) => {
                        TestContext.WriteLine($"BREAK {e.Type}, {e.Backtrace.GetFrame (0)}");
                        breakcountHitCount++;
                        session.Continue();
                    };
                    var rnd  = new Random();
                    int port = rnd.Next(10000, 20000);
                    TestContext.Out.WriteLine($"{port}");
                    var args = new SoftDebuggerConnectArgs("", IPAddress.Loopback, port)
                    {
                        MaxConnectionAttempts = 10,
                    };
                    var startInfo = new SoftDebuggerStartInfo(args)
                    {
                        WorkingDirectory = Path.Combine(appBuilder.ProjectDirectory, app.IntermediateOutputPath, "android", "assets"),
                    };
                    var options = new DebuggerSessionOptions()
                    {
                        EvaluationOptions = EvaluationOptions.DefaultOptions,
                    };
                    options.EvaluationOptions.UseExternalTypeResolver = true;
                    ClearAdbLogcat();
                    appBuilder.BuildLogFile = "run.log";

                    parameters.Add($"AndroidSdbTargetPort={port}");
                    parameters.Add($"AndroidSdbHostPort={port}");
                    parameters.Add("AndroidAttachDebugger=True");

                    Assert.True(appBuilder.RunTarget(app, "_Run", doNotCleanupOnUpdate: true,
                                                     parameters: parameters.ToArray()), "Project should have run.");

                    Assert.IsTrue(WaitForDebuggerToStart(Path.Combine(Root, appBuilder.ProjectDirectory, "logcat.log")), "Activity should have started");
                    // we need to give a bit of time for the debug server to start up.
                    WaitFor(2000);
                    session.LogWriter    += (isStderr, text) => { Console.WriteLine(text); };
                    session.OutputWriter += (isStderr, text) => { Console.WriteLine(text); };
                    session.DebugWriter  += (level, category, message) => { Console.WriteLine(message); };
                    session.Run(startInfo, options);
                    WaitFor(TimeSpan.FromSeconds(30), () => session.IsConnected);
                    Assert.True(session.IsConnected, "Debugger should have connected but it did not.");
                    // we need to wait here for a while to allow the breakpoints to hit
                    // but we need to timeout
                    TimeSpan timeout  = TimeSpan.FromSeconds(60);
                    int      expected = 4;
                    while (session.IsConnected && breakcountHitCount < 3 && timeout >= TimeSpan.Zero)
                    {
                        Thread.Sleep(10);
                        timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10));
                    }
                    WaitFor(2000);
                    Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}");
                    breakcountHitCount = 0;
                    ClearAdbLogcat();
                    ClickButton(app.PackageName, "myXFButton", "CLICK ME");
                    while (session.IsConnected && breakcountHitCount < 1 && timeout >= TimeSpan.Zero)
                    {
                        Thread.Sleep(10);
                        timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10));
                    }
                    expected = 1;
                    Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}");
                    appBuilder.BuildLogFile = "uninstall.log";
                    Assert.True(appBuilder.Uninstall(app), "Project should have uninstalled.");
                    session.Exit();
                }
        }