public void ConvertCustomView([Values(true, false)] bool useAapt2)
        {
            var path = Path.Combine("temp", TestName);
            var app  = new XamarinAndroidApplicationProject {
                ProjectName = "MyApp",
                Sources     =
                {
                    new BuildItem.Source("Foo.cs")
                    {
                        TextContent = () => "public class Foo : Bar { }"
                    },
                    new BuildItem.Source("CustomTextView.cs")
                    {
                        TextContent = () =>
                                      @"using Android.Widget;
							using Android.Content;
							using Android.Util;
							namespace MyApp
							{
								public class CustomTextView : TextView
								{
									public CustomTextView(Context context, IAttributeSet attributes) : base(context, attributes)
									{
									}
								}
							}"
                    }
                }
            };

            // Use a custom view
            app.LayoutMain = app.LayoutMain.Replace("</LinearLayout>", "<MyApp.CustomTextView android:id=\"@+id/myText\" /></LinearLayout>");
            //NOTE: so _BuildApkEmbed runs in commercial tests
            app.SetProperty("EmbedAssembliesIntoApk", "True");
            app.SetProperty("AndroidUseSharedRuntime", "False");
            app.SetProperty("AndroidUseAapt2", useAapt2.ToString());

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

            //NOTE: this test is checking when $(ProduceReferenceAssembly) is False
            lib.SetProperty("ProduceReferenceAssembly", "False");
            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 [] {
                        "_BuildLibraryImportsCache",
                        "_ResolveLibraryProjectImports",
                        "_ConvertCustomView",
                    };
                    foreach (var target in targetsShouldSkip)
                    {
                        Assert.IsTrue(appBuilder.Output.IsTargetSkipped(target), $"`{target}` should be skipped!");
                    }

                    var targetsShouldRun = new [] {
                        //MyLibrary.dll changed and $(ProduceReferenceAssembly)=False
                        "CoreCompile",
                        "_GenerateJavaStubs",
                        "_BuildApkEmbed",
                        "_CopyPackage",
                        "_Sign",
                    };
                    foreach (var target in targetsShouldRun)
                    {
                        Assert.IsFalse(appBuilder.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped!");
                    }
                }
        }
Exemplo n.º 2
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}'.");
            }
        }
        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 { }"
                    },
                }
            };

            //NOTE: so _BuildApkEmbed runs in commercial tests
            app.SetProperty("EmbedAssembliesIntoApk", true.ToString());
            app.SetProperty("AndroidUseSharedRuntime", false.ToString());

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

            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 [] {
                        "CoreCompile",
                        "_BuildLibraryImportsCache",
                        "_ResolveLibraryProjectImports",
                        "_GenerateJavaStubs",
                    };
                    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!");
                    }
                }
        }
Exemplo n.º 4
0
        public void NetStandardReferenceTest()
        {
            var netStandardProject = new DotNetStandard()
            {
                ProjectName           = "XamFormsSample",
                ProjectGuid           = Guid.NewGuid().ToString(),
                Sdk                   = "Microsoft.NET.Sdk",
                TargetFramework       = "netstandard1.4",
                IsRelease             = true,
                PackageTargetFallback = "portable-net45+win8+wpa81+wp8",
                PackageReferences     =
                {
                    KnownPackages.XamarinForms_2_3_4_231,
                    new Package()
                    {
                        Id      = "System.IO.Packaging",
                        Version = "4.4.0",
                    },
                    new Package()
                    {
                        Id      = "Newtonsoft.Json",
                        Version = "10.0.3"
                    },
                },
                OtherBuildItems =
                {
                    new BuildItem("None")
                    {
                        Remove = () => "**\\*.xaml",
                    },
                    new BuildItem("Compile")
                    {
                        Update        = () => "**\\*.xaml.cs",
                        DependentUpon = () => "%(Filename)"
                    },
                    new BuildItem("EmbeddedResource")
                    {
                        Include   = () => "**\\*.xaml",
                        SubType   = () => "Designer",
                        Generator = () => "MSBuild:UpdateDesignTimeXaml",
                    },
                },
                Sources =
                {
                    new BuildItem.Source("App.xaml.cs")
                    {
                        TextContent = () => @"using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using System.IO.Packaging;

using Xamarin.Forms;

namespace XamFormsSample
{
    public partial class App : Application
    {
        Package package;

        public App()
        {
            try {
                JsonConvert.DeserializeObject<string>(""test"");
                package = Package.Open ("""");
            } catch {
            }
            InitializeComponent();

            MainPage = new ContentPage ();
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}",
                    },
                    new BuildItem.Source("App.xaml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<Application xmlns=""http://xamarin.com/schemas/2014/forms""
             xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
             x:Class=""XamFormsSample.App"">
  <Application.Resources>
    <!-- Application resource dictionary -->
  </Application.Resources>
</Application>",
                    },
                },
            };

            var app = new XamarinAndroidApplicationProject()
            {
                ProjectName          = "App1",
                IsRelease            = true,
                UseLatestPlatformSdk = true,
                References           =
                {
                    new BuildItem.Reference("Mono.Android.Export"),
                    new BuildItem.ProjectReference($"..\\{netStandardProject.ProjectName}\\{netStandardProject.ProjectName}.csproj",
                                                   netStandardProject.ProjectName, netStandardProject.ProjectGuid),
                },
                PackageReferences =
                {
                    KnownPackages.SupportDesign_27_0_2_1,
                    KnownPackages.SupportV7CardView_27_0_2_1,
                    KnownPackages.AndroidSupportV4_27_0_2_1,
                    KnownPackages.SupportCoreUtils_27_0_2_1,
                    KnownPackages.SupportMediaCompat_27_0_2_1,
                    KnownPackages.SupportFragment_27_0_2_1,
                    KnownPackages.SupportCoreUI_27_0_2_1,
                    KnownPackages.SupportCompat_27_0_2_1,
                    KnownPackages.SupportV7AppCompat_27_0_2_1,
                    KnownPackages.SupportV7MediaRouter_27_0_2_1,
                    KnownPackages.XamarinForms_2_3_4_231,
                    new Package()
                    {
                        Id      = "System.Runtime.Loader",
                        Version = "4.3.0",
                    },
                }
            };

            app.MainActivity = @"using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using XamFormsSample;

namespace App1
{
	[Activity (Label = ""App1"", MainLauncher = true, Icon = ""@drawable/icon"")]
	public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity {
			protected override void OnCreate (Bundle bundle)
			{
				base.OnCreate (bundle);

				global::Xamarin.Forms.Forms.Init (this, bundle);

				LoadApplication (new App ());
			}
		}
	}"    ;
            app.SetProperty(KnownProperties.AndroidSupportedAbis, "x86;armeabi-v7a");
            var expectedFiles = new string [] {
                "Java.Interop.dll",
                "Mono.Android.dll",
                "mscorlib.dll",
                "System.Core.dll",
                "System.dll",
                "System.Runtime.Serialization.dll",
                "System.IO.Packaging.dll",
                "System.IO.Compression.dll",
                "Mono.Android.Export.dll",
                "App1.dll",
                "FormsViewGroup.dll",
                "Xamarin.Android.Arch.Core.Common.dll",
                "Xamarin.Android.Arch.Lifecycle.Common.dll",
                "Xamarin.Android.Arch.Lifecycle.Runtime.dll",
                "Xamarin.Android.Support.Compat.dll",
                "Xamarin.Android.Support.Core.UI.dll",
                "Xamarin.Android.Support.Core.Utils.dll",
                "Xamarin.Android.Support.Design.dll",
                "Xamarin.Android.Support.Fragment.dll",
                "Xamarin.Android.Support.Media.Compat.dll",
                "Xamarin.Android.Support.v4.dll",
                "Xamarin.Android.Support.v7.AppCompat.dll",
                "Xamarin.Android.Support.Animated.Vector.Drawable.dll",
                "Xamarin.Android.Support.Vector.Drawable.dll",
                "Xamarin.Android.Support.Transition.dll",
                "Xamarin.Android.Support.v7.MediaRouter.dll",
                "Xamarin.Android.Support.v7.RecyclerView.dll",
                "Xamarin.Android.Support.Annotations.dll",
                "Xamarin.Android.Support.v7.CardView.dll",
                "Xamarin.Android.Support.v7.Palette.dll",
                "Xamarin.Forms.Core.dll",
                "Xamarin.Forms.Platform.Android.dll",
                "Xamarin.Forms.Platform.dll",
                "Xamarin.Forms.Xaml.dll",
                "XamFormsSample.dll",
                "Mono.Security.dll",
                "System.Xml.dll",
                "System.Net.Http.dll",
                "System.ServiceModel.Internals.dll",
                "Newtonsoft.Json.dll",
                "Microsoft.CSharp.dll",
                "System.Numerics.dll",
                "System.Xml.Linq.dll",
            };
            var path = Path.Combine("temp", TestContext.CurrentContext.Test.Name);

            using (var builder = CreateDllBuilder(Path.Combine(path, netStandardProject.ProjectName), cleanupOnDispose: false)) {
                using (var ab = CreateApkBuilder(Path.Combine(path, app.ProjectName), cleanupOnDispose: false)) {
                    builder.RequiresMSBuild =
                        ab.RequiresMSBuild  = true;
                    Assert.IsTrue(builder.Build(netStandardProject), "XamFormsSample should have built.");
                    Assert.IsTrue(ab.Build(app), "App should have built.");
                    var apk = Path.Combine(Root, ab.ProjectDirectory,
                                           app.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk");
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        var existingFiles = zip.Where(a => a.FullName.StartsWith("assemblies/", StringComparison.InvariantCultureIgnoreCase));
                        var missingFiles  = expectedFiles.Where(x => !zip.ContainsEntry("assemblies/" + Path.GetFileName(x)));
                        Assert.IsFalse(missingFiles.Any(),
                                       string.Format("The following Expected files are missing. {0}",
                                                     string.Join(Environment.NewLine, missingFiles)));
                        var additionalFiles = existingFiles.Where(x => !expectedFiles.Contains(Path.GetFileName(x.FullName)));
                        Assert.IsTrue(!additionalFiles.Any(),
                                      string.Format("Unexpected Files found! {0}",
                                                    string.Join(Environment.NewLine, additionalFiles.Select(x => x.FullName))));
                    }
                }
            }
        }
Exemplo n.º 5
0
        public void CheckTheCorrectRuntimeAssemblyIsUsedFromNuget()
        {
            string monoandroidFramework = "monoandroid10.0";
            string path = Path.Combine(Root, "temp", TestName);
            var    ns   = new DotNetStandard()
            {
                ProjectName = "Dummy",
                Sdk         = "MSBuild.Sdk.Extras/2.0.54",
                Sources     =
                {
                    new BuildItem.Source("Class1.cs")
                    {
                        TextContent = () => @"public class Class1 {
#if __ANDROID__
	public static string Library => ""Android"";
#else
	public static string Library => "".NET Standard"";
#endif
}",
                    },
                },
                OtherBuildItems =
                {
                    new BuildItem.NoActionResource("$(OutputPath)netstandard2.0\\$(AssemblyName).dll")
                    {
                        TextContent   = null,
                        BinaryContent = null,
                        Metadata      =
                        {
                            { "PackagePath", "ref\\netstandard2.0"                 },
                            { "Pack",        "True"                                }
                        },
                    },
                    new BuildItem.NoActionResource($"$(OutputPath){monoandroidFramework}\\$(AssemblyName).dll")
                    {
                        TextContent   = null,
                        BinaryContent = null,
                        Metadata      =
                        {
                            { "PackagePath", $"lib\\{monoandroidFramework}"        },
                            { "Pack",        "True"                                }
                        },
                    },
                },
            };

            ns.SetProperty("TargetFrameworks", $"netstandard2.0;{monoandroidFramework}");
            ns.SetProperty("PackageId", "dummy.package.foo");
            ns.SetProperty("PackageVersion", "1.0.0");
            ns.SetProperty("GeneratePackageOnBuild", "True");
            ns.SetProperty("IncludeBuildOutput", "False");
            ns.SetProperty("Summary", "Test");
            ns.SetProperty("Description", "Test");
            ns.SetProperty("PackageOutputPath", path);


            var xa = new XamarinAndroidApplicationProject()
            {
                ProjectName       = "App",
                PackageReferences =
                {
                    new Package()
                    {
                        Id      = "dummy.package.foo",
                        Version = "1.0.0",
                    },
                },
                OtherBuildItems =
                {
                    new BuildItem.NoActionResource("NuGet.config")
                    {
                    },
                },
            };

            xa.SetProperty("RestoreNoCache", "true");
            xa.SetProperty("RestorePackagesPath", "$(MSBuildThisFileDirectory)packages");
            using (var nsb = CreateDllBuilder(Path.Combine(path, ns.ProjectName), cleanupAfterSuccessfulBuild: false, cleanupOnDispose: false))
                using (var xab = CreateApkBuilder(Path.Combine(path, xa.ProjectName), cleanupAfterSuccessfulBuild: false, cleanupOnDispose: false)) {
                    nsb.ThrowOnBuildFailure = xab.ThrowOnBuildFailure = false;
                    Assert.IsTrue(nsb.Build(ns), "Build of NetStandard Library should have succeeded.");
                    Assert.IsFalse(xab.Build(xa, doNotCleanupOnUpdate: true), "Build of App Library should have failed.");
                    File.WriteAllText(Path.Combine(Root, xab.ProjectDirectory, "NuGet.config"), @"<?xml version='1.0' encoding='utf-8'?>
<configuration>
  <packageSources>
    <add key='nuget.org' value='https://api.nuget.org/v3/index.json' protocolVersion='3' />
    <add key='bug-testing' value='..' />
  </packageSources>
</configuration>");
                    Assert.IsTrue(xab.Build(xa, doNotCleanupOnUpdate: true), "Build of App Library should have succeeded.");
                    string expected = Path.Combine("dummy.package.foo", "1.0.0", "lib", monoandroidFramework, "Dummy.dll");
                    Assert.IsTrue(xab.LastBuildOutput.ContainsText(expected), $"Build should be using {expected}");
                }
        }
Exemplo n.º 6
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}'.");
            }
        }
Exemplo n.º 7
0
        public void Build_XAML_Change(bool produceReferenceAssembly, bool install)
        {
            if (install)
            {
                AssertCommercialBuild();                  // This test will fail without Fast Deployment
                AssertHasDevices();
            }

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

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

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

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

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

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

                    libBuilder.AutomaticNuGetRestore     =
                        appBuilder.AutomaticNuGetRestore = false;

                    // Profile XAML change
                    xaml += $"{Environment.NewLine}<!--comment-->";
                    lib.Touch("MyPage.xaml");
                    libBuilder.Build(lib, doNotCleanupOnUpdate: true);
                    if (install)
                    {
                        Profile(appBuilder, b => b.Install(app, doNotCleanupOnUpdate: true), caller);
                    }
                    else
                    {
                        Profile(appBuilder, b => b.Build(app, doNotCleanupOnUpdate: true), caller);
                    }
                }
        }
        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);
            }
        }
        public void MonoSymbolicateNetStandardStackTrace()
        {
            AssertHasDevices();

            var lib = new DotNetStandard {
                ProjectName     = "Library1",
                Sdk             = "Microsoft.NET.Sdk",
                TargetFramework = "netstandard2.0",
                Sources         =
                {
                    new BuildItem.Source("Class1.cs")
                    {
                        TextContent = () => @"
using System;
namespace Library1 {
	public class Class1 {
		string Data { get; set; }
		public Class1(string data) {
			Data = data;
		}

		public string GetData() {
			if (Data == null)
				throw new NullReferenceException();
			return Data;
		}
	}
}",
                    },
                }
            };

            proj = new XamarinFormsAndroidApplicationProject()
            {
                IsRelease  = true,
                References =
                {
                    new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"),
                },
            };
            proj.SetAndroidSupportedAbis("armeabi-v7a", "arm64-v8a", "x86", "x86_64");
            proj.SetProperty(proj.ReleaseProperties, "MonoSymbolArchive", "True");
            proj.MainActivity = proj.DefaultMainActivity.Replace("//${AFTER_ONCREATE}",
                                                                 @"			var cl = new Library1.Class1(null);
			cl.GetData();
");
            var rootPath = Path.Combine(Root, "temp", TestName);

            using (var lb = CreateDllBuilder(Path.Combine(Path.Combine(Root, "temp", TestName), lib.ProjectName))) {
                Assert.IsTrue(lb.Build(lib), "Library build should have succeeded.");

                builder = CreateApkBuilder(Path.Combine(rootPath, proj.ProjectName));
                Assert.IsTrue(builder.Install(proj), "Install should have succeeded.");
                var archivePath = Path.Combine(Root, builder.ProjectDirectory, proj.OutputPath, $"{proj.PackageName}.apk.mSYM");
                Assert.IsTrue(Directory.Exists(archivePath), $"Symbol archive path {archivePath} should exist.");

                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, "crash-logcat.log");
                MonitorAdbLogcat((line) => {
                    return(line.Contains($"Force finishing activity {proj.PackageName}"));
                }, logcatPath, 30);

                var didParse = int.TryParse(proj.TargetSdkVersion, out int apiLevel);
                Assert.IsTrue(didParse, $"Unable to parse {proj.TargetSdkVersion} as an int.");
                SymbolicateAndAssert(archivePath, logcatPath, new string [] {
                    Path.Combine(Root, lb.ProjectDirectory, "Class1.cs:12"),
                    Path.Combine(Root, builder.ProjectDirectory, "MainActivity.cs:33"),
                    Directory.Exists(builder.BuildOutputDirectory)
                                                ? Path.Combine("src", "Mono.Android", "obj", XABuildPaths.Configuration, "monoandroid10", $"android-{apiLevel}", "mcw", "Android.App.Activity.cs:")
                                                : $"src/Mono.Android/obj/Release/monoandroid10/android-{apiLevel}/mcw/Android.App.Activity.cs:",
                });
            }
        }
Exemplo n.º 10
0
        public void NetStandardReferenceTest()
        {
            var netStandardProject = new DotNetStandard()
            {
                Language              = XamarinAndroidProjectLanguage.CSharp,
                ProjectName           = "XamFormsSample",
                ProjectGuid           = Guid.NewGuid().ToString(),
                Sdk                   = "Microsoft.NET.Sdk",
                TargetFramework       = "netstandard1.4",
                IsRelease             = true,
                PackageTargetFallback = "portable-net45+win8+wpa81+wp8",
                PackageReferences     =
                {
                    KnownPackages.XamarinFormsPCL_2_3_4_231,
                    new Package()
                    {
                        Id      = "System.IO.Packaging",
                        Version = "4.4.0",
                    },
                    new Package()
                    {
                        Id      = "Newtonsoft.Json",
                        Version = "10.0.3"
                    },
                },
                OtherBuildItems =
                {
                    new BuildItem("None")
                    {
                        Remove = () => "**\\*.xaml",
                    },
                    new BuildItem("Compile")
                    {
                        Update        = () => "**\\*.xaml.cs",
                        DependentUpon = () => "%(Filename)"
                    },
                    new BuildItem("EmbeddedResource")
                    {
                        Include   = () => "**\\*.xaml",
                        SubType   = () => "Designer",
                        Generator = () => "MSBuild:UpdateDesignTimeXaml",
                    },
                },
                Sources =
                {
                    new BuildItem.Source("App.xaml.cs")
                    {
                        TextContent = () => @"using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;

using Xamarin.Forms;

namespace XamFormsSample
{
    public partial class App : Application
    {
        public App()
        {
            JsonConvert.DeserializeObject<string>(""test"");
            InitializeComponent();
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}",
                    },
                    new BuildItem.Source("App.xaml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<Application xmlns=""http://xamarin.com/schemas/2014/forms""
             xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
             x:Class=""XamFormsSample.App"">
  <Application.Resources>
    <!-- Application resource dictionary -->
  </Application.Resources>
</Application>",
                    },
                },
            };

            var app = new XamarinAndroidApplicationProject()
            {
                ProjectName          = "App1",
                IsRelease            = true,
                UseLatestPlatformSdk = true,
                References           =
                {
                    new BuildItem.Reference("Mono.Android.Export"),
                    new BuildItem.ProjectReference($"..\\{netStandardProject.ProjectName}\\{netStandardProject.ProjectName}.csproj",
                                                   netStandardProject.ProjectName, netStandardProject.ProjectGuid),
                },
                PackageReferences =
                {
                    KnownPackages.SupportDesign_25_4_0_1,
                    KnownPackages.SupportV7CardView_24_2_1,
                    KnownPackages.AndroidSupportV4_25_4_0_1,
                    KnownPackages.SupportCoreUtils_25_4_0_1,
                    KnownPackages.SupportMediaCompat_25_4_0_1,
                    KnownPackages.SupportFragment_25_4_0_1,
                    KnownPackages.SupportCoreUI_25_4_0_1,
                    KnownPackages.SupportCompat_25_4_0_1,
                    KnownPackages.SupportV7AppCompat_25_4_0_1,
                    KnownPackages.XamarinForms_2_3_4_231,
                }
            };

            app.SetProperty(KnownProperties.AndroidSupportedAbis, "x86;armeabi-v7a");
            var expectedFiles = new string [] {
                "Java.Interop.dll",
                "Mono.Android.dll",
                "mscorlib.dll",
                "mscorlib.dll.mdb",
                "System.Collections.Concurrent.dll",
                "System.Collections.dll",
                "System.Core.dll",
                "System.Diagnostics.Debug.dll",
                "System.dll",
                "System.Linq.dll",
                "System.Reflection.dll",
                "System.Reflection.Extensions.dll",
                "System.Runtime.dll",
                "System.Runtime.Extensions.dll",
                "System.Runtime.InteropServices.dll",
                "System.Runtime.Serialization.dll",
                "System.Threading.dll",
                "System.IO.Packaging.dll",
                "System.IO.Compression.dll",
                "System.IO.Compression.pdb",
                "Mono.Android.Export.dll",
                "Mono.Android.Export.pdb",
                "App1.dll",
                "App1.pdb",
                "FormsViewGroup.dll",
                "FormsViewGroup.dll.mdb",
                "Xamarin.Android.Support.Compat.dll",
                "Xamarin.Android.Support.Core.UI.dll",
                "Xamarin.Android.Support.Core.Utils.dll",
                "Xamarin.Android.Support.Design.dll",
                "Xamarin.Android.Support.Fragment.dll",
                "Xamarin.Android.Support.Media.Compat.dll",
                "Xamarin.Android.Support.v4.dll",
                "Xamarin.Android.Support.v7.AppCompat.dll",
                "Xamarin.Android.Support.Animated.Vector.Drawable.dll",
                "Xamarin.Android.Support.Vector.Drawable.dll",
                "Xamarin.Android.Support.Transition.dll",
                "Xamarin.Android.Support.v7.MediaRouter.dll",
                "Xamarin.Android.Support.v7.RecyclerView.dll",
                "Xamarin.Android.Support.Annotations.dll",
                "Xamarin.Android.Support.v7.CardView.dll",
                "Xamarin.Forms.Core.dll",
                "Xamarin.Forms.Core.dll.mdb",
                "Xamarin.Forms.Platform.Android.dll",
                "Xamarin.Forms.Platform.Android.dll.mdb",
                "Xamarin.Forms.Platform.dll",
                "Xamarin.Forms.Xaml.dll",
                "Xamarin.Forms.Xaml.dll.mdb",
                "XamFormsSample.dll",
                "XamFormsSample.pdb",
                "Mono.Android.pdb",
                "System.Core.pdb",
                "System.pdb",
                "Mono.Security.dll",
                "Mono.Security.pdb",
                "System.Xml.dll",
                "System.Xml.pdb",
                "System.ComponentModel.Composition.dll",
                "System.ComponentModel.Composition.pdb",
                "System.Net.Http.dll",
                "System.Net.Http.pdb",
                "System.Runtime.Serialization.pdb",
                "System.ServiceModel.Internals.dll",
                "System.ServiceModel.Internals.pdb",
                "System.Threading.Tasks.dll",
                "System.ObjectModel.dll",
                "System.Globalization.dll",
                "System.ComponentModel.dll",
                "System.Xml.ReaderWriter.dll",
                "System.Linq.Expressions.dll",
                "System.IO.dll",
                "System.Dynamic.Runtime.dll",
                "System.Text.RegularExpressions.dll",
                "System.Diagnostics.Tools.dll",
                "Newtonsoft.Json.dll",
                "Microsoft.CSharp.dll",
                "System.Numerics.dll",
                "System.Xml.Linq.dll",
            };
            var path = Path.Combine("temp", TestContext.CurrentContext.Test.Name);

            using (var builder = CreateDllBuilder(Path.Combine(path, netStandardProject.ProjectName), cleanupOnDispose: false)) {
                if (!Directory.Exists(builder.MicrosoftNetSdkDirectory))
                {
                    Assert.Ignore("Microsoft.NET.Sdk not found.");
                }
                builder.RequiresMSBuild = true;
                builder.Target          = "Restore";
                Assert.IsTrue(builder.Build(netStandardProject), "XamFormsSample Nuget packages should have been restored.");
                builder.Target = "Build";
                Assert.IsTrue(builder.Build(netStandardProject), "XamFormsSample should have built.");
                using (var ab = CreateApkBuilder(Path.Combine(path, app.ProjectName), cleanupOnDispose: false)) {
                    ab.RequiresMSBuild = true;
                    ab.Target          = "Restore";
                    Assert.IsTrue(ab.Build(app), "App should have built.");
                    ab.Target = "SignAndroidPackage";
                    Assert.IsTrue(ab.Build(app), "App should have built.");
                    var apk = Path.Combine(Root, ab.ProjectDirectory,
                                           app.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk");
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        var existingFiles = zip.Where(a => a.FullName.StartsWith("assemblies/", StringComparison.InvariantCultureIgnoreCase));
                        var missingFiles  = expectedFiles.Where(x => !zip.ContainsEntry("assmelbies/" + Path.GetFileName(x)));
                        Assert.IsTrue(missingFiles.Any(),
                                      string.Format("The following Expected files are missing. {0}",
                                                    string.Join(Environment.NewLine, missingFiles)));
                        var additionalFiles = existingFiles.Where(x => !expectedFiles.Contains(Path.GetFileName(x.FullName)));
                        Assert.IsTrue(!additionalFiles.Any(),
                                      string.Format("Unexpected Files found! {0}",
                                                    string.Join(Environment.NewLine, additionalFiles.Select(x => x.FullName))));
                    }
                    if (!HasDevices)
                    {
                        Assert.Ignore("Skipping Installation. No devices available.");
                    }
                    ab.Target = "Install";
                    Assert.IsTrue(ab.Build(app), "App should have installed.");
                }
            }
        }