Exemple #1
0
        public void BeforeDeploymentTests()
        {
            if (!HasDevices)
            {
                Assert.Ignore("Skipping Test. No devices available.");
            }
            string debuggable = RunAdbCommand("shell getprop ro.debuggable");

            if (debuggable != "1")
            {
                Assert.Ignore("TimeZone tests need to use `su root` and this device does not support that feature. Try using an emulator.");
            }

            proj = new XamarinFormsAndroidApplicationProject();
            proj.SetProperty(KnownProperties.AndroidSupportedAbis, "armeabi-v7a;x86");
            var mainPage = proj.Sources.First(x => x.Include() == "MainPage.xaml.cs");
            var source   = mainPage.TextContent().Replace("InitializeComponent ();", @"InitializeComponent ();
			Console.WriteLine ($""TimeZoneInfo={TimeZoneInfo.Local.DisplayName}"");
");

            mainPage.TextContent = () => source;
            builder = CreateApkBuilder(Path.Combine("temp", "DeploymentTests"));
            string apiLevel;

            proj.TargetFrameworkVersion = builder.LatestTargetFrameworkVersion(out apiLevel);
            proj.PackageName            = "Xamarin.TimeZoneTest";
            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=""Xamarin.TimeZoneTest"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest> ";
            Assert.IsTrue(builder.Build(proj), "Build should have succeeded.");
            Assert.IsTrue(builder.Install(proj), "Install should have succeeded.");
        }
Exemple #2
0
        public void SetupDependenciesForDesigner()
        {
            var path = Path.Combine("temp", TestName);
            var lib  = new XamarinAndroidLibraryProject {
                ProjectName     = "Library1",
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset("Assets\\foo.txt")
                    {
                        TextContent = () => "Bar",
                    },
                },
            };
            var proj = new XamarinFormsAndroidApplicationProject {
                ProjectName = "App1",
                References  = { new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj") },
            };

            using (var libb = CreateDllBuilder(Path.Combine(path, lib.ProjectName)))
                using (var appb = CreateApkBuilder(Path.Combine(path, proj.ProjectName))) {
                    libb.Save(lib);
                    Assert.IsTrue(appb.RunTarget(proj, "SetupDependenciesForDesigner", parameters: new [] { "DesignTimeBuild=True" }), "design-time build should have succeeded.");
                    //Now a full build
                    Assert.IsTrue(libb.Build(lib), "library build should have succeeded.");
                    Assert.IsTrue(appb.Build(proj), "app build should have succeeded.");
                }
        }
Exemple #3
0
        public void ApplicationRunsWithoutDebugger([Values(false, true)] bool isRelease, [Values(false, true)] bool extractNativeLibs)
        {
            AssertHasDevices();

            var proj = new XamarinFormsAndroidApplicationProject()
            {
                IsRelease = isRelease,
            };

            if (isRelease || !CommercialBuildAvailable)
            {
                proj.SetAndroidSupportedAbis("armeabi-v7a", "x86");
            }
            proj.SetDefaultTargetDevice();
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                SetTargetFrameworkAndManifest(proj, b);
                proj.AndroidManifest = proj.AndroidManifest.Replace("<application ", $"<application android:extractNativeLibs=\"{extractNativeLibs.ToString ().ToLowerInvariant ()}\" ");
                Assert.True(b.Install(proj), "Project should have installed.");
                var manifest = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "AndroidManifest.xml");
                AssertExtractNativeLibs(manifest, extractNativeLibs);
                ClearAdbLogcat();
                if (CommercialBuildAvailable)
                {
                    Assert.True(b.RunTarget(proj, "_Run"), "Project should have run.");
                }
                else
                {
                    AdbStartActivity($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity");
                }

                Assert.True(WaitForActivityToStart(proj.PackageName, "MainActivity",
                                                   Path.Combine(Root, b.ProjectDirectory, "logcat.log"), 30), "Activity should have started.");
                Assert.True(b.Uninstall(proj), "Project should have uninstalled.");
            }
        }
        public void ApplicationRunsWithoutDebugger([Values(false, true)] bool isRelease)
        {
            AssertHasDevices();

            var proj = new XamarinFormsAndroidApplicationProject()
            {
                IsRelease = isRelease,
            };

            if (isRelease || !CommercialBuildAvailable)
            {
                var abis = new string [] { "armeabi-v7a", "x86" };
                proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            }
            proj.SetDefaultTargetDevice();
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                SetTargetFrameworkAndManifest(proj, b);
                Assert.True(b.Install(proj), "Project should have installed.");
                ClearAdbLogcat();
                if (CommercialBuildAvailable)
                {
                    Assert.True(b.RunTarget(proj, "_Run"), "Project should have run.");
                }
                else
                {
                    AdbStartActivity($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity");
                }

                Assert.True(WaitForActivityToStart(proj.PackageName, "MainActivity",
                                                   Path.Combine(Root, b.ProjectDirectory, "logcat.log"), 30), "Activity should have started.");
                Assert.True(b.Uninstall(proj), "Project should have uninstalled.");
            }
        }
        public void CheckNothingIsDeletedByIncrementalClean([Values(true, false)] bool enableMultiDex, [Values(true, false)] bool useAapt2)
        {
            // do a release build
            // change one of the properties (say AotAssemblies)
            // do another build. it should NOT hose the resource directory.
            var path = Path.Combine("temp", TestName);
            var proj = new XamarinFormsAndroidApplicationProject()
            {
                ProjectName = "App1",
                IsRelease   = true,
            };

            if (enableMultiDex)
            {
                proj.SetProperty("AndroidEnableMultiDex", "True");
            }
            if (useAapt2)
            {
                proj.SetProperty("AndroidUseAapt2", "True");
            }
            using (var b = CreateApkBuilder(path)) {
                Assert.IsTrue(b.Build(proj), "First should have succeeded");
                IEnumerable <string> files = Directory.EnumerateFiles(Path.Combine(Root, path, proj.IntermediateOutputPath), "*.*", SearchOption.AllDirectories);
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, parameters: null, saveProject: false), "Second should have succeeded");
                foreach (var file in files)
                {
                    FileAssert.Exists(file, $"{file} should not have been deleted!");
                }
            }
        }
        public void CheckNothingIsDeletedByIncrementalClean([Values(true, false)] bool enableMultiDex, [Values(true, false)] bool useAapt2)
        {
            var path = Path.Combine("temp", TestName);
            var proj = new XamarinFormsAndroidApplicationProject()
            {
                ProjectName = "App1",
                IsRelease   = true,
            };

            if (enableMultiDex)
            {
                proj.SetProperty("AndroidEnableMultiDex", "True");
            }
            if (useAapt2)
            {
                proj.SetProperty("AndroidUseAapt2", "True");
            }
            using (var b = CreateApkBuilder(path)) {
                //To be sure we are at a clean state
                var projectDir = Path.Combine(Root, b.ProjectDirectory);
                if (Directory.Exists(projectDir))
                {
                    Directory.Delete(projectDir, true);
                }

                Assert.IsTrue(b.Build(proj), "First should have succeeded");
                var intermediate = Path.Combine(projectDir, proj.IntermediateOutputPath);
                var output       = Path.Combine(projectDir, proj.OutputPath);
                var fileWrites   = Path.Combine(intermediate, $"{proj.ProjectName}.csproj.FileListAbsolute.txt");
                FileAssert.Exists(fileWrites);
                var expected = File.ReadAllText(fileWrites);
                var files    = Directory.EnumerateFiles(intermediate, "*", SearchOption.AllDirectories).ToList();
                files.AddRange(Directory.EnumerateFiles(output, "*", SearchOption.AllDirectories));

                //Touch a few files, do an incremental build
                var filesToTouch = new [] {
                    Path.Combine(intermediate, "build.props"),
                    Path.Combine(intermediate, $"{proj.ProjectName}.pdb"),
                };
                foreach (var file in filesToTouch)
                {
                    FileAssert.Exists(file);
                    File.SetLastWriteTimeUtc(file, DateTime.UtcNow);
                    File.SetLastAccessTimeUtc(file, DateTime.UtcNow);
                }
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "Second should have succeeded");

                //No changes
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "Third should have succeeded");
                Assert.IsFalse(b.Output.IsTargetSkipped("IncrementalClean"), "`IncrementalClean` should have run!");
                foreach (var file in files)
                {
                    FileAssert.Exists(file, $"{file} should not have been deleted!");
                }
                FileAssert.Exists(fileWrites);
                var actual = File.ReadAllText(fileWrites);
                Assert.AreEqual(expected, actual, $"`{fileWrites}` has changes!");
            }
        }
Exemple #7
0
        public void DesignerBeforeNuGetRestore()
        {
            var path       = Path.Combine("temp", TestName);
            var parameters = new [] { "DesignTimeBuild=True", "AndroidUseManagedDesignTimeResourceGenerator=False" };
            var lib        = new XamarinAndroidLibraryProject {
                ProjectName = "Library1",
                Sources     =
                {
                    new BuildItem.Source("Foo.cs")
                    {
                        TextContent = () => "public class Foo { }",
                    }
                },
            };
            var proj = new XamarinFormsAndroidApplicationProject {
                ProjectName = "App1",
                References  = { new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj") },
                Sources     =
                {
                    new BuildItem.Source("Bar.cs")
                    {
                        TextContent = () => "public class Bar : Foo { }",
                    }
                },
            };

            var dir = Path.Combine(Root, path);

            if (Directory.Exists(dir))
            {
                Directory.Delete(dir, recursive: true);
            }

            using (var libb = CreateDllBuilder(Path.Combine(path, lib.ProjectName), false, false))
                using (var appb = CreateApkBuilder(Path.Combine(path, proj.ProjectName), false, false)) {
                    libb.AutomaticNuGetRestore     =
                        appb.AutomaticNuGetRestore = false;
                    // Save the library project, but don't build it yet
                    libb.Save(lib);
                    appb.Target = "SetupDependenciesForDesigner";
                    Assert.IsTrue(appb.Build(proj, parameters: parameters), "first build should have succeeded");

                    var packageManagerPath = Path.Combine(Root, appb.ProjectDirectory, proj.IntermediateOutputPath, "android", "src", "mono", "MonoPackageManager.java");
                    var before             = GetAssembliesFromPackageManager(packageManagerPath);
                    Assert.AreEqual("", before, $"After first `{appb.Target}`, assemblies list would be empty.");

                    libb.AutomaticNuGetRestore     =
                        appb.AutomaticNuGetRestore = true;
                    Assert.IsTrue(appb.Build(proj, parameters: parameters), "second build should have succeeded");

                    var after = GetAssembliesFromPackageManager(packageManagerPath);
                    Assert.AreNotEqual(before, after, $"After second `{appb.Target}`, assemblies list should *not* be empty.");
                    foreach (var assembly in new [] { "Xamarin.Forms.Core.dll", "Xamarin.Forms.Platform.Android.dll" })
                    {
                        StringAssert.Contains(assembly, after);
                    }
                }
        }
        public void ApplicationRunsWithoutDebugger([Values(false, true)] bool isRelease)
        {
            if (!HasDevices)
            {
                Assert.Ignore("Test needs a device attached.");
                return;
            }

            var proj = new XamarinFormsAndroidApplicationProject()
            {
                IsRelease = isRelease,
            };

            if (isRelease || !CommercialBuildAvailable)
            {
                var abis = new string [] { "armeabi-v7a", "x86" };
                proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            }
            proj.SetDefaultTargetDevice();
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                string apiLevel;
                proj.TargetFrameworkVersion = b.LatestTargetFrameworkVersion(out apiLevel);
                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=""UnnamedProject.UnnamedProject"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest>";
                b.Save(proj, saveProject: true);
                proj.NuGetRestore(Path.Combine(Root, b.ProjectDirectory), b.PackagesDirectory);
                Assert.True(b.Build(proj), "Project should have built.");
                Assert.True(b.Install(proj), "Project should have installed.");
                ClearAdbLogcat();
                if (CommercialBuildAvailable)
                {
                    Assert.True(b.RunTarget(proj, "_Run"), "Project should have run.");
                }
                else
                {
                    AdbStartActivity($"{proj.PackageName}/md52d9cf6333b8e95e8683a477bc589eda5.MainActivity");
                }

                string logcatPath       = Path.Combine(XABuildPaths.TestOutputDirectory, b.ProjectDirectory, "logcat.log");
                bool   didActivityStart = WaitForActivityToStart(proj.PackageName, "MainActivity", output: out string logcatOutput, timeout: 30);
                File.WriteAllText(logcatPath, logcatOutput);
                Assert.True(didActivityStart, "Activity should have started.");
                Assert.True(b.Uninstall(proj), "Project should have uninstalled.");
            }
        }
Exemple #9
0
        public void BeforeDeploymentTests()
        {
            AssertHasDevices();

            string debuggable = RunAdbCommand("shell getprop ro.debuggable");

            if (debuggable != "1")
            {
                Assert.Ignore("TimeZone tests need to use `su root` and this device does not support that feature. Try using an emulator.");
            }
            // Disable auto timezone
            RunAdbCommand("shell settings put global auto_time_zone 0");

            proj = new XamarinFormsAndroidApplicationProject();
            proj.SetAndroidSupportedAbis("armeabi-v7a", "x86");
            var mainPage = proj.Sources.First(x => x.Include() == "MainPage.xaml.cs");
            var source   = mainPage.TextContent().Replace("InitializeComponent ();", @"InitializeComponent ();
			Console.WriteLine ($""TimeZoneInfoNative={Java.Util.TimeZone.Default.ID}"");
			Console.WriteLine ($""TimeZoneInfo={TimeZoneInfo.Local.DisplayName}"");
");

            source = source.Replace("Console.WriteLine (\"Button was Clicked!\");", @"Console.WriteLine (""Button was Clicked!"");
			Console.WriteLine ($""TimeZoneInfoClick={TimeZoneInfo.Local.DisplayName}"");
");
            mainPage.TextContent = () => source;
            builder = CreateApkBuilder(Path.Combine("temp", "DeploymentTests"));
            string apiLevel;

            proj.TargetFrameworkVersion = builder.LatestTargetFrameworkVersion(out apiLevel);

            // TODO: We aren't sure how to support preview bindings in .NET6 yet.
            if (Builder.UseDotNet && apiLevel == "31")
            {
                apiLevel = "30";
                proj.TargetFrameworkVersion = "v11.0";
            }

            proj.PackageName     = "Xamarin.TimeZoneTest";
            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=""Xamarin.TimeZoneTest"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest> ";
            Assert.IsTrue(builder.Build(proj), "Build should have succeeded.");
            Assert.IsTrue(builder.Install(proj), "Install should have succeeded.");
        }
Exemple #10
0
        public void AppProjectTargetsDoNotBreak()
        {
            var targets = new [] {
                "_CopyIntermediateAssemblies",
                "_GeneratePackageManagerJava",
                "_ResolveLibraryProjectImports",
                "_BuildAdditionalResourcesCache",
                "_CleanIntermediateIfNuGetsChange",
            };
            var proj = new XamarinFormsAndroidApplicationProject();

            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "first build should succeed");
                foreach (var target in targets)
                {
                    Assert.IsFalse(b.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped!");
                }

                var intermediate = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath);
                var filesToTouch = new [] {
                    Path.Combine(intermediate, "build.props"),
                    Path.Combine(intermediate, proj.ProjectName + ".dll"),
                    Path.Combine(intermediate, "android", "assets", proj.ProjectName + ".dll"),
                    Path.Combine(Root, b.ProjectDirectory, "packages.config"),
                };
                foreach (var file in filesToTouch)
                {
                    FileAssert.Exists(file);
                    File.SetLastWriteTimeUtc(file, DateTime.UtcNow);
                    File.SetLastAccessTimeUtc(file, DateTime.UtcNow);
                }

                //NOTE: second build, targets will run because inputs changed
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "second build should succeed");
                foreach (var target in targets)
                {
                    Assert.IsFalse(b.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped on second build!");
                }

                //NOTE: third build, targets should certainly *not* run! there are no changes
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "third build should succeed");
                foreach (var target in targets)
                {
                    Assert.IsTrue(b.Output.IsTargetSkipped(target), $"`{target}` should be skipped on third build!");
                }
            }
        }
        public void LinkAssembliesNoShrink()
        {
            var proj = new XamarinFormsAndroidApplicationProject();

            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "build should have succeeded.");

                // Touch an assembly to a timestamp older than build.props
                var formsViewGroup = b.Output.GetIntermediaryPath(Path.Combine("android", "assets", "FormsViewGroup.dll"));
                File.SetLastWriteTimeUtc(formsViewGroup, new DateTime(1970, 1, 1));
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true), "build should have succeeded.");
                Assert.IsFalse(b.Output.IsTargetSkipped("_LinkAssembliesNoShrink"), "_LinkAssembliesNoShrink should *not* be skipped.");

                // No changes
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true), "build should have succeeded.");
                Assert.IsTrue(b.Output.IsTargetSkipped("_LinkAssembliesNoShrink"), "_LinkAssembliesNoShrink should be skipped.");
            }
        }
Exemple #12
0
        public void InstantRunSimpleBuild([Values("dx", "d8")] string dexTool)
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("Not required on Open Source Builds");
            }

            if (!HasDevices)
            {
                Assert.Ignore("Test needs a device attached.");
                return;
            }

            var proj = new XamarinFormsAndroidApplicationProject {
                AndroidFastDeploymentType = "Assemblies:Dexes",
                UseLatestPlatformSdk      = true,
                DexTool = dexTool,
            };
            var b = CreateApkBuilder(Path.Combine("temp", TestName));

            Assert.IsTrue(b.Clean(proj), "Clean should have succeeded.");
            Assert.IsTrue(b.Build(proj), "Build should have succeeded.");

            var manifest = b.Output.GetIntermediaryAsText(BuildOutputFiles.AndroidManifest);

            Assert.IsTrue(File.Exists(b.Output.GetIntermediaryPath("android/bin/dex/mono.android.dex")), "there should be mono.android.dex in the intermediaries.");

            using (var apk = ((AndroidApplicationBuildOutput)b.Output).OpenApk()) {
                var dexFile = Path.GetTempFileName();
                File.WriteAllBytes(dexFile, apk.GetRaw(ApkContents.ClassesDex));
                try {
                    string className = "Lcom/xamarin/forms/platform/android/FormsViewGroup;";
                    Assert.IsFalse(DexUtils.ContainsClass(className, dexFile, AndroidSdkPath), $"`{dexFile}` should *not* include `{className}`!");
                    className = "Lmono/MonoRuntimeProvider;";
                    Assert.IsFalse(DexUtils.ContainsClass(className, dexFile, AndroidSdkPath), $"`{dexFile}` should include `{className}`!");
                    className = "Lmono/MonoPackageManager;";
                    Assert.IsTrue(DexUtils.ContainsClass(className, dexFile, AndroidSdkPath), $"`{dexFile}` should include `{className}`!");
                } finally {
                    File.Delete(dexFile);
                }
            }

            b.Dispose();
        }
        public void ResolveLibraryProjectImports()
        {
            var proj = new XamarinFormsAndroidApplicationProject();

            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "first build should have succeeded.");
                var intermediate = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath);
                var cacheFile    = Path.Combine(intermediate, "libraryprojectimports.cache");
                FileAssert.Exists(cacheFile);
                var expected = ReadCache(cacheFile);
                Assert.AreNotEqual(0, expected.Jars.Length,
                                   $"{nameof (expected.Jars)} should not be empty");
                Assert.AreNotEqual(0, expected.ResolvedResourceDirectories.Length,
                                   $"{nameof (expected.ResolvedResourceDirectories)} should not be empty");

                // Delete the stamp file; this triggers <ResolveLibraryProjectImports/> to re-run.
                // However, the task will skip everything, since the hashes of each assembly will be the same.
                var stamp = Path.Combine(intermediate, "stamp", "_ResolveLibraryProjectImports.stamp");
                FileAssert.Exists(stamp);
                File.Delete(stamp);

                Assert.IsTrue(b.Build(proj), "second build should have succeeded.");
                var actual = ReadCache(cacheFile);
                CollectionAssert.AreEqual(actual.Jars.Select(j => j.ItemSpec),
                                          expected.Jars.Select(j => j.ItemSpec));
                CollectionAssert.AreEqual(actual.ResolvedResourceDirectories.Select(j => j.ItemSpec),
                                          expected.ResolvedResourceDirectories.Select(j => j.ItemSpec));

                // Add a new AAR file to the project
                var aar = new AndroidItem.AndroidAarLibrary("Jars\\android-crop-1.0.1.aar")
                {
                    WebContent = "https://jcenter.bintray.com/com/soundcloud/android/android-crop/1.0.1/android-crop-1.0.1.aar"
                };
                proj.OtherBuildItems.Add(aar);

                Assert.IsTrue(b.Build(proj), "third build should have succeeded.");
                actual = ReadCache(cacheFile);
                Assert.AreEqual(expected.Jars.Length + 1, actual.Jars.Length,
                                $"{nameof (expected.Jars)} should have one more item");
                Assert.AreEqual(expected.ResolvedResourceDirectories.Length + 1, actual.ResolvedResourceDirectories.Length,
                                $"{nameof (expected.ResolvedResourceDirectories)} should have one more item");
            }
        }
        public void IncrementalDesignTimeBuild()
        {
            var proj = new XamarinFormsAndroidApplicationProject();

            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                b.Target = "SetupDependenciesForDesigner";
                Assert.IsTrue(b.Build(proj, parameters: DesignerParameters), $"{b.Target} should have succeeded.");

                // Change a layout, DTB
                proj.LayoutMain = proj.LayoutMain.Replace("@string/hello", "hello");
                proj.Touch("Resources\\layout\\Main.axml");
                Assert.IsTrue(b.DesignTimeBuild(proj, target: "UpdateGeneratedFiles"), "DTB should have succeeded.");

                var resourcepathscache = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "designtime", "libraryprojectimports.cache");
                FileAssert.Exists(resourcepathscache);
                var doc = XDocument.Load(resourcepathscache);
                Assert.AreEqual(40, doc.Root.Element("Jars").Elements("Jar").Count(), "libraryprojectimports.cache did not contain expected jar files");
            }
        }
Exemple #15
0
        public void CopyIntermediateAssemblies()
        {
            var target = "_CopyIntermediateAssemblies";
            var proj   = new XamarinFormsAndroidApplicationProject();

            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "first build should succeed");
                Assert.IsFalse(b.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped!");

                var assembly = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, proj.ProjectName + ".dll");
                FileAssert.Exists(assembly);
                File.SetLastWriteTimeUtc(assembly, DateTime.UtcNow);
                File.SetLastAccessTimeUtc(assembly, DateTime.UtcNow);

                //NOTE: second build, target will run because inputs changed
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "second build should succeed");
                Assert.IsFalse(b.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped on second build!");

                //NOTE: third build, it should certainly *not* run! there are no changes
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "third build should succeed");
                Assert.IsTrue(b.Output.IsTargetSkipped(target), $"`{target}` should be skipped on third build!");
            }
        }
Exemple #16
0
        public void BeforeDeploymentTests()
        {
            proj = new XamarinFormsAndroidApplicationProject();
            proj.SetProperty(KnownProperties.AndroidSupportedAbis, "armeabi-v7a;x86");
            var mainPage = proj.Sources.First(x => x.Include() == "MainPage.xaml.cs");
            var source   = mainPage.TextContent().Replace("InitializeComponent ();", @"InitializeComponent ();
			Console.WriteLine ($""TimeZoneInfo={TimeZoneInfo.Local.DisplayName}"");
");

            mainPage.TextContent = () => source;
            builder = CreateApkBuilder(Path.Combine("temp", "DeploymentTests"));
            string apiLevel;

            proj.TargetFrameworkVersion = builder.LatestTargetFrameworkVersion(out apiLevel);
            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=""UnnamedProject.UnnamedProject"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest> ";
            Assert.IsTrue(builder.Build(proj), "Build should have succeeded.");
            Assert.IsTrue(builder.Install(proj), "Install should have succeeded.");
        }
Exemple #17
0
        public void IncrementalFastDeployment()
        {
            AssertCommercialBuild();
            AssertHasDevices();

            var class1src = new BuildItem.Source("Class1.cs")
            {
                TextContent = () => "namespace Library1 { public class Class1 { public static int foo = 0; } }"
            };
            var lib1 = new XamarinAndroidLibraryProject()
            {
                ProjectName = "Library1",
                Sources     =
                {
                    class1src,
                }
            };

            var class2src = new BuildItem.Source("Class2.cs")
            {
                TextContent = () => "namespace Library2 { public class Class2 { public static int foo = 0; } }"
            };
            var lib2 = new DotNetStandard {
                ProjectName     = "Library2",
                Sdk             = "Microsoft.NET.Sdk",
                TargetFramework = "netstandard2.0",
                Sources         =
                {
                    class2src,
                }
            };

            var app = new XamarinFormsAndroidApplicationProject()
            {
                EmbedAssembliesIntoApk = false,
                References             =
                {
                    new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"),
                    new BuildItem("ProjectReference", "..\\Library2\\Library2.csproj"),
                },
            };

            // Set up library projects
            var rootPath = Path.Combine(Root, "temp", TestName);

            using (var lb1 = CreateDllBuilder(Path.Combine(rootPath, lib1.ProjectName)))
                Assert.IsTrue(lb1.Build(lib1), "First library build should have succeeded.");
            using (var lb2 = CreateDllBuilder(Path.Combine(rootPath, lib2.ProjectName)))
                Assert.IsTrue(lb2.Build(lib2), "Second library build should have succeeded.");

            long lib1FirstBuildSize = new FileInfo(Path.Combine(rootPath, lib1.ProjectName, lib1.OutputPath, "Library1.dll")).Length;

            using (var builder = CreateApkBuilder(Path.Combine(rootPath, app.ProjectName))) {
                builder.ThrowOnBuildFailure = false;
                builder.BuildLogFile        = "install.log";
                Assert.IsTrue(builder.Install(app), "First install should have succeeded.");
                var logLines = builder.LastBuildOutput;
                Assert.IsTrue(logLines.Any(l => l.Contains("NotifySync CopyFile") && l.Contains("UnnamedProject.dll")), "UnnamedProject.dll should have been uploaded");
                Assert.IsTrue(logLines.Any(l => l.Contains("NotifySync CopyFile") && l.Contains("Library1.dll")), "Library1.dll should have been uploaded");
                Assert.IsTrue(logLines.Any(l => l.Contains("NotifySync CopyFile") && l.Contains("Library2.dll")), "Library2.dll should have been uploaded");
                var firstInstallTime = builder.LastBuildTime;
                builder.BuildLogFile = "install2.log";
                Assert.IsTrue(builder.Install(app, doNotCleanupOnUpdate: true, saveProject: false), "Second install should have succeeded.");
                var secondInstallTime = builder.LastBuildTime;

                var filesToTouch = new [] {
                    Path.Combine(rootPath, lib2.ProjectName, "Class2.cs"),
                    Path.Combine(rootPath, app.ProjectName, "MainPage.xaml"),
                };
                foreach (var file in filesToTouch)
                {
                    FileAssert.Exists(file);
                    File.SetLastWriteTimeUtc(file, DateTime.UtcNow);
                }

                class1src.TextContent = () => "namespace Library1 { public class Class1 { public static int foo = 100; } }";
                class1src.Timestamp   = DateTime.UtcNow.AddSeconds(1);
                using (var lb1 = CreateDllBuilder(Path.Combine(rootPath, lib1.ProjectName)))
                    Assert.IsTrue(lb1.Build(lib1), "Second library build should have succeeded.");

                long lib1SecondBuildSize = new FileInfo(Path.Combine(rootPath, lib1.ProjectName, lib1.OutputPath, "Library1.dll")).Length;
                Assert.AreEqual(lib1FirstBuildSize, lib1SecondBuildSize, "Library2.dll was not the same size.");

                builder.BuildLogFile = "install3.log";
                Assert.IsTrue(builder.Install(app, doNotCleanupOnUpdate: true, saveProject: false), "Third install should have succeeded.");
                logLines = builder.LastBuildOutput;
                Assert.IsTrue(logLines.Any(l => l.Contains("NotifySync CopyFile") && l.Contains("UnnamedProject.dll")), "UnnamedProject.dll should have been uploaded");
                Assert.IsTrue(logLines.Any(l => l.Contains("NotifySync CopyFile") && l.Contains("Library1.dll")), "Library1.dll should have been uploaded");
                Assert.IsTrue(logLines.Any(l => l.Contains("NotifySync SkipCopyFile") && l.Contains("Library2.dll")), "Library2.dll should not have been uploaded");
                var thirdInstallTime = builder.LastBuildTime;
                builder.BuildLogFile = "install4.log";
                Assert.IsTrue(builder.Install(app, doNotCleanupOnUpdate: true, saveProject: false), "Fourth install should have succeeded.");
                var fourthInstalTime = builder.LastBuildTime;

                Assert.IsTrue(thirdInstallTime < firstInstallTime, $"Third incremental install: '{thirdInstallTime}' should be faster than clean install: '{firstInstallTime}'.");
                Assert.IsTrue(secondInstallTime < firstInstallTime && secondInstallTime < thirdInstallTime,
                              $"Second unchanged install: '{secondInstallTime}' should be faster than clean install: '{firstInstallTime}' and incremental install: '{thirdInstallTime}'.");
                Assert.IsTrue(fourthInstalTime < firstInstallTime && fourthInstalTime < thirdInstallTime,
                              $"Fourth unchanged install: '{fourthInstalTime}' should be faster than clean install: '{firstInstallTime}' and incremental install: '{thirdInstallTime}'.");
            }
        }
Exemple #18
0
        public void IncrementalFastDeployment()
        {
            AssertCommercialBuild();
            AssertHasDevices();

            var lib1 = new XamarinAndroidLibraryProject()
            {
                ProjectName = "Library1",
                Sources     =
                {
                    new BuildItem.Source("Class1.cs")
                    {
                        TextContent = () => "namespace Library1 { public class Class1 { } }"
                    },
                }
            };

            var lib2 = new DotNetStandard {
                ProjectName     = "Library2",
                Sdk             = "Microsoft.NET.Sdk",
                TargetFramework = "netstandard2.0",
                Sources         =
                {
                    new BuildItem.Source("Class2.cs")
                    {
                        TextContent = () => "namespace Library2 { public class Class2 { } }"
                    },
                }
            };

            var app = new XamarinFormsAndroidApplicationProject()
            {
                AndroidUseSharedRuntime = true,
                EmbedAssembliesIntoApk  = false,
                References =
                {
                    new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"),
                    new BuildItem("ProjectReference", "..\\Library2\\Library2.csproj"),
                },
            };

            // Set up library projects
            var rootPath = Path.Combine(Root, "temp", TestName);

            using (var lb1 = CreateDllBuilder(Path.Combine(rootPath, lib1.ProjectName)))
                Assert.IsTrue(lb1.Build(lib1), "First library build should have succeeded.");
            using (var lb2 = CreateDllBuilder(Path.Combine(rootPath, lib2.ProjectName)))
                Assert.IsTrue(lb2.Build(lib2), "Second library build should have succeeded.");

            using (var builder = CreateApkBuilder(Path.Combine(rootPath, app.ProjectName))) {
                builder.ThrowOnBuildFailure = false;
                Assert.IsTrue(builder.Install(app), "First install should have succeeded.");
                var firstInstallTime = builder.LastBuildTime;
                Assert.IsTrue(builder.Install(app, doNotCleanupOnUpdate: true, saveProject: false), "Second install should have succeeded.");
                var secondInstallTime = builder.LastBuildTime;

                var filesToTouch = new [] {
                    Path.Combine(rootPath, lib1.ProjectName, "Class1.cs"),
                    Path.Combine(rootPath, lib2.ProjectName, "Class2.cs"),
                    Path.Combine(rootPath, app.ProjectName, "MainPage.xaml"),
                };
                foreach (var file in filesToTouch)
                {
                    FileAssert.Exists(file);
                    File.SetLastWriteTimeUtc(file, DateTime.UtcNow);
                }

                Assert.IsTrue(builder.Install(app, doNotCleanupOnUpdate: true, saveProject: false), "Third install should have succeeded.");
                var thirdInstallTime = builder.LastBuildTime;
                Assert.IsTrue(builder.Install(app, doNotCleanupOnUpdate: true, saveProject: false), "Fourth install should have succeeded.");
                var fourthInstalTime = builder.LastBuildTime;

                Assert.IsTrue(thirdInstallTime < firstInstallTime, $"Third incremental install: '{thirdInstallTime}' should be faster than clean install: '{firstInstallTime}'.");
                Assert.IsTrue(secondInstallTime < firstInstallTime && secondInstallTime < thirdInstallTime,
                              $"Second unchanged install: '{secondInstallTime}' should be faster than clean install: '{firstInstallTime}' and incremental install: '{thirdInstallTime}'.");
                Assert.IsTrue(fourthInstalTime < firstInstallTime && fourthInstalTime < thirdInstallTime,
                              $"Fourth unchanged install: '{fourthInstalTime}' should be faster than clean install: '{firstInstallTime}' and incremental install: '{thirdInstallTime}'.");
            }
        }
        public void Build_XAML_Change(bool produceReferenceAssembly, bool install)
        {
            if (install)
            {
                AssertCommercialBuild();                  // This test will fail without Fast Deployment
                AssertHasDevices();
            }

            var path = Path.Combine("temp", TestName);
            var xaml =
                @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<ContentPage xmlns=""http://xamarin.com/schemas/2014/forms""
             xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
             x:Class=""MyLibrary.MyPage"">
</ContentPage>";
            var caller = nameof(Build_XAML_Change);

            if (install)
            {
                caller = caller.Replace("Build", "Install");
            }
            else if (produceReferenceAssembly)
            {
                caller += "_RefAssembly";
            }
            var app = new XamarinFormsAndroidApplicationProject {
                ProjectName = "MyApp",
                Sources     =
                {
                    new BuildItem.Source("Foo.cs")
                    {
                        TextContent = () => "public class Foo : Bar { }"
                    },
                }
            };

            //NOTE: this will skip a 382ms <VerifyVersionsTask/> from the support library
            app.SetProperty("XamarinAndroidSupportSkipVerifyVersions", "True");

            int count = 0;
            var lib   = new DotNetStandard {
                ProjectName     = "MyLibrary",
                Sdk             = "Microsoft.NET.Sdk",
                TargetFramework = "netstandard2.0",
                Sources         =
                {
                    new BuildItem.Source("Bar.cs")
                    {
                        TextContent = () => "public class Bar { public Bar () { System.Console.WriteLine (" + count++ + "); } }"
                    },
                    new BuildItem("EmbeddedResource", "MyPage.xaml")
                    {
                        TextContent = () => xaml,
                    }
                },
                PackageReferences =
                {
                    KnownPackages.XamarinForms_4_0_0_425677
                }
            };

            lib.SetProperty("ProduceReferenceAssembly", produceReferenceAssembly.ToString());
            app.References.Add(new BuildItem.ProjectReference($"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj", lib.ProjectName, lib.ProjectGuid));

            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName)))
                using (var appBuilder = CreateBuilderWithoutLogFile(Path.Combine(path, app.ProjectName))) {
                    libBuilder.Build(lib);
                    appBuilder.Target = "Build";
                    if (install)
                    {
                        appBuilder.Install(app);
                    }
                    else
                    {
                        appBuilder.Build(app);
                    }

                    libBuilder.AutomaticNuGetRestore     =
                        appBuilder.AutomaticNuGetRestore = false;

                    // Profile XAML change
                    xaml += $"{Environment.NewLine}<!--comment-->";
                    lib.Touch("MyPage.xaml");
                    libBuilder.Build(lib, doNotCleanupOnUpdate: true);
                    if (install)
                    {
                        Profile(appBuilder, b => b.Install(app, doNotCleanupOnUpdate: true), caller);
                    }
                    else
                    {
                        Profile(appBuilder, b => b.Build(app, doNotCleanupOnUpdate: true), caller);
                    }
                }
        }
Exemple #20
0
        static void Main()
        {
            var temp = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location));

            using (builder = new ProjectBuilder(Path.Combine("temp", "Fuzzer"))
            {
                AutomaticNuGetRestore = false,
                CleanupAfterSuccessfulBuild = false,
                CleanupOnDispose = true,
                Root = Xamarin.Android.Build.Paths.TestOutputDirectory,
            }) {
                directory = Path.GetFullPath(Path.Combine(builder.Root, builder.ProjectDirectory));
                if (Directory.Exists(directory))
                {
                    Directory.Delete(directory, recursive: true);
                }

                application = new XamarinFormsAndroidApplicationProject();
                application.AndroidManifest = application.AndroidManifest.Replace("<uses-sdk />", "<uses-sdk android:targetSdkVersion=\"28\" />");
                application.MainActivity    = application.DefaultMainActivity.Replace("//${AFTER_ONCREATE}", "Android.Util.Log.Debug (\"FUZZER\", \"App started!\");");
                var abis = new string [] { "armeabi-v7a", "arm64-v8a", "x86" };
                application.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));

                if (!NuGetRestore())
                {
                    Console.WriteLine("Initial NuGet restore failed!");
                    return;
                }

                Func <bool> [] operations =
                {
                    AddClass,
                    AddResource,
                    Build,
                    ChangePackageName,
                    Clean,
                    DesignerBuild,
                    DesignTimeBuild,
                    Install,
                    NuGetRestore,
                    RemoveClass,
                    RemoveResource,
                    RenameClass,
                    RenameResource,
                    Run,
                    TouchRandomFile,
                    Uninstall,
                };

                while (true)
                {
                    var operation = operations [random.Next(operations.Length)];
                    if (!operation())
                    {
                        break;
                    }
                }
            }

            Console.WriteLine("Press enter to exit...");
            Console.ReadLine();
        }
        public void BuildApplicationWithMonoEnvironment([Values("", "Normal", "Offline")] string sequencePointsMode)
        {
            const string supportedAbis = "armeabi-v7a;x86";

            var lib = new XamarinAndroidLibraryProject {
                ProjectName     = "Library1",
                IsRelease       = true,
                OtherBuildItems = { new AndroidItem.AndroidEnvironment("Mono.env")
                                    {
                                        TextContent = () => "MONO_DEBUG=soft-breakpoints"
                                    }, },
            };
            var app = new XamarinFormsAndroidApplicationProject()
            {
                IsRelease = true,
                AndroidLinkModeRelease = AndroidLinkMode.Full,
                References             =
                {
                    new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"),
                },
            };
            //LinkSkip one assembly that contains __AndroidLibraryProjects__.zip
            string linkSkip = "FormsViewGroup";

            app.SetProperty("AndroidLinkSkip", linkSkip);
            app.SetProperty("_AndroidSequencePointsMode", sequencePointsMode);
            app.SetAndroidSupportedAbis(supportedAbis);
            using (var libb = CreateDllBuilder(Path.Combine("temp", TestName, lib.ProjectName)))
                using (var appb = CreateApkBuilder(Path.Combine("temp", TestName, app.ProjectName))) {
                    Assert.IsTrue(libb.Build(lib), "Library build should have succeeded.");
                    Assert.IsTrue(appb.Build(app), "App should have succeeded.");
                    Assert.IsTrue(StringAssertEx.ContainsText(appb.LastBuildOutput, $"Save assembly: {linkSkip}"), $"{linkSkip} should be saved, and not linked!");

                    string        intermediateOutputDir = Path.Combine(Root, appb.ProjectDirectory, app.IntermediateOutputPath);
                    List <string> envFiles = EnvironmentHelper.GatherEnvironmentFiles(intermediateOutputDir, supportedAbis, true);
                    Dictionary <string, string> envvars = EnvironmentHelper.ReadEnvironmentVariables(envFiles);
                    Assert.IsTrue(envvars.Count > 0, $"No environment variables defined");

                    string monoDebugVar;
                    Assert.IsTrue(envvars.TryGetValue("MONO_DEBUG", out monoDebugVar), "Environment should contain MONO_DEBUG");
                    Assert.IsFalse(String.IsNullOrEmpty(monoDebugVar), "Environment must contain MONO_DEBUG with a value");
                    Assert.IsTrue(monoDebugVar.IndexOf("soft-breakpoints") >= 0, "Environment must contain MONO_DEBUG with 'soft-breakpoints' in its value");

                    if (!String.IsNullOrEmpty(sequencePointsMode))
                    {
                        Assert.IsTrue(monoDebugVar.IndexOf("gen-compact-seq-points") >= 0, "The values from Mono.env should have been merged into environment");
                    }

                    EnvironmentHelper.AssertValidEnvironmentSharedLibrary(intermediateOutputDir, AndroidSdkPath, AndroidNdkPath, supportedAbis);

                    var assemblyDir = Path.Combine(Root, appb.ProjectDirectory, app.IntermediateOutputPath, "android", "assets");
                    var rp          = new ReaderParameters {
                        ReadSymbols = false
                    };
                    foreach (var assemblyFile in Directory.EnumerateFiles(assemblyDir, "*.dll"))
                    {
                        using (var assembly = AssemblyDefinition.ReadAssembly(assemblyFile)) {
                            foreach (var module in assembly.Modules)
                            {
                                var resources = module.Resources.Select(r => r.Name).ToArray();
                                Assert.IsFalse(StringAssertEx.ContainsText(resources, "__AndroidEnvironment__"), "AndroidEnvironment EmbeddedResource should be stripped!");
                                Assert.IsFalse(StringAssertEx.ContainsText(resources, "__AndroidLibraryProjects__.zip"), "__AndroidLibraryProjects__.zip should be stripped!");
                                Assert.IsFalse(StringAssertEx.ContainsText(resources, "__AndroidNativeLibraries__.zip"), "__AndroidNativeLibraries__.zip should be stripped!");
                            }
                        }
                    }
                }
        }
        public void ApplicationRunsWithDebuggerAndBreaks(bool useSharedRuntime, bool embedAssemblies, string fastDevType, bool allowDeltaInstall)
        {
            AssertCommercialBuild();
            AssertHasDevices();
            var proj = new XamarinFormsAndroidApplicationProject()
            {
                IsRelease = false,
                AndroidUseSharedRuntime   = useSharedRuntime,
                EmbedAssembliesIntoApk    = embedAssemblies,
                AndroidFastDeploymentType = fastDevType
            };
            var abis = new string [] { "armeabi-v7a", "x86" };

            proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            if (allowDeltaInstall)
            {
                proj.SetProperty(KnownProperties._AndroidAllowDeltaInstall, "true");
            }
            proj.SetDefaultTargetDevice();
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                SetTargetFrameworkAndManifest(proj, b);
                Assert.True(b.Install(proj), "Project should have installed.");

                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, b.ProjectDirectory, "MainActivity.cs"), 20 },
                    { Path.Combine(Root, b.ProjectDirectory, "MainPage.xaml.cs"), 14 },
                    { Path.Combine(Root, b.ProjectDirectory, "MainPage.xaml.cs"), 19 },
                    { Path.Combine(Root, b.ProjectDirectory, "App.xaml.cs"), 12 },
                };
                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(b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets"),
                };
                var options = new DebuggerSessionOptions()
                {
                    EvaluationOptions = EvaluationOptions.DefaultOptions,
                };
                options.EvaluationOptions.UseExternalTypeResolver = true;
                ClearAdbLogcat();
                Assert.True(b.RunTarget(proj, "_Run", parameters: new string [] {
                    $"AndroidSdbTargetPort={port}",
                    $"AndroidSdbHostPort={port}",
                    "AndroidAttachDebugger=True",
                }), "Project should have run.");

                Assert.IsTrue(WaitForDebuggerToStart(Path.Combine(Root, b.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 = 3;
                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(proj.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}");
                Assert.True(b.Uninstall(proj), "Project should have uninstalled.");
                session.Exit();
            }
        }
        public void AppProjectTargetsDoNotBreak()
        {
            var targets = new List <string> {
                "_CopyIntermediateAssemblies",
                "_GeneratePackageManagerJava",
                "_ResolveLibraryProjectImports",
                "_BuildAdditionalResourcesCache",
                "_CleanIntermediateIfNuGetsChange",
                "_CopyConfigFiles",
                "_CopyPdbFiles",
            };
            var proj = new XamarinFormsAndroidApplicationProject {
                OtherBuildItems =
                {
                    new BuildItem.NoActionResource("UnnamedProject.dll.config")
                    {
                        TextContent = () => "<?xml version='1.0' ?><configuration/>",
                        Metadata    =
                        {
                            { "CopyToOutputDirectory", "PreserveNewest" },
                        }
                    }
                }
            };

            if (IsWindows)
            {
                //NOTE: pdb2mdb will run on Windows on the current project's symbols if DebugType=Full
                proj.SetProperty(proj.DebugProperties, "DebugType", "Full");
                targets.Add("_CopyMdbFiles");
                targets.Add("_ConvertPdbFiles");
            }
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "first build should succeed");
                foreach (var target in targets)
                {
                    Assert.IsFalse(b.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped!");
                }

                var output       = Path.Combine(Root, b.ProjectDirectory, proj.OutputPath);
                var intermediate = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath);
                var filesToTouch = new [] {
                    Path.Combine(intermediate, "..", "project.assets.json"),
                    Path.Combine(intermediate, "build.props"),
                    Path.Combine(intermediate, $"{proj.ProjectName}.dll"),
                    Path.Combine(intermediate, $"{proj.ProjectName}.pdb"),
                    Path.Combine(intermediate, "android", "assets", $"{proj.ProjectName}.dll"),
                    Path.Combine(output, $"{proj.ProjectName}.dll.config"),
                };
                foreach (var file in filesToTouch)
                {
                    FileAssert.Exists(file);
                    File.SetLastWriteTimeUtc(file, DateTime.UtcNow);
                    File.SetLastAccessTimeUtc(file, DateTime.UtcNow);
                }

                //NOTE: second build, targets will run because inputs changed
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "second build should succeed");
                foreach (var target in targets)
                {
                    Assert.IsFalse(b.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped on second build!");
                }

                //NOTE: third build, targets should certainly *not* run! there are no changes
                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "third build should succeed");
                foreach (var target in targets)
                {
                    Assert.IsTrue(b.Output.IsTargetSkipped(target), $"`{target}` should be skipped on third build!");
                }
            }
        }
Exemple #24
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();
                }
        }
        public void ResolveLibraryProjectImports([Values(true, false)] bool useAapt2)
        {
            var proj = new XamarinFormsAndroidApplicationProject();

            proj.SetProperty("AndroidUseAapt2", useAapt2.ToString());
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "first build should have succeeded.");
                var intermediate = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath);
                var cacheFile    = Path.Combine(intermediate, "libraryprojectimports.cache");
                FileAssert.Exists(cacheFile);
                var expected = ReadCache(cacheFile);
                Assert.AreNotEqual(0, expected.Jars.Length,
                                   $"{nameof (expected.Jars)} should not be empty");
                Assert.AreNotEqual(0, expected.ResolvedResourceDirectories.Length,
                                   $"{nameof (expected.ResolvedResourceDirectories)} should not be empty");
                Assert.AreNotEqual(0, expected.ResolvedResourceDirectoryStamps.Length,
                                   $"{nameof (expected.ResolvedResourceDirectoryStamps)} should not be empty");

                // Delete the stamp file; this triggers <ResolveLibraryProjectImports/> to re-run.
                // However, the task will skip everything, since the hashes of each assembly will be the same.
                var stamp = Path.Combine(intermediate, "stamp", "_ResolveLibraryProjectImports.stamp");
                FileAssert.Exists(stamp);
                File.Delete(stamp);

                Assert.IsTrue(b.Build(proj), "second build should have succeeded.");
                var actual = ReadCache(cacheFile);
                CollectionAssert.AreEqual(actual.Jars.Select(j => j.ItemSpec),
                                          expected.Jars.Select(j => j.ItemSpec));
                CollectionAssert.AreEqual(actual.ResolvedResourceDirectories.Select(j => j.ItemSpec),
                                          expected.ResolvedResourceDirectories.Select(j => j.ItemSpec));

                // Add a new AAR file to the project
                var aar = new AndroidItem.AndroidAarLibrary("Jars\\android-crop-1.0.1.aar")
                {
                    WebContent = "https://jcenter.bintray.com/com/soundcloud/android/android-crop/1.0.1/android-crop-1.0.1.aar"
                };
                proj.OtherBuildItems.Add(aar);

                Assert.IsTrue(b.Build(proj), "third build should have succeeded.");
                actual = ReadCache(cacheFile);
                Assert.AreEqual(expected.Jars.Length + 1, actual.Jars.Length,
                                $"{nameof (expected.Jars)} should have one more item");
                Assert.AreEqual(expected.ResolvedResourceDirectories.Length + 1, actual.ResolvedResourceDirectories.Length,
                                $"{nameof (expected.ResolvedResourceDirectories)} should have one more item");
                Assert.AreEqual(expected.ResolvedResourceDirectoryStamps.Length + 1, actual.ResolvedResourceDirectoryStamps.Length,
                                $"{nameof (expected.ResolvedResourceDirectoryStamps)} should have one more item");
                foreach (var s in actual.ResolvedResourceDirectoryStamps)
                {
                    FileAssert.Exists(s.ItemSpec);
                }

                // Build with no changes, checking we are skipping targets appropriately
                Assert.IsTrue(b.Build(proj), "fourth build should have succeeded.");
                var targets = new List <string> {
                    "_UpdateAndroidResgen",
                    "_CompileJava",
                    "_CreateBaseApk",
                };
                if (useAapt2)
                {
                    targets.Add("_ConvertLibraryResourcesCases");
                }
                foreach (var targetName in targets)
                {
                    Assert.IsTrue(b.Output.IsTargetSkipped(targetName), $"`{targetName}` should be skipped!");
                }
            }
        }
        public void ApplicationRunsWithDebuggerAndBreaks(bool useSharedRuntime, bool embedAssemblies, string fastDevType)
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("Test does not run on the Open Source Builds.");
                return;
            }
            if (!HasDevices)
            {
                Assert.Ignore("Test needs a device attached.");
                return;
            }
            var proj = new XamarinFormsAndroidApplicationProject()
            {
                IsRelease = false,
                AndroidFastDeploymentType = fastDevType
            };
            var abis = new string [] { "armeabi-v7a", "x86" };

            proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            proj.SetProperty(KnownProperties.AndroidUseSharedRuntime, useSharedRuntime.ToString());
            proj.SetProperty("EmbedAssembliesIntoApk", embedAssemblies.ToString());
            proj.SetDefaultTargetDevice();
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                string apiLevel;
                proj.TargetFrameworkVersion = b.LatestTargetFrameworkVersion(out apiLevel);
                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=""UnnamedProject.UnnamedProject"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest>";
                b.Save(proj, saveProject: true);
                proj.NuGetRestore(Path.Combine(Root, b.ProjectDirectory), b.PackagesDirectory);
                Assert.True(b.Build(proj), "Project should have built.");
                Assert.True(b.Install(proj), "Project should have installed.");

                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, b.ProjectDirectory, "MainActivity.cs"), 19 },
                    { Path.Combine(Root, b.ProjectDirectory, "MainPage.xaml.cs"), 14 },
                    { Path.Combine(Root, b.ProjectDirectory, "MainPage.xaml.cs"), 19 },
                    { Path.Combine(Root, b.ProjectDirectory, "App.xaml.cs"), 12 },
                };
                session.TargetHitBreakpoint += (sender, e) => {
                    Console.WriteLine($"BREAK {e.Type}");
                    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(b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets"),
                };
                var options = new DebuggerSessionOptions()
                {
                    EvaluationOptions = EvaluationOptions.DefaultOptions,
                };
                options.EvaluationOptions.UseExternalTypeResolver = true;
                ClearAdbLogcat();
                Assert.True(b.RunTarget(proj, "_Run", parameters: new string [] {
                    $"AndroidSdbTargetPort={port}",
                    $"AndroidSdbHostPort={port}",
                    "AndroidAttachDebugger=True",
                }), "Project should have run.");

                Assert.IsTrue(WaitForDebuggerToStart(output: out string logcat), "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);
                while (session.IsConnected && breakcountHitCount < 3)
                {
                    Thread.Sleep(10);
                    timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10));
                }
                WaitFor(2000);
                ClearAdbLogcat();
                ClickButton(proj.PackageName, "myXFButton", "CLICK ME");
                while (session.IsConnected && breakcountHitCount < 4)
                {
                    Thread.Sleep(10);
                    timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10));
                }
                int expected = 4;
                Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}");
                Assert.True(b.Uninstall(proj), "Project should have uninstalled.");
                session.Exit();
            }
        }