Example #1
0
        public void LocalizedAssemblies_ShouldBeFastDeployed()
        {
            AssertCommercialBuild();
            AssertHasDevices();

            var path = Path.Combine("temp", TestName);
            var lib  = new XamarinAndroidLibraryProject {
                ProjectName     = "Localization",
                OtherBuildItems =
                {
                    new BuildItem("EmbeddedResource", "Bar.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancel</value></data>")
                    },
                    new BuildItem("EmbeddedResource", "Bar.es.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancelar</value></data>")
                    }
                }
            };

            var app = new XamarinAndroidApplicationProject {
                EmbedAssembliesIntoApk = false,
                OtherBuildItems        =
                {
                    new BuildItem("EmbeddedResource", "Foo.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancel</value></data>")
                    },
                    new BuildItem("EmbeddedResource", "Foo.es.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancelar</value></data>")
                    }
                }
            };

            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 = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.IsTrue(libBuilder.Build(lib), "Library Build should have succeeded.");
                    Assert.IsTrue(appBuilder.Install(app), "App Install should have succeeded.");
                    var projectOutputPath     = Path.Combine(Root, appBuilder.ProjectDirectory, app.OutputPath);
                    var resourceFilesFromDisk = Directory.EnumerateFiles(projectOutputPath, "*.resources.dll", SearchOption.AllDirectories)
                                                .Select(r => r = r.Replace(projectOutputPath, string.Empty).Replace("\\", "/"));

                    var overrideContents = string.Empty;
                    foreach (var dir in GetOverrideDirectoryPaths(app.PackageName))
                    {
                        overrideContents += RunAdbCommand($"shell run-as {app.PackageName} find {dir}");
                    }
                    Assert.IsTrue(resourceFilesFromDisk.Any(), $"Unable to find any localized assemblies in {resourceFilesFromDisk}");
                    foreach (var res in resourceFilesFromDisk)
                    {
                        StringAssert.Contains(res, overrideContents, $"{res} did not exist in the .__override__ directory.\nFound:{overrideContents}");
                    }
                    appBuilder.BuildLogFile = "uninstall.log";
                    appBuilder.Uninstall(app);
                }
        }
Example #2
0
        public void ClassLibraryMainLauncherRuns()
        {
            AssertHasDevices();

            var path = Path.Combine("temp", TestName);

            var app = new XamarinAndroidApplicationProject {
                ProjectName = "MyApp",
            };

            if (!CommercialBuildAvailable)
            {
                app.SetAndroidSupportedAbis("armeabi-v7a", "x86");
            }
            app.SetDefaultTargetDevice();

            var lib = new XamarinAndroidLibraryProject {
                ProjectName = "MyLibrary"
            };

            lib.Sources.Add(new BuildItem.Source("MainActivity.cs")
            {
                TextContent = () => lib.ProcessSourceTemplate(app.DefaultMainActivity).Replace("${JAVA_PACKAGENAME}", app.JavaPackageName),
            });
            lib.AndroidResources.Clear();
            foreach (var resource in app.AndroidResources)
            {
                lib.AndroidResources.Add(resource);
            }
            var reference = $"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj";

            app.References.Add(new BuildItem.ProjectReference(reference, lib.ProjectName, lib.ProjectGuid));

            // Remove the default MainActivity.cs & AndroidResources
            app.AndroidResources.Clear();
            app.AndroidResources.Add(new AndroidItem.AndroidResource("Resources\\layout\\foo.xml")
            {
                TextContent = () => "<?xml version=\"1.0\" encoding=\"utf-8\" ?><LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\" />"
            });
            app.Sources.Remove(app.GetItem("MainActivity.cs"));

            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName)))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    SetTargetFrameworkAndManifest(app, appBuilder);
                    Assert.IsTrue(libBuilder.Build(lib), "library build should have succeeded.");
                    Assert.True(appBuilder.Install(app), "app should have installed.");
                    ClearAdbLogcat();
                    if (CommercialBuildAvailable)
                    {
                        Assert.True(appBuilder.RunTarget(app, "_Run"), "Project should have run.");
                    }
                    else
                    {
                        AdbStartActivity($"{app.PackageName}/{app.JavaPackageName}.MainActivity");
                    }

                    Assert.True(WaitForActivityToStart(app.PackageName, "MainActivity",
                                                       Path.Combine(Root, appBuilder.ProjectDirectory, "logcat.log"), 30), "Activity should have started.");
                }
        }
Example #3
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.");
                }
        }
Example #4
0
        public void FullPath()
        {
            var assetPath = Path.GetFullPath(Path.Combine(Root, "temp", TestName, "Assets", "foo.txt"));

            Directory.CreateDirectory(Path.GetDirectoryName(assetPath));
            File.WriteAllText(assetPath, contents: "bar");
            var proj = new XamarinAndroidLibraryProject {
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset(assetPath)
                    {
                        Metadata ={                { "LogicalName", Path.Combine("Assets", "foo.txt") } },
                    },
                },
            };

            using (var b = CreateDllBuilder(Path.Combine("temp", TestName, "SubDir"))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                var libraryProjectImports = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "__AndroidLibraryProjects__.zip");
                FileAssert.Exists(libraryProjectImports);
                using (var zip = ZipHelper.OpenZip(libraryProjectImports)) {
                    var entryName = "library_project_imports/assets/foo.txt";
                    var entry     = zip.ReadEntry(entryName);
                    Assert.IsNotNull(entry, $"{libraryProjectImports} should contain {entryName}");
                    using (var memory = new MemoryStream()) {
                        entry.Extract(memory);
                        memory.Position = 0;
                        Assert.AreEqual("bar", Encoding.Default.GetString(memory.ToArray()));
                    }
                }
            }
        }
Example #5
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);
                    }
                }
        }
Example #6
0
        public void OneTimeSetUp()
        {
            var path = Path.Combine("temp", TestName);

            lib = new XamarinAndroidLibraryProject {
                ProjectName     = "Localization",
                IsRelease       = true,
                OtherBuildItems =
                {
                    new BuildItem("EmbeddedResource", "Foo.resx")
                    {
                        TextContent = () => ResxWithContents("<data name=\"CancelButton\"><value>Cancel</value></data>")
                    },
                    new BuildItem("EmbeddedResource", "Foo.es.resx")
                    {
                        TextContent = () => ResxWithContents("<data name=\"CancelButton\"><value>Cancelar</value></data>")
                    }
                }
            };

            var bytes = new byte [1024];

            app = new XamarinFormsMapsApplicationProject {
                IsRelease = true,
            };
            app.OtherBuildItems.Add(new AndroidItem.AndroidAsset("foo.bar")
            {
                BinaryContent = () => bytes,
            });
            app.OtherBuildItems.Add(new AndroidItem.AndroidAsset("foo.wav")
            {
                BinaryContent = () => bytes,
            });
            app.OtherBuildItems.Add(new BuildItem("None", "buildConfig.json")
            {
                TextContent = () => BuildConfig,
            });
            app.SetProperty("AndroidStoreUncompressedFileExtensions", ".bar");
            app.References.Add(new BuildItem.ProjectReference($"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj", lib.ProjectName, lib.ProjectGuid));

            //NOTE: this is here to enable adb shell run-as
            app.AndroidManifest = app.AndroidManifest.Replace("<application ", "<application android:debuggable=\"true\" ");
            app.SetProperty(app.ReleaseProperties, "AndroidPackageFormat", "aab");
            var abis = new string [] { "armeabi-v7a", "arm64-v8a", "x86" };

            app.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            app.SetProperty("AndroidBundleConfigurationFile", "buildConfig.json");

            libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName), cleanupOnDispose: true);
            Assert.IsTrue(libBuilder.Build(lib), "Library build should have succeeded.");
            appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName), cleanupOnDispose: true);
            Assert.IsTrue(appBuilder.Build(app), "App build should have succeeded.");

            var projectDir = Path.Combine(Root, appBuilder.ProjectDirectory);

            intermediate = Path.Combine(projectDir, app.IntermediateOutputPath);
            bin          = Path.Combine(projectDir, app.OutputPath);
        }
        public void ProduceReferenceAssembly()
        {
            var path = Path.Combine("temp", TestName);
            var app  = new XamarinAndroidApplicationProject {
                ProjectName = "MyApp",
                Sources     =
                {
                    new BuildItem.Source("Foo.cs")
                    {
                        TextContent = () => "public class Foo : Bar { }"
                    },
                }
            };
            int count = 0;
            var lib   = new XamarinAndroidLibraryProject {
                ProjectName = "MyLibrary",
                Sources     =
                {
                    new BuildItem.Source("Bar.cs")
                    {
                        TextContent = () => "public class Bar { public Bar () { System.Console.WriteLine (" + count++ + "); } }"
                    },
                }
            };

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

            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName), false))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.IsTrue(libBuilder.Build(lib), "first library build should have succeeded.");
                    Assert.IsTrue(appBuilder.Build(app), "first app build should have succeeded.");

                    lib.Touch("Bar.cs");

                    Assert.IsTrue(libBuilder.Build(lib, doNotCleanupOnUpdate: true, saveProject: false), "second library build should have succeeded.");
                    Assert.IsTrue(appBuilder.Build(app, doNotCleanupOnUpdate: true, saveProject: false), "second app build should have succeeded.");

                    var targetsShouldSkip = new [] {
                        //TODO: perhaps more targets will skip here eventually?
                        "CoreCompile",
                    };
                    foreach (var target in targetsShouldSkip)
                    {
                        Assert.IsTrue(appBuilder.Output.IsTargetSkipped(target), $"`{target}` should be skipped!");
                    }

                    var targetsShouldRun = new [] {
                        "_BuildApkEmbed",
                        "_CopyPackage",
                        "_Sign",
                    };
                    foreach (var target in targetsShouldRun)
                    {
                        Assert.IsFalse(appBuilder.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped!");
                    }
                }
        }
Example #8
0
        void BuildLibraryWithResources(string path)
        {
            var library = new XamarinAndroidLibraryProject()
            {
                ProjectName = "Library",
            };

            var libraryStrings = library.AndroidResources.FirstOrDefault(r => r.Include() == @"Resources\values\Strings.xml");

            library.AndroidResources.Clear();
            library.AndroidResources.Add(libraryStrings);
            library.AndroidResources.Add(new AndroidItem.AndroidResource(Path.Combine("Resources", "animator", "slide_in_bottom.xml"))
            {
                TextContent = () => Animator
            });
            library.AndroidResources.Add(new AndroidItem.AndroidResource(Path.Combine("Resources", "font", "arial.ttf"))
            {
                TextContent = () => ""
            });
            library.AndroidResources.Add(new AndroidItem.AndroidResource(Path.Combine("Resources", "values", "strings2.xml"))
            {
                TextContent = () => StringsXml2
            });
            library.AndroidResources.Add(new AndroidItem.AndroidResource(Path.Combine("Resources", "values", "dimen.xml"))
            {
                TextContent = () => Dimen
            });

            using (var stream = typeof(XamarinAndroidCommonProject).Assembly.GetManifestResourceStream("Xamarin.ProjectTools.Resources.Base.Icon.png")) {
                var icon_binary_mdpi = new byte [stream.Length];
                stream.Read(icon_binary_mdpi, 0, (int)stream.Length);
                library.AndroidResources.Add(new AndroidItem.AndroidResource(Path.Combine("Resources", "drawable", "ic_menu_preferences.png"))
                {
                    BinaryContent = () => icon_binary_mdpi
                });
                library.AndroidResources.Add(new AndroidItem.AndroidResource(Path.Combine("Resources", "mipmap-hdpi", "icon.png"))
                {
                    BinaryContent = () => icon_binary_mdpi
                });
            }

            library.AndroidResources.Add(new AndroidItem.AndroidResource(Path.Combine("Resources", "menu", "options.xml"))
            {
                TextContent = () => Menu
            });

            using (ProjectBuilder builder = CreateDllBuilder(Path.Combine(Root, path))) {
                Assert.IsTrue(builder.Build(library), "Build should have succeeded");
            }
        }
        public void Build_AndroidAsset_Change()
        {
            var bytes = new byte [1024 * 1024 * 10];
            var rnd   = new Random();

            rnd.NextBytes(bytes);
            var lib = new XamarinAndroidLibraryProject()
            {
                ProjectName = "Library1",
            };

            lib.OtherBuildItems.Add(new AndroidItem.AndroidAsset("Assets\\foo.bar")
            {
                BinaryContent = () => bytes,
            });
            var proj = new XamarinAndroidApplicationProject()
            {
                ProjectName = "App1",
                References  =
                {
                    new BuildItem.ProjectReference("..\\Library1\\Library1.csproj"),
                },
            };

            rnd.NextBytes(bytes);
            proj.OtherBuildItems.Add(new AndroidItem.AndroidAsset("Assets\\foo.bar")
            {
                BinaryContent = () => bytes,
            });
            using (var libBuilder = CreateBuilderWithoutLogFile(Path.Combine("temp", TestName, lib.ProjectName)))
                using (var builder = CreateBuilderWithoutLogFile(Path.Combine("temp", TestName, proj.ProjectName))) {
                    builder.Target = "Build";
                    libBuilder.Build(lib);
                    builder.Build(proj);

                    rnd.NextBytes(bytes);
                    lib.Touch("Assets\\foo.bar");
                    libBuilder.Build(lib);
                    builder.Target = "SignAndroidPackage";
                    // Profile AndroidAsset change
                    Profile(builder, b => b.Build(proj));
                }
        }
        public void LibraryIncrementalBuild()
        {
            var testPath     = Path.Combine("temp", TestName);
            var class1Source = new BuildItem.Source("Class1.cs")
            {
                TextContent = () => @"
using System;
namespace Lib
{
	public class Class1
	{
		public Class1 ()
		{
		}
	}
}"
            };
            var lib = new XamarinAndroidLibraryProject()
            {
                ProjectName = "Lib",
                ProjectGuid = Guid.NewGuid().ToString(),
                Sources     =
                {
                    class1Source,
                },
            };

            using (var b = CreateDllBuilder(Path.Combine(testPath, "Lib"))) {
                Assert.IsTrue(b.Build(lib), "Build should have succeeded.");
                Assert.IsTrue(b.LastBuildOutput.ContainsText("LogicalName=__AndroidLibraryProjects__.zip") ||
                              b.LastBuildOutput.ContainsText("Lib.obj.Debug.__AndroidLibraryProjects__.zip,__AndroidLibraryProjects__.zip"),
                              "The LogicalName for __AndroidLibraryProjects__.zip should be set.");
                class1Source.Timestamp = DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(1));
                Assert.IsTrue(b.Build(lib), "Build should have succeeded.");
                Assert.IsTrue(b.LastBuildOutput.ContainsText("LogicalName=__AndroidLibraryProjects__.zip") ||
                              b.LastBuildOutput.ContainsText("Lib.obj.Debug.__AndroidLibraryProjects__.zip,__AndroidLibraryProjects__.zip"),
                              "The LogicalName for __AndroidLibraryProjects__.zip should be set.");
            }
        }
        public void MissingSatelliteAssemblyInLibrary()
        {
            var path = Path.Combine("temp", TestName);
            var lib  = new XamarinAndroidLibraryProject {
                ProjectName     = "Localization",
                OtherBuildItems =
                {
                    new BuildItem("EmbeddedResource", "Foo.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancel</value></data>")
                    },
                    new BuildItem("EmbeddedResource", "Foo.es.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancelar</value></data>")
                    }
                }
            };

            var app = new XamarinAndroidApplicationProject {
                IsRelease = true,
            };

            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 = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.IsTrue(libBuilder.Build(lib), "Library Build should have succeeded.");
                    appBuilder.Target = "Build";
                    Assert.IsTrue(appBuilder.Build(app), "App Build should have succeeded.");
                    appBuilder.Target = "SignAndroidPackage";
                    Assert.IsTrue(appBuilder.Build(app), "App SignAndroidPackage should have succeeded.");

                    var apk = Path.Combine(Root, appBuilder.ProjectDirectory,
                                           app.IntermediateOutputPath, "android", "bin", $"{app.PackageName}.apk");
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        Assert.IsTrue(zip.ContainsEntry($"assemblies/es/{lib.ProjectName}.resources.dll"), "Apk should contain satellite assemblies!");
                    }
                }
        }
Example #12
0
        public void FullPath()
        {
            var assetPath = Path.GetFullPath(Path.Combine(Root, "temp", TestName, "Assets", "foo.txt"));

            Directory.CreateDirectory(Path.GetDirectoryName(assetPath));
            File.WriteAllText(assetPath, contents: "bar");
            var proj = new XamarinAndroidLibraryProject {
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset(assetPath)
                    {
                        Metadata ={                { "LogicalName", Path.Combine("Assets", "foo.txt") } },
                    },
                },
            };

            using (var b = CreateDllBuilder(Path.Combine("temp", TestName, "SubDir"))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                var libraryProjectImports = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "__AndroidLibraryProjects__.zip");
                if (Builder.UseDotNet)
                {
                    var aarPath = Path.Combine(Root, b.ProjectDirectory, proj.OutputPath, $"{proj.ProjectName}.aar");
                    FileAssert.Exists(aarPath);
                    using (var aar = ZipHelper.OpenZip(aarPath)) {
                        aar.AssertEntryContents(aarPath, "assets/foo.txt", contents: "bar");
                    }
                    FileAssert.DoesNotExist(libraryProjectImports);
                }
                else
                {
                    FileAssert.Exists(libraryProjectImports);
                    using (var zip = ZipHelper.OpenZip(libraryProjectImports)) {
                        zip.AssertEntryContents(libraryProjectImports, "library_project_imports/assets/foo.txt", contents: "bar");
                    }
                }
            }
        }
        public void CustomLinkDescriptionPreserve([Values(AndroidLinkMode.SdkOnly, AndroidLinkMode.Full)] AndroidLinkMode linkMode)
        {
            AssertHasDevices();

            var lib1 = new XamarinAndroidLibraryProject()
            {
                ProjectName = "Library1",
                Sources     =
                {
                    new BuildItem.Source("SomeClass.cs")
                    {
                        TextContent = () => "namespace Library1 { public class SomeClass { } }"
                    },
                    new BuildItem.Source("NonPreserved.cs")
                    {
                        TextContent = () => "namespace Library1 { public class NonPreserved { } }"
                    },
                    new BuildItem.Source("LinkerClass.cs")
                    {
                        TextContent = () => @"
namespace Library1 {
	public class LinkerClass {
		public LinkerClass () { }

		public bool IsPreserved { get { return true; } }

		public bool ThisMethodShouldBePreserved () { return true; }

		public void WasThisMethodPreserved (string arg1) { }

		[Android.Runtime.Preserve]
		public void PreserveAttribMethod () { }
	}
}",
                    }, new BuildItem.Source("LinkModeFullClass.cs")
                    {
                        TextContent = () => @"
namespace Library1 {
	public class LinkModeFullClass {
		public bool ThisMethodShouldNotBePreserved () { return true; }
	}
}",
                    },
                }
            };

            var lib2 = new DotNetStandard {
                ProjectName       = "LinkTestLib",
                Sdk               = "Microsoft.NET.Sdk",
                TargetFramework   = "netstandard2.0",
                PackageReferences =
                {
                    new Package {
                        Id      = "sqlite-net-pcl",
                        Version = "1.7.335",
                    }
                },
                Sources =
                {
                    new BuildItem.Source("Bug21578.cs")
                    {
                        TextContent = () =>{
                            using (var sr = new StreamReader(typeof(InstallAndRunTests).Assembly.GetManifestResourceStream("Xamarin.Android.Build.Tests.Resources.LinkDescTest.Bug21578.cs")))
                                return(sr.ReadToEnd());
                        },
                    },
                    new BuildItem.Source("Bug35195.cs")
                    {
                        TextContent = () =>{
                            using (var sr = new StreamReader(typeof(InstallAndRunTests).Assembly.GetManifestResourceStream("Xamarin.Android.Build.Tests.Resources.LinkDescTest.Bug35195.cs")))
                                return(sr.ReadToEnd());
                        },
                    },
                },
            };

            if (!Builder.UseDotNet)
            {
                // DataContractSerializer is not trimming safe
                // https://github.com/dotnet/runtime/issues/45559
                lib2.Sources.Add(new BuildItem.Source("Bug36250.cs")
                {
                    TextContent = () => {
                        using (var sr = new StreamReader(typeof(InstallAndRunTests).Assembly.GetManifestResourceStream("Xamarin.Android.Build.Tests.Resources.LinkDescTest.Bug36250.cs")))
                            return(sr.ReadToEnd());
                    },
                });
            }

            proj = new XamarinFormsAndroidApplicationProject()
            {
                IsRelease = true,
                AndroidLinkModeRelease = linkMode,
                References             =
                {
                    new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"),
                    new BuildItem("ProjectReference", "..\\LinkTestLib\\LinkTestLib.csproj"),
                },
                OtherBuildItems =
                {
                    new BuildItem("LinkDescription", "linker.xml")
                    {
                        TextContent = () => linkMode == AndroidLinkMode.SdkOnly ? "<linker/>" : @"
<linker>
  <assembly fullname=""Library1"">
    <type fullname=""Library1.LinkerClass"">
      <method name="".ctor"" />
      <method name=""WasThisMethodPreserved"" />
      <method name=""get_IsPreserved"" />
    </type>
  </assembly>
  <assembly fullname=""LinkTestLib"">
    <type fullname=""LinkTestLib.TodoTask"" />
  </assembly>
</linker>
",
                    },
                },
            };
            if (Builder.UseDotNet)
            {
                // NOTE: workaround for netcoreapp3.1 dependency preferred over monoandroid8.0
                proj.PackageReferences.Add(new Package {
                    Id      = "SQLitePCLRaw.lib.e_sqlite3.android",
                    Version = "2.0.4",
                });
            }

            proj.AndroidManifest = proj.AndroidManifest.Replace("</manifest>", "<uses-permission android:name=\"android.permission.INTERNET\" /></manifest>");
            proj.SetAndroidSupportedAbis("armeabi-v7a", "arm64-v8a", "x86", "x86_64");
            using (var sr = new StreamReader(typeof(InstallAndRunTests).Assembly.GetManifestResourceStream("Xamarin.Android.Build.Tests.Resources.LinkDescTest.MainActivityReplacement.cs")))
                proj.MainActivity = sr.ReadToEnd();

            // 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.");

            builder = CreateApkBuilder(Path.Combine(rootPath, proj.ProjectName));
            Assert.IsTrue(builder.Install(proj), "First install should have succeeded.");

            ClearAdbLogcat();
            if (CommercialBuildAvailable)
            {
                Assert.True(builder.RunTarget(proj, "_Run"), "Project should have run.");
            }
            else
            {
                AdbStartActivity($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity");
            }

            var logcatPath = Path.Combine(Root, builder.ProjectDirectory, "logcat.log");

            Assert.IsTrue(MonitorAdbLogcat((line) => {
                return(line.Contains("All regression tests completed."));
            }, logcatPath, 90), "Linker test app did not run successfully.");

            var logcatOutput = File.ReadAllText(logcatPath);

            StringAssert.Contains("[PASS]", logcatOutput);
            StringAssert.DoesNotContain("[FAIL]", logcatOutput);
            if (linkMode == AndroidLinkMode.Full)
            {
                StringAssert.Contains("[LINKALLPASS]", logcatOutput);
                StringAssert.DoesNotContain("[LINKALLFAIL]", logcatOutput);
            }
        }
Example #14
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}'.");
            }
        }
Example #15
0
        public void CheckWarningsRaisedForDuplicateResourcesAcrossEntireProject()
        {
            var lib1 = new XamarinAndroidLibraryProject()
            {
                ProjectName      = "Library1",
                AndroidResources =
                {
                    new AndroidItem.AndroidResource("Resources\\values\\Styles.xml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<style name=""Foo"" />
</resources>"
                    },
                }
            };
            var stringRes = lib1.AndroidResources.First(x => x.Include() == "Resources\\values\\Strings.xml");

            stringRes.TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""library_name"">Library1</string>
	<string name=""some_string_value"">Hello Me</string>
</resources>";

            var proj = new XamarinAndroidApplicationProject()
            {
                References       = { new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj") },
                AndroidResources =
                {
                    new AndroidItem.AndroidResource("Resources\\values\\Styles.xml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<style name=""CustomText"">
		<item name=""android:textSize"">20sp</item>
		<item name=""android:textColor"">#008</item>
	</style>
</resources>"
                    },
                },
            };

            stringRes             = proj.AndroidResources.First(x => x.Include() == "Resources\\values\\Strings.xml");
            stringRes.TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""hello"">Hello World, Click Me!</string>
	<string name=""app_name"">Application one</string>
	<string name=""some_string_value"">Hello Me From the App</string>
</resources>";

            var projectPath = string.Format("temp/CheckWarningsRaisedForDuplicateResourcesAcrossEntireProject");

            using (var dllBuilder = CreateDllBuilder(Path.Combine(projectPath, "Library1"))) {
                dllBuilder.Verbosity = LoggerVerbosity.Diagnostic;
                dllBuilder.Build(lib1);
                using (var b = CreateApkBuilder(Path.Combine(projectPath, "UnamedApp"))) {
                    b.Verbosity           = LoggerVerbosity.Diagnostic;
                    b.ThrowOnBuildFailure = false;
                    Assert.IsTrue(b.Build(proj), "Build should have succeeded");
                    StringAssert.Contains("XA5215: Duplicate Resource found for", b.LastBuildOutput);
                    var stylesXml = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "res", "values", "styles.xml");
                    Assert.IsTrue(File.Exists(stylesXml), "{0} should exist", stylesXml);
                    var doc = XDocument.Load(stylesXml);
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "CustomText"), "CustomText should exist in styles.xml");
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "Foo"), "Foo should exist in styles.xml");
                    var stringsXml = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "res", "values", "strings.xml");
                    Assert.IsTrue(File.Exists(stringsXml), "{0} should exist", stylesXml);
                    doc = XDocument.Load(stringsXml);
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "some_string_value"), "some_string_value should exist in strings.xml");
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "some_string_value" && x.Value == "Hello Me From the App"),
                                  "some_string_value should have the value of \"Hello Me From the App\"");
                }
            }
        }
Example #16
0
        public void BuildAMassiveApp()
        {
            var testPath = Path.Combine("temp", "BuildAMassiveApp");

            TestOutputDirectories [TestContext.CurrentContext.Test.ID] = Path.Combine(Root, testPath);
            var sb = new SolutionBuilder("BuildAMassiveApp.sln")
            {
                SolutionPath = Path.Combine(Root, testPath),
            };
            var app1 = new XamarinFormsMapsApplicationProject {
                TargetFrameworkVersion = sb.LatestTargetFrameworkVersion(),
                ProjectName            = "App1",
                AotAssemblies          = true,
                IsRelease = true,
            };

            //NOTE: BuildingInsideVisualStudio prevents the projects from being built as dependencies
            sb.BuildingInsideVisualStudio = false;
            app1.Imports.Add(new Import("foo.targets")
            {
                TextContent = () => @"<?xml version=""1.0"" encoding=""utf-16""?>
<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
<Target Name=""_CheckAbis"" BeforeTargets=""_DefineBuildTargetAbis"">
	<PropertyGroup>
		<AndroidSupportedAbis>armeabi-v7a;x86</AndroidSupportedAbis>
		<AndroidSupportedAbis Condition=""Exists('$(MSBuildThisFileDirectory)..\..\..\..\Debug\lib\xamarin.android\xbuild\Xamarin\Android\lib\arm64-v8a\libmono-android.release.so')"">$(AndroidSupportedAbis);arm64-v8a</AndroidSupportedAbis>
		<AndroidSupportedAbis Condition=""Exists('$(MSBuildThisFileDirectory)..\..\..\..\Debug\lib\xamarin.android\xbuild\Xamarin\Android\lib\x86_64\libmono-android.release.so')"">$(AndroidSupportedAbis);x86_64</AndroidSupportedAbis>
	</PropertyGroup>
	<Message Text=""$(AndroidSupportedAbis)"" />
</Target>
<Target Name=""_Foo"" AfterTargets=""_SetLatestTargetFrameworkVersion"">
	<PropertyGroup>
		<AotAssemblies Condition=""!Exists('$(MonoAndroidBinDirectory)"         + Path.DirectorySeparatorChar + @"cross-arm')"">False</AotAssemblies>
	</PropertyGroup>
	<Message Text=""$(AotAssemblies)"" />
</Target>
</Project>
",
            });
            sb.Projects.Add(app1);
            var code = new StringBuilder();

            code.AppendLine("using System;");
            code.AppendLine("namespace App1 {");
            code.AppendLine("\tpublic class AppCode {");
            code.AppendLine("\t\tpublic void Foo () {");
            for (int i = 0; i < 128; i++)
            {
                var libName = $"Lib{i}";
                var lib     = new XamarinAndroidLibraryProject()
                {
                    TargetFrameworkVersion = sb.LatestTargetFrameworkVersion(),
                    ProjectName            = libName,
                    IsRelease       = true,
                    OtherBuildItems =
                    {
                        new AndroidItem.AndroidAsset($"Assets\\{libName}.txt")
                        {
                            TextContent = () => "Asset1",
                            Encoding    = Encoding.ASCII,
                        },
                        new AndroidItem.AndroidAsset($"Assets\\subfolder\\{libName}.txt")
                        {
                            TextContent = () => "Asset2",
                            Encoding    = Encoding.ASCII,
                        },
                    },
                    Sources =
                    {
                        new BuildItem.Source($"{libName}.cs")
                        {
                            TextContent = () => @"using System;

namespace " + libName + @" {

	public class "     + libName + @" {
		public static void Foo () {
		}
	}
}"
                        },
                    }
                };
                var strings = lib.AndroidResources.First(x => x.Include() == "Resources\\values\\Strings.xml");
                strings.TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name="""     + libName + @"_name"">" + libName + @"</string>
</resources>";
                sb.Projects.Add(lib);
                app1.References.Add(new BuildItem.ProjectReference($"..\\{libName}\\{libName}.csproj", libName, lib.ProjectGuid));
                code.AppendLine($"\t\t\t{libName}.{libName}.Foo ();");
            }
            code.AppendLine("\t\t}");
            code.AppendLine("\t}");
            code.AppendLine("}");
            app1.Sources.Add(new BuildItem.Source("Code.cs")
            {
                TextContent = () => code.ToString(),
            });
            Assert.IsTrue(sb.Build(new string [] { "Configuration=Release" }), "Solution should have built.");
            Assert.IsTrue(sb.BuildProject(app1, "SignAndroidPackage"), "Build of project should have succeeded");
            sb.Dispose();
        }
Example #17
0
        public void InternationalResourceTest([Values(false, true)] bool explicitCrunch)
        {
            var library = new XamarinAndroidLibraryProject()
            {
                ProjectName      = "Library1",
                AndroidResources =
                {
                    new AndroidItem.AndroidResource("Resources\\values-de\\Strings.xml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""greeting"">Ja</string>
</resources>",
                    },
                },
            };

            var strings = library.AndroidResources.First(x => x.Include() == "Resources\\values\\Strings.xml");

            strings.TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""greeting"">Yes</string>
	<string name=""library_name"">Library1</string>
</resources>";
            var project = new XamarinAndroidApplicationProject()
            {
                ProjectName           = "Application1",
                AndroidExplicitCrunch = explicitCrunch,
                References            = { new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj") },
                AndroidResources      =
                {
                    new AndroidItem.AndroidResource("Resources\\values-de\\Strings.xml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""hello"">Hallo Welt, Klick mich!</string>
</resources>",
                    }
                },
            };
            var projectPath = string.Format("temp/InternationalResourceTest{0}", explicitCrunch);

            using (var dllBuilder = CreateDllBuilder(Path.Combine(projectPath, "Library1"))) {
                dllBuilder.Verbosity = LoggerVerbosity.Diagnostic;
                Assert.IsTrue(dllBuilder.Build(library), "Library1 build should have succeeded");
                using (var b = CreateApkBuilder(Path.Combine(projectPath, "Application1"))) {
                    b.Verbosity           = LoggerVerbosity.Diagnostic;
                    b.ThrowOnBuildFailure = false;
                    Assert.IsTrue(b.Build(project), "Applications1 build should have succeeded");

                    var stringsXml = Path.Combine(Root, b.ProjectDirectory, project.IntermediateOutputPath, "res", "values", "strings.xml");
                    Assert.IsTrue(File.Exists(stringsXml), "{0} should exist", stringsXml);
                    var doc = XDocument.Load(stringsXml);
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "greeting" && x.Value == "Yes"), "greeting should have a value of Yes");
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "hello" && x.Value == "Hello World, Click Me!"), "hello should have a value of Hello World, Click Me!");

                    var stringsXml_de = Path.Combine(Root, b.ProjectDirectory, project.IntermediateOutputPath, "res", "values-de", "strings.xml");
                    Assert.IsTrue(File.Exists(stringsXml), "{0} should exist", stringsXml_de);

                    doc = XDocument.Load(stringsXml_de);
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "greeting" && x.Value == "Ja"), "greeting should have a value of Ja");
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "hello" && x.Value == "Hallo Welt, Klick mich!"), "hello should have a value of Hallo Welt, Klick mich!");

                    Assert.IsTrue(dllBuilder.Build(library), "Second Library1 build should have succeeded");
                    Assert.IsTrue(b.Build(project), "Second Applications1 build should have succeeded");

                    var strings_de = (AndroidItem.AndroidResource)library.AndroidResources.First(x => x.Include() == "Resources\\values-de\\Strings.xml");
                    strings_de.TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""greeting"">Foo</string>
</resources>";
                    strings_de.Timestamp   = DateTime.Now;

                    Assert.IsTrue(dllBuilder.Build(library), "Third Library1 build should have succeeded");
                    Assert.IsTrue(b.Build(project), "Third Applications1 build should have succeeded");

                    doc = XDocument.Load(stringsXml_de);
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "greeting" && x.Value == "Foo"), "greeting should have a value of Foo");
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "hello" && x.Value == "Hallo Welt, Klick mich!"), "hello should have a value of Hallo Welt, Klick mich!");

                    Directory.Delete(projectPath, recursive: true);
                }
            }
        }
Example #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}'.");
            }
        }
Example #19
0
        public void MergeResources([Values(false, true)] bool explicitCrunch)
        {
            var lib1 = new XamarinAndroidLibraryProject()
            {
                ProjectName      = "Library1",
                AndroidResources = { new AndroidItem.AndroidResource("Resources\\values\\Colors.xml")
                                     {
                                         TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<color name=""dark_red"">#440000</color>
	<color name=""dark_blue"">#000044</color>
</resources>"
                                     }, }
            };

            var proj = new XamarinAndroidApplicationProject()
            {
                AndroidExplicitCrunch = explicitCrunch,
                References            = { new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj") },
                AndroidResources      = { new AndroidItem.AndroidResource("Resources\\values\\Values.xml")
                                          {
                                              TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<color name=""dark_red"">#FF0000</color>
	<color name=""xamarin_green"">#00FF00</color>
	<color name=""xamarin_green1"">#00FF00</color>
</resources>"
                                          },
                                          new AndroidItem.AndroidResource("Resources\\values\\Colors.xml")
                                          {
                                              TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<color name=""dark_blue"">#0000FF</color>
</resources>"
                                          }, },
            };
            var projectPath = string.Format("temp/MergeResources_{0}", explicitCrunch);

            using (var dllBuilder = CreateDllBuilder(Path.Combine(projectPath, "Library1"), false, false)) {
                dllBuilder.Verbosity = LoggerVerbosity.Diagnostic;
                Assert.IsTrue(dllBuilder.Build(lib1), "Library project should have built");
                using (var b = CreateApkBuilder(Path.Combine(projectPath, "UnamedApp"), false, false)) {
                    b.Verbosity           = LoggerVerbosity.Diagnostic;
                    b.ThrowOnBuildFailure = false;
                    Assert.IsTrue(b.Build(proj), "Build should have succeeded");
                    StringAssert.Contains("XA5215: Duplicate Resource found for", b.LastBuildOutput);
                    var colorsXml = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "res", "values", "colors.xml");
                    Assert.IsTrue(File.Exists(colorsXml), "{0} should exist", colorsXml);
                    var doc = XDocument.Load(colorsXml);
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "dark_red" && x.Value == "#FF0000"), "dark_red should have a value of #FF0000");
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "dark_blue" && x.Value == "#0000FF"), "dark_blue should have a value of #0000FF");

                    var valuesXml = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "res", "values", "values.xml");
                    Assert.IsTrue(File.Exists(valuesXml), "{0} should exist", valuesXml);
                    doc = XDocument.Load(valuesXml);
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "xamarin_green"), "xamarin_green should exist in values.xml");
                    Assert.IsFalse(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "dark_red"), "dark_red should exist in values.xml");
                    Assert.IsFalse(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "dark_blue"), "dark_blue should not exist in values.xml");

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

                    var values = (AndroidItem.AndroidResource)proj.AndroidResources.First(x => x.Include() == "Resources\\values\\Values.xml");
                    values.TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<color name=""dark_red"">#FFFFFF</color>
	<color name=""xamarin_green"">#00AA00</color>
</resources>";
                    values.Timestamp   = DateTime.Now;
                    Assert.IsTrue(b.Build(proj), "Third Build should have succeeded");

                    Assert.IsTrue(File.Exists(colorsXml), "{0} should exist", colorsXml);
                    doc = XDocument.Load(colorsXml);
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "dark_red" && x.Value == "#FFFFFF"), "dark_red should have a value of #FFFFFF");
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "dark_blue" && x.Value == "#0000FF"), "dark_blue should have a value of #0000FF");

                    Assert.IsTrue(File.Exists(valuesXml), "{0} should exist", valuesXml);
                    doc = XDocument.Load(valuesXml);
                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "xamarin_green"), "xamarin_green should exist in values.xml");
                    Assert.IsFalse(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "dark_red"), "dark_red should not exist in values.xml");
                    Assert.IsFalse(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "dark_blue"), "dark_blue should not exist in values.xml");

                    Assert.IsTrue(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "xamarin_green" && x.Value == "#00AA00"), "xamarin_green should have a value of #00AA00");
                    Assert.IsFalse(doc.Element("resources").Elements().Any(x => x.Attribute("name").Value == "xamarin_green1"), "xamarin_green1 should not exist in values.xml");

                    Directory.Delete(projectPath, recursive: true);
                }
            }
        }
Example #20
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();
                }
        }
Example #21
0
        public void CheckAssetsAreIncludedInAPK([Values(true, false)] bool useAapt2)
        {
            AssertAaptSupported(useAapt2);
            var projectPath = Path.Combine("temp", TestName);
            var libproj     = new XamarinAndroidLibraryProject()
            {
                ProjectName     = "Library1",
                IsRelease       = true,
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset("Assets\\asset1.txt")
                    {
                        TextContent = () => "Asset1",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\")
                    {
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset2.txt")
                    {
                        TextContent = () => "Asset2",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset5.txt")
                    {
                        TextContent = () => "Asset5",
                        Encoding    = Encoding.ASCII,
                        Metadata    = { { "LogicalName", Path.Combine(Path.GetPathRoot(Root), "Assets", "subfolder", "asset5.txt") } },
                    },
                }
            };
            var proj = new XamarinAndroidApplicationProject()
            {
                ProjectName     = "App1",
                IsRelease       = true,
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset("Assets\\asset3.txt")
                    {
                        TextContent = () => "Asset3",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\")
                    {
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset4.txt")
                    {
                        TextContent = () => "Asset4",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset6.txt")
                    {
                        TextContent = () => "Asset6",
                        Encoding    = Encoding.ASCII,
                        Metadata    = { { "LogicalName", Path.Combine(Path.GetPathRoot(Root), "Assets", "subfolder", "asset6.txt") } },
                    },
                }
            };

            proj.AndroidUseAapt2 = useAapt2;
            proj.References.Add(new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"));
            using (var libb = CreateDllBuilder(Path.Combine(projectPath, libproj.ProjectName))) {
                Assert.IsTrue(libb.Build(libproj), "{0} should have built successfully.", libproj.ProjectName);
                using (var b = CreateApkBuilder(Path.Combine(projectPath, proj.ProjectName))) {
                    Assert.IsTrue(b.Build(proj), "{0} should have built successfully.", proj.ProjectName);
                    using (var apk = ZipHelper.OpenZip(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "bin", $"{proj.PackageName}.apk"))) {
                        foreach (var a in libproj.OtherBuildItems.Where(x => x is AndroidItem.AndroidAsset))
                        {
                            var item = a.Include().ToLower().Replace("\\", "/");
                            if (item.EndsWith("/"))
                            {
                                continue;
                            }
                            var data = ZipHelper.ReadFileFromZip(apk, item);
                            Assert.IsNotNull(data, "{0} should be in the apk.", item);
                            Assert.AreEqual(a.TextContent(), Encoding.ASCII.GetString(data), "The Contents of {0} should be \"{1}\"", item, a.TextContent());
                        }
                        foreach (var a in proj.OtherBuildItems.Where(x => x is AndroidItem.AndroidAsset))
                        {
                            var item = a.Include().ToLower().Replace("\\", "/");
                            if (item.EndsWith("/"))
                            {
                                continue;
                            }
                            var data = ZipHelper.ReadFileFromZip(apk, item);
                            Assert.IsNotNull(data, "{0} should be in the apk.", item);
                            Assert.AreEqual(a.TextContent(), Encoding.ASCII.GetString(data), "The Contents of {0} should be \"{1}\"", item, a.TextContent());
                        }
                    }
                    Directory.Delete(Path.Combine(Root, projectPath), recursive: true);
                }
            }
        }
        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!");
                            }
                        }
                    }
                }
        }
Example #23
0
        public void Check9PatchFilesAreProcessed([Values(false, true)] bool explicitCrunch)
        {
            var projectPath = string.Format("temp/Check9PatchFilesAreProcessed_{0}", explicitCrunch.ToString());
            var libproj     = new XamarinAndroidLibraryProject()
            {
                ProjectName = "Library1"
            };

            using (var stream = typeof(XamarinAndroidCommonProject).Assembly.GetManifestResourceStream("Xamarin.ProjectTools.Resources.Base.Image.9.png")) {
                var image_data = new byte [stream.Length];
                stream.Read(image_data, 0, (int)stream.Length);
                var image2 = new AndroidItem.AndroidResource("Resources\\drawable\\Image2.9.png")
                {
                    BinaryContent = () => image_data
                };
                libproj.AndroidResources.Add(image2);
            }
            using (var libb = CreateDllBuilder(Path.Combine(projectPath, "Library1"))) {
                libb.Build(libproj);
                var proj = new XamarinAndroidApplicationProject();
                using (var stream = typeof(XamarinAndroidCommonProject).Assembly.GetManifestResourceStream("Xamarin.ProjectTools.Resources.Base.Image.9.png")) {
                    var image_data = new byte [stream.Length];
                    stream.Read(image_data, 0, (int)stream.Length);
                    var image1 = new AndroidItem.AndroidResource("Resources\\drawable\\Image1.9.png")
                    {
                        BinaryContent = () => image_data
                    };
                    proj.AndroidResources.Add(image1);
                }
                proj.References.Add(new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"));
                proj.Packages.Add(KnownPackages.AndroidSupportV4_21_0_3_0);
                proj.Packages.Add(KnownPackages.SupportV7AppCompat_21_0_3_0);
                proj.Packages.Add(KnownPackages.SupportV7MediaRouter_21_0_3_0);
                proj.Packages.Add(KnownPackages.GooglePlayServices_22_0_0_2);
                proj.AndroidExplicitCrunch = explicitCrunch;
                proj.SetProperty("TargetFrameworkVersion", "v5.0");
                proj.SetProperty(proj.DebugProperties, "JavaMaximumHeapSize", "1G");
                proj.SetProperty(proj.ReleaseProperties, "JavaMaximumHeapSize", "1G");
                using (var b = CreateApkBuilder(Path.Combine(projectPath, "Application1"), false, false)) {
                    b.Verbosity = LoggerVerbosity.Diagnostic;
                    Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                    var path = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android/bin/packaged_resources");
                    var data = ZipHelper.ReadFileFromZip(path, "res/drawable/image1.9.png");
                    Assert.IsNotNull(data, "image1.9.png should be in {0}android/bin/packaged_resources",
                                     proj.IntermediateOutputPath);
                    var png = PNGChecker.LoadFromBytes(data);
                    Assert.IsTrue(png.Is9Patch, "image1.9.png should have been processed into a 9 patch image.");
                    data = ZipHelper.ReadFileFromZip(path, "res/drawable/image2.9.png");
                    Assert.IsNotNull(data, "image2.9.png should be in {0}android/bin/packaged_resources",
                                     proj.IntermediateOutputPath);
                    png = PNGChecker.LoadFromBytes(data);
                    Assert.IsTrue(png.Is9Patch, "image2.9.png should have been processed into a 9 patch image.");
                    data = ZipHelper.ReadFileFromZip(path, "res/drawable-hdpi-v4/common_signin_btn_icon_normal_dark.9.png");
                    Assert.IsNotNull(data, "common_signin_btn_icon_normal_dark.9.png should be in {0}android/bin/packaged_resources",
                                     proj.IntermediateOutputPath);
                    png = PNGChecker.LoadFromBytes(data);
                    Assert.IsTrue(png.Is9Patch, "common_signin_btn_icon_normal_dark.9.png should have been processed into a 9 patch image.");
                    Directory.Delete(Path.Combine(Root, projectPath), recursive: true);
                }
            }
        }
        public void ResolveNativeLibrariesInManagedReferences([Values(true, false)] bool useShortFileNames)
        {
            var lib = new XamarinAndroidLibraryProject()
            {
                ProjectName     = "Lib",
                IsRelease       = true,
                ProjectGuid     = Guid.NewGuid().ToString(),
                OtherBuildItems =
                {
                    new BuildItem(AndroidBuildActions.EmbeddedNativeLibrary, "libs/armeabi-v7a/libfoo.so")
                    {
                        TextContent = () => string.Empty,
                        Encoding    = Encoding.ASCII,
                    }
                },
                Sources =
                {
                    new BuildItem.Source("Class1.cs")
                    {
                        TextContent = () => @"
using System;
namespace Lib
{
	public class Class1
	{
		public Class1 ()
		{
		}
	}
}"
                    },
                },
            };

            lib.SetProperty(lib.ActiveConfigurationProperties, "UseShortFileNames", useShortFileNames);
            var so = lib.OtherBuildItems.First(x => x.Include() == "libs/armeabi-v7a/libfoo.so");

            var lib2 = new XamarinAndroidLibraryProject()
            {
                ProjectName     = "Lib2",
                ProjectGuid     = Guid.NewGuid().ToString(),
                IsRelease       = true,
                OtherBuildItems =
                {
                    new BuildItem(AndroidBuildActions.EmbeddedNativeLibrary, "libs/armeabi-v7a/libfoo2.so")
                    {
                        TextContent = () => string.Empty,
                        Encoding    = Encoding.ASCII,
                    },
                    new BuildItem.ProjectReference(@"..\Lib\Lib.csproj",     "Lib", lib.ProjectGuid)
                    {
                    }
                },
                Sources =
                {
                    new BuildItem.Source("Class2.cs")
                    {
                        TextContent = () => @"
using System;
namespace Lib2
{
	public class Class2
	{
		public Class2 ()
		{
			var c = new Lib.Class1 ();
		}
	}
}"
                    },
                },
            };

            lib2.SetProperty(lib.ActiveConfigurationProperties, "UseShortFileNames", useShortFileNames);
            var path = Path.Combine(Root, "temp", $"ResolveNativeLibrariesInManagedReferences_{useShortFileNames}");

            using (var libbuilder = CreateDllBuilder(Path.Combine(path, "Lib"))) {
                Assert.IsTrue(libbuilder.Build(lib), "lib 1st. build failed");

                using (var libbuilder2 = CreateDllBuilder(Path.Combine(path, "Lib2"))) {
                    Assert.IsTrue(libbuilder2.Build(lib2), "lib 1st. build failed");

                    var app = new XamarinAndroidApplicationProject()
                    {
                        ProjectName     = "App",
                        IsRelease       = true,
                        OtherBuildItems =
                        {
                            new BuildItem.ProjectReference(@"..\Lib2\Lib2.csproj", "Lib2", lib2.ProjectGuid),
                        }
                    };
                    app.SetProperty(app.ActiveConfigurationProperties, "UseShortFileNames", useShortFileNames);
                    using (var builder = CreateApkBuilder(Path.Combine(path, "App"))) {
                        builder.Verbosity = LoggerVerbosity.Diagnostic;
                        Assert.IsTrue(builder.Build(app), "app 1st. build failed");

                        var libfoo = ZipHelper.ReadFileFromZip(Path.Combine(Root, builder.ProjectDirectory, app.OutputPath, app.PackageName + "-Signed.apk"),
                                                               "lib/armeabi-v7a/libfoo.so");
                        Assert.IsNotNull(libfoo, "libfoo.so should exist in the .apk");

                        so.TextContent = () => "newValue";
                        so.Timestamp   = DateTimeOffset.UtcNow;
                        Assert.IsTrue(libbuilder.Build(lib), "lib 2nd. build failed");
                        Assert.IsTrue(libbuilder2.Build(lib2), "lib 2nd. build failed");
                        Assert.IsTrue(builder.Build(app), "app 2nd. build failed");

                        Assert.IsNotNull(libfoo, "libfoo.so should exist in the .apk");

                        Assert.AreEqual(so.TextContent().Length, new FileInfo(Path.Combine(Root, libbuilder.ProjectDirectory, lib.IntermediateOutputPath,
                                                                                           useShortFileNames ? "nl" : "native_library_imports", "armeabi-v7a", "libfoo.so")).Length,
                                        "intermediate size mismatch");
                        libfoo = ZipHelper.ReadFileFromZip(Path.Combine(Root, builder.ProjectDirectory, app.OutputPath, app.PackageName + "-Signed.apk"),
                                                           "lib/armeabi-v7a/libfoo.so");
                        Assert.AreEqual(so.TextContent().Length, libfoo.Length, "compressed size mismatch");
                        var libfoo2 = ZipHelper.ReadFileFromZip(Path.Combine(Root, builder.ProjectDirectory, app.OutputPath, app.PackageName + "-Signed.apk"),
                                                                "lib/armeabi-v7a/libfoo2.so");
                        Assert.IsNotNull(libfoo2, "libfoo2.so should exist in the .apk");
                        Directory.Delete(path, recursive: true);
                    }
                }
            }
        }
Example #25
0
        public void CheckResouceIsOverridden([Values(true, false)] bool useAapt2)
        {
            AssertHasDevices();
            AssertAaptSupported(useAapt2);

            var library = new XamarinAndroidLibraryProject()
            {
                ProjectName      = "Library1",
                AndroidResources =
                {
                    new AndroidItem.AndroidResource(() => "Resources\\values\\strings2.xml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""hello_me"">Click Me! One</string>
</resources>",
                    },
                },
            };
            var library2 = new XamarinAndroidLibraryProject()
            {
                ProjectName      = "Library2",
                AndroidResources =
                {
                    new AndroidItem.AndroidResource(() => "Resources\\values\\strings2.xml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""hello_me"">Click Me! Two</string>
</resources>",
                    },
                },
            };
            var app = new XamarinAndroidApplicationProject()
            {
                PackageName = "Xamarin.ResourceTest",
                References  =
                {
                    new BuildItem.ProjectReference("..\\Library1\\Library1.csproj"),
                    new BuildItem.ProjectReference("..\\Library2\\Library2.csproj"),
                },
            };

            library.AndroidUseAapt2      =
                library2.AndroidUseAapt2 =
                    app.AndroidUseAapt2  = useAapt2;
            app.LayoutMain = app.LayoutMain.Replace("@string/hello", "@string/hello_me");
            using (var l1 = CreateApkBuilder(Path.Combine("temp", TestName, library.ProjectName)))
                using (var l2 = CreateApkBuilder(Path.Combine("temp", TestName, library2.ProjectName)))
                    using (var b = CreateApkBuilder(Path.Combine("temp", TestName, app.ProjectName))) {
                        b.ThrowOnBuildFailure = false;
                        string apiLevel;
                        app.TargetFrameworkVersion = b.LatestTargetFrameworkVersion(out apiLevel);
                        app.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=""{app.PackageName}"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest> ";
                        Assert.IsTrue(l1.Build(library, doNotCleanupOnUpdate: true), $"Build of {library.ProjectName} should have suceeded.");
                        Assert.IsTrue(l2.Build(library2, doNotCleanupOnUpdate: true), $"Build of {library2.ProjectName} should have suceeded.");
                        b.BuildLogFile = "build1.log";
                        Assert.IsTrue(b.Build(app, doNotCleanupOnUpdate: true), $"Build of {app.ProjectName} should have suceeded.");
                        b.BuildLogFile = "install1.log";
                        Assert.IsTrue(b.Install(app, doNotCleanupOnUpdate: true), "Install should have suceeded.");
                        AdbStartActivity($"{app.PackageName}/{app.JavaPackageName}.MainActivity");
                        WaitForPermissionActivity(Path.Combine(Root, builder.ProjectDirectory, "permission-logcat.log"));
                        WaitForActivityToStart(app.PackageName, "MainActivity",
                                               Path.Combine(Root, builder.ProjectDirectory, "startup-logcat.log"), 15);
                        XDocument ui   = GetUI();
                        XElement  node = ui.XPathSelectElement($"//node[contains(@resource-id,'myButton')]");
                        StringAssert.AreEqualIgnoringCase("Click Me! One", node.Attribute("text").Value, "Text of Button myButton should have been \"Click Me! One\"");
                        b.BuildLogFile = "clean.log";
                        Assert.IsTrue(b.Clean(app, doNotCleanupOnUpdate: true), "Clean should have suceeded.");

                        app = new XamarinAndroidApplicationProject()
                        {
                            PackageName = "Xamarin.ResourceTest",
                            References  =
                            {
                                new BuildItem.ProjectReference("..\\Library1\\Library1.csproj"),
                                new BuildItem.ProjectReference("..\\Library2\\Library2.csproj"),
                            },
                        };

                        library2.References.Add(new BuildItem.ProjectReference("..\\Library1\\Library1.csproj"));
                        app.AndroidUseAapt2        = useAapt2;
                        app.LayoutMain             = app.LayoutMain.Replace("@string/hello", "@string/hello_me");
                        app.TargetFrameworkVersion = b.LatestTargetFrameworkVersion(out apiLevel);
                        app.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=""{app.PackageName}"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest> ";
                        b.BuildLogFile             = "build.log";
                        Assert.IsTrue(b.Build(app, doNotCleanupOnUpdate: true), $"Build of {app.ProjectName} should have suceeded.");
                        b.BuildLogFile = "install.log";
                        Assert.IsTrue(b.Install(app, doNotCleanupOnUpdate: true), "Install should have suceeded.");
                        AdbStartActivity($"{app.PackageName}/{app.JavaPackageName}.MainActivity");
                        WaitForPermissionActivity(Path.Combine(Root, builder.ProjectDirectory, "permission-logcat.log"));
                        WaitForActivityToStart(app.PackageName, "MainActivity",
                                               Path.Combine(Root, builder.ProjectDirectory, "startup-logcat.log"), 15);
                        ui   = GetUI();
                        node = ui.XPathSelectElement($"//node[contains(@resource-id,'myButton')]");
                        StringAssert.AreEqualIgnoringCase("Click Me! One", node.Attribute("text").Value, "Text of Button myButton should have been \"Click Me! One\"");
                    }
        }
Example #26
0
        public void CheckAssetsAreIncludedInAPK()
        {
            var projectPath = string.Format("temp/CheckAssetsAreIncludedInAPK");
            var libproj     = new XamarinAndroidLibraryProject()
            {
                ProjectName     = "Library1",
                IsRelease       = true,
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset("Assets\\asset1.txt")
                    {
                        TextContent = () => "Asset1",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset2.txt")
                    {
                        TextContent = () => "Asset2",
                        Encoding    = Encoding.ASCII,
                    },
                }
            };
            var proj = new XamarinAndroidApplicationProject()
            {
                ProjectName     = "App1",
                IsRelease       = true,
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset("Assets\\asset3.txt")
                    {
                        TextContent = () => "Asset3",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset4.txt")
                    {
                        TextContent = () => "Asset4",
                        Encoding    = Encoding.ASCII,
                    },
                }
            };

            proj.References.Add(new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"));
            using (var libb = CreateDllBuilder(Path.Combine(projectPath, libproj.ProjectName))) {
                Assert.IsTrue(libb.Build(libproj), "{0} should have built successfully.", libproj.ProjectName);
                using (var b = CreateApkBuilder(Path.Combine(projectPath, proj.ProjectName))) {
                    Assert.IsTrue(b.Build(proj), "{0} should have built successfully.", proj.ProjectName);
                    using (var apk = ZipHelper.OpenZip(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "bin", "packaged_resources"))) {
                        foreach (var a in libproj.OtherBuildItems.Where(x => x is AndroidItem.AndroidAsset))
                        {
                            var item = a.Include().ToLower().Replace("\\", "/");
                            var data = ZipHelper.ReadFileFromZip(apk, item);
                            Assert.IsNotNull(data, "{0} should be in the apk.", item);
                            Assert.AreEqual(a.TextContent(), Encoding.ASCII.GetString(data), "The Contents of {0} should be \"{1}\"", item, a.TextContent());
                        }
                        foreach (var a in proj.OtherBuildItems.Where(x => x is AndroidItem.AndroidAsset))
                        {
                            var item = a.Include().ToLower().Replace("\\", "/");
                            var data = ZipHelper.ReadFileFromZip(apk, item);
                            Assert.IsNotNull(data, "{0} should be in the apk.", item);
                            Assert.AreEqual(a.TextContent(), Encoding.ASCII.GetString(data), "The Contents of {0} should be \"{1}\"", item, a.TextContent());
                        }
                    }
                    Directory.Delete(Path.Combine(Root, projectPath), recursive: true);
                }
            }
        }
        public void LibraryProjectTargetsDoNotBreak()
        {
            var targets = new [] {
                "_CreateNativeLibraryArchive",
                "_CreateManagedLibraryResourceArchive",
            };
            var proj = new XamarinAndroidLibraryProject {
                Sources =
                {
                    new BuildItem.Source("Class1.cs")
                    {
                        TextContent = () => "public class Class1 { }"
                    },
                },
                OtherBuildItems =
                {
                    new AndroidItem.EmbeddedNativeLibrary("foo\\armeabi-v7a\\libtest.so")
                    {
                        BinaryContent  = () => new byte [10],
                        MetadataValues = "Link=libs\\armeabi-v7a\\libtest.so",
                    },
                    new AndroidItem.EmbeddedNativeLibrary("foo\\x86\\libtest.so")
                    {
                        BinaryContent  = () => new byte [10],
                        MetadataValues = "Link=libs\\x86\\libtest.so",
                    },
                    new AndroidItem.AndroidAsset("Assets\\foo.txt")
                    {
                        TextContent = () => "bar",
                    },
                },
            };

            using (var b = CreateDllBuilder(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(Root, b.ProjectDirectory, "foo", "armeabi-v7a", "libtest.so"),
                    Path.Combine(Root, b.ProjectDirectory, "Assets", "foo.txt"),
                };
                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 CustomDesignerTargetSetupDependenciesForDesigner()
        {
            var target = "SetupDependenciesForDesigner";
            var path   = Path.Combine("temp", "SetupDependenciesForDesigner");
            var lib    = new XamarinAndroidLibraryProject()
            {
                ProjectName     = "Library1",
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset("Assets\\foo.txt")
                    {
                        TextContent = () => "bar",
                    },
                },
            };
            var proj = new XamarinAndroidApplicationProject()
            {
                Packages =
                {
                    KnownPackages.SupportMediaCompat_25_4_0_1,
                    KnownPackages.SupportFragment_25_4_0_1,
                    KnownPackages.SupportCoreUtils_25_4_0_1,
                    KnownPackages.SupportCoreUI_25_4_0_1,
                    KnownPackages.SupportCompat_25_4_0_1,
                    KnownPackages.AndroidSupportV4_25_4_0_1,
                    KnownPackages.SupportV7AppCompat_25_4_0_1,
                },
                References = { new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj") },
            };

            proj.Sources.Add(new BuildItem.Source("CustomTextView.cs")
            {
                TextContent = () => @"using Android.Widget;
using Android.Content;
using Android.Util;
namespace UnnamedProject
{
	public class CustomTextView : TextView
	{
		public CustomTextView(Context context, IAttributeSet attributes) : base(context, attributes)
		{
		}
	}
}"
            });
            proj.AndroidResources.Add(new AndroidItem.AndroidResource("Resources\\layout\\custom_text.xml")
            {
                TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<LinearLayout xmlns:android=""http://schemas.android.com/apk/res/android""
	android:orientation = ""vertical""
	android:layout_width = ""fill_parent""
	android:layout_height = ""fill_parent"">
	<UnnamedProject.CustomTextView
		android:id = ""@+id/myText1""
		android:layout_width = ""fill_parent""
		android:layout_height = ""wrap_content""
		android:text = ""namespace_lower"" />
	<unnamedproject.CustomTextView
		android:id = ""@+id/myText2""
		android:layout_width = ""fill_parent""
		android:layout_height = ""wrap_content""
		android:text = ""namespace_proper"" />
</LinearLayout>"
            });

            using (var libb = CreateDllBuilder(Path.Combine(path, lib.ProjectName), false, false))
                using (var appb = CreateApkBuilder(Path.Combine(path, proj.ProjectName), false, false)) {
                    // Save the library project, but don't build it yet
                    libb.Save(lib);
                    appb.Target = target;
                    Assert.IsTrue(appb.Build(proj, parameters: DesignerParameters), $"build should have succeeded for target `{target}`");
                    Assert.IsTrue(appb.Output.AreTargetsAllBuilt("_UpdateAndroidResgen"), "_UpdateAndroidResgen should have run completely.");
                    var customViewPath = Path.Combine(Root, appb.ProjectDirectory, proj.IntermediateOutputPath, "res", "layout", "custom_text.xml");
                    Assert.IsTrue(File.Exists(customViewPath), $"custom_text.xml should exist at {customViewPath}");
                    var doc = XDocument.Load(customViewPath);
                    Assert.IsNotNull(doc.Element("LinearLayout").Element("UnnamedProject.CustomTextView"),
                                     "UnnamedProject.CustomTextView should have not been replaced with an $(MD5Hash).CustomTextView");
                    Assert.IsNotNull(doc.Element("LinearLayout").Element("unnamedproject.CustomTextView"),
                                     "unnamedproject.CustomTextView should have not been replaced with an $(MD5Hash).CustomTextView");
                    // Build the library project now
                    Assert.IsTrue(libb.Build(lib), "library build should have succeeded.");
                    appb.Target = "Build";
                    Assert.IsTrue(appb.Build(proj), "app build should have succeeded.");
                    Assert.IsTrue(appb.Output.AreTargetsAllBuilt("_UpdateAndroidResgen"), "_UpdateAndroidResgen should have run completely.");
                    doc = XDocument.Load(customViewPath);
                    Assert.IsNull(doc.Element("LinearLayout").Element("UnnamedProject.CustomTextView"),
                                  "UnnamedProject.CustomTextView should have been replaced with an $(MD5Hash).CustomTextView");
                    Assert.IsNull(doc.Element("LinearLayout").Element("unnamedproject.CustomTextView"),
                                  "unnamedproject.CustomTextView should have been replaced with an $(MD5Hash).CustomTextView");
                    appb.Target = target;
                    Assert.IsTrue(appb.Build(proj, parameters: DesignerParameters), $"build should have succeeded for target `{target}`");
                    Assert.IsTrue(appb.Output.AreTargetsAllSkipped("_UpdateAndroidResgen"), "_UpdateAndroidResgen should have been skipped.");
                    doc = XDocument.Load(customViewPath);
                    Assert.IsNull(doc.Element("LinearLayout").Element("UnnamedProject.CustomTextView"),
                                  "UnnamedProject.CustomTextView should have been replaced with an $(MD5Hash).CustomTextView");
                    Assert.IsNull(doc.Element("LinearLayout").Element("unnamedproject.CustomTextView"),
                                  "unnamedproject.CustomTextView should have been replaced with an $(MD5Hash).CustomTextView");
                }
        }