Exemple #1
0
        public void GetDependencyWhenBuildToolsAreMissingTest()
        {
            var apis           = new ApiInfo [] {
            };
            var path           = Path.Combine("temp", TestName);
            var androidSdkPath = CreateFauxAndroidSdkDirectory(Path.Combine(path, "android-sdk"),
                                                               null, apis);
            var referencesPath = CreateFauxReferencesDirectory(Path.Combine(path, "xbuild-frameworks"), apis);
            var proj           = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
                TargetFrameworkVersion = "v8.0",
                TargetSdkVersion       = "26",
                UseLatestPlatformSdk   = false,
            };
            var parameters = new string [] {
                $"TargetFrameworkRootPath={referencesPath}",
                $"AndroidSdkDirectory={androidSdkPath}",
            };
            string buildToolsVersion = GetExpectedBuildToolsVersion();

            using (var builder = CreateApkBuilder(Path.Combine(path, proj.ProjectName), cleanupAfterSuccessfulBuild: false, cleanupOnDispose: false)) {
                builder.ThrowOnBuildFailure = false;
                builder.Target = "GetAndroidDependencies";
                Assert.True(builder.Build(proj, parameters: parameters),
                            string.Format("First Build should have succeeded"));
                int apiLevel = Builder.UseDotNet ? AndroidSdkResolver.GetMaxInstalledPlatform() : 26;
                StringAssertEx.Contains($"platforms/android-{apiLevel}", builder.LastBuildOutput, $"platforms/android-{apiLevel} should be a dependency.");
                StringAssertEx.Contains($"build-tools/{buildToolsVersion}", builder.LastBuildOutput, $"build-tools/{buildToolsVersion} should be a dependency.");
                StringAssertEx.Contains("platform-tools", builder.LastBuildOutput, "platform-tools should be a dependency.");
            }
        }
        public void BuildBasicBindingLibrary(string classParser)
        {
            var proj = new XamarinAndroidBindingProject()
            {
                IsRelease = true,
            };

            proj.Jars.Add(new AndroidItem.EmbeddedJar("Jars\\svg-android.jar")
            {
                WebContent = "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/svg-android/svg-android.jar"
            });
            proj.AndroidClassParser = classParser;
            using (var b = CreateDllBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");

                //A list of properties we check exist in binding projects
                var properties = new [] {
                    "AndroidSdkBuildToolsVersion",
                    "AndroidSdkPlatformToolsVersion",
                    "AndroidSdkToolsVersion",
                    "AndroidNdkVersion",
                };
                foreach (var property in properties)
                {
                    Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, property + " = "), $"$({property}) should be set!");
                }
            }
        }
Exemple #3
0
        public void CheckSignApk([Values(true, false)] bool useApkSigner, [Values(true, false)] bool perAbiApk)
        {
            string ext            = Environment.OSVersion.Platform != PlatformID.Unix ? ".bat" : "";
            var    foundApkSigner = Directory.EnumerateDirectories(Path.Combine(AndroidSdkPath, "build-tools")).Any(dir => Directory.EnumerateFiles(dir, "apksigner" + ext).Any());

            if (useApkSigner && !foundApkSigner)
            {
                Assert.Ignore("Skipping test. Required build-tools verison which contains apksigner is not installed.");
            }
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
            };

            if (useApkSigner)
            {
                proj.SetProperty("AndroidUseApkSigner", "true");
            }
            else
            {
                proj.RemoveProperty("AndroidUseApkSigner");
            }
            proj.SetProperty(proj.ReleaseProperties, KnownProperties.AndroidCreatePackagePerAbi, perAbiApk);
            proj.SetProperty(proj.ReleaseProperties, KnownProperties.AndroidSupportedAbis, "armeabi-v7a;x86");
            using (var b = CreateApkBuilder(Path.Combine("temp", TestContext.CurrentContext.Test.Name))) {
                b.Verbosity = Microsoft.Build.Framework.LoggerVerbosity.Diagnostic;
                Assert.IsTrue(b.Build(proj), "build failed");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, " 0 Warning(s)"));
                proj.AndroidResources.First().Timestamp = null;
                Assert.IsTrue(b.Build(proj), "Second build failed");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, " 0 Warning(s)"));
            }
        }
        public void CheckClassesDexIsIncluded([Values("dx", "d8", "invalid")] string dexTool)
        {
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
                DexTool   = dexTool,
            };

            using (var b = CreateApkBuilder()) {
                b.ThrowOnBuildFailure = false;
                if (Builder.UseDotNet && dexTool == "dx")
                {
                    Assert.IsFalse(b.Build(proj), "build failed");
                    StringAssertEx.Contains("XA1023", b.LastBuildOutput, "Output should contain XA1023 errors");
                    return;
                }

                Assert.IsTrue(b.Build(proj), "build failed");
                var apk = Path.Combine(Root, b.ProjectDirectory,
                                       proj.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk");
                using (var zip = ZipHelper.OpenZip(apk)) {
                    Assert.IsTrue(zip.ContainsEntry("classes.dex"), "Apk should contain classes.dex");
                }
            }
        }
        public void BuildBasicBindingLibrary(string classParser)
        {
            var targets = new List <string> {
                "_ExportJarToXml",
                "GenerateBindings",
                "_ResolveLibraryProjectImports",
                "CoreCompile",
            };

            if (Builder.UseDotNet)
            {
                targets.Add("_CreateAar");
            }
            else
            {
                targets.Add("_CreateBindingResourceArchive");
                //TODO: .NET 5+ cannot support javadoc yet, due to missing mdoc
                targets.Add("_ExtractJavaDocJars");
                targets.Add("BuildDocumentation");
            }

            var proj = new XamarinAndroidBindingProject()
            {
                IsRelease = true,
            };

            proj.Jars.Add(new AndroidItem.AndroidLibrary("Jars\\svg-android.jar")
            {
                WebContent = "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/svg-android/svg-android.jar"
            });
            proj.AndroidClassParser = classParser;
            using (var b = CreateDllBuilder()) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");

                var assemblyPath = Path.Combine(Root, b.ProjectDirectory, proj.OutputPath, $"{proj.ProjectName}.dll");
                using (var assembly = AssemblyDefinition.ReadAssembly(assemblyPath)) {
                    var typeName = "Com.Larvalabs.Svgandroid.SVG";
                    var type     = assembly.MainModule.GetType(typeName);
                    Assert.IsNotNull(type, $"{assemblyPath} should contain {typeName}");
                }

                //A list of properties we check exist in binding projects
                var properties = new [] {
                    "AndroidSdkBuildToolsVersion",
                    "AndroidSdkPlatformToolsVersion",
                    "AndroidSdkToolsVersion",
                    "AndroidNdkVersion",
                };
                foreach (var property in properties)
                {
                    Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, property + " = "), $"$({property}) should be set!");
                }

                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "second build should succeed");
                foreach (var target in targets)
                {
                    Assert.IsTrue(b.Output.IsTargetSkipped(target), $"`{target}` should be skipped on second build!");
                }
            }
        }
        public void BuildBasicApplicationReleaseWithCustomAotProfile()
        {
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
                AndroidEnableProfiledAot = true,
            };

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

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

            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Using profile data file.*custom\.aotprofile", b.LastBuildOutput, "Should use custom AOT profile", RegexOptions.IgnoreCase);
                StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Method.*emitted at", b.LastBuildOutput, "Should contain verbose AOT compiler output", RegexOptions.IgnoreCase);
            }
        }
        public void LibraryProjectZipWithLint()
        {
            var path = Path.Combine("temp", TestName);
            var lib  = new XamarinAndroidBindingProject()
            {
                ProjectName        = "BindingsProject",
                AndroidClassParser = "class-parse",
                Jars =
                {
                    new AndroidItem.LibraryProjectZip("fragment-1.2.2.aar")
                    {
                        WebContent = "https://maven.google.com/androidx/fragment/fragment/1.2.2/fragment-1.2.2.aar"
                    }
                },
                MetadataXml = @"<metadata><remove-node path=""/api/package[@name='androidx.fragment.app']/interface[@name='FragmentManager.OpGenerator']"" /></metadata>"
            };
            var app = new XamarinAndroidApplicationProject()
            {
                ProjectName = "App",
                IsRelease   = true,
                LinkTool    = "r8",
                References  = { new BuildItem.ProjectReference($"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj", lib.ProjectName, lib.ProjectGuid) }
            };

            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName), cleanupAfterSuccessfulBuild: false))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.IsTrue(libBuilder.Build(lib), "Library build should have succeeded.");
                    Assert.IsTrue(appBuilder.Build(app), "App build should have succeeded.");
                    StringAssertEx.DoesNotContain("warning : Missing class: com.android.tools.lint.detector.api.Detector", appBuilder.LastBuildOutput, "Build output should contain no warnings about com.android.tools.lint.detector.api.Detector");
                    var libraryProjects = Path.Combine(Root, appBuilder.ProjectDirectory, app.IntermediateOutputPath, "lp");
                    Assert.IsFalse(Directory.EnumerateFiles(libraryProjects, "lint.jar", SearchOption.AllDirectories).Any(),
                                   "`lint.jar` should not be extracted!");
                }
        }
Exemple #8
0
        public void InstallErrorCode()
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("Not required on Open Source Builds");
            }

            if (!HasDevices)
            {
                Assert.Ignore("Test Skipped no devices or emulators found.");
            }

            //Setup a situation where we get INSTALL_FAILED_NO_MATCHING_ABIS
            var abi  = "armeabi-v7a";
            var proj = new XamarinAndroidApplicationProject {
                AndroidUseSharedRuntime = false,
                EmbedAssembliesIntoApk  = true,
            };

            proj.SetProperty(proj.DebugProperties, KnownProperties.AndroidSupportedAbis, abi);

            using (var builder = CreateApkBuilder(Path.Combine("temp", TestContext.CurrentContext.Test.Name))) {
                builder.ThrowOnBuildFailure = false;
                if (!builder.Install(proj))
                {
                    Assert.IsTrue(StringAssertEx.ContainsText(builder.LastBuildOutput, "ADB0020"), "Should receive ADB0020 error code.");
                }
                else
                {
                    Assert.Ignore($"Install should have failed, but we might have an {abi} emulator attached.");
                }
            }
        }
Exemple #9
0
        public void InstallErrorCode()
        {
            AssertCommercialBuild();
            AssertHasDevices();

            //Setup a situation where we get INSTALL_FAILED_NO_MATCHING_ABIS
            var abi  = "armeabi-v7a";
            var proj = new XamarinAndroidApplicationProject {
                EmbedAssembliesIntoApk = true,
            };

            proj.SetAndroidSupportedAbis(abi);

            using (var builder = CreateApkBuilder(Path.Combine("temp", TestContext.CurrentContext.Test.Name))) {
                builder.ThrowOnBuildFailure = false;
                if (!builder.Install(proj))
                {
                    Assert.IsTrue(StringAssertEx.ContainsText(builder.LastBuildOutput, "ADB0020"), "Should receive ADB0020 error code.");
                }
                else
                {
                    Assert.Ignore($"Install should have failed, but we might have an {abi} emulator attached.");
                }
            }
        }
        public void Queries_API30([Values(true, false)] bool useAapt2)
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("$(AndroidUseSharedRuntime) is required for this test.");
                return;
            }

            var proj = new XamarinAndroidApplicationProject {
                AndroidUseSharedRuntime = true,
                EmbedAssembliesIntoApk  = false,
            };

            proj.SetProperty("AndroidUseAapt2", useAapt2.ToString());
            proj.AndroidManifest = proj.AndroidManifest.Replace("<uses-sdk />", "<uses-sdk android:targetSdkVersion=\"30\" />");
            using (var b = CreateApkBuilder()) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded");

                string manifest = b.Output.GetIntermediaryAsText(Path.Combine("android", "AndroidManifest.xml"));
                var    doc      = XDocument.Parse(manifest);
                var    ns       = XNamespace.Get("http://schemas.android.com/apk/res/android");
                var    names    = doc.Element("manifest")?
                                  .Element("queries")?
                                  .Elements("package")?
                                  .Select(e => e.Attribute(ns + "name")?.Value);
                StringAssertEx.Contains("Mono.Android.DebugRuntime", names);
                StringAssertEx.Contains("Mono.Android.Platform.ApiLevel_30", names);
            }
        }
Exemple #11
0
        public void Bug12935([Values(true, false)] bool useAapt2)
        {
            AssertAaptSupported(useAapt2);
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
            };

            proj.MainActivity    = ScreenOrientationActivity;
            proj.AndroidUseAapt2 = useAapt2;
            var directory = $"temp/Bug12935_{useAapt2}";

            using (var builder = CreateApkBuilder(directory)) {
                proj.TargetFrameworkVersion = "v4.2";
                proj.AndroidManifest        = string.Format(TargetSdkManifest, "17");
                Assert.IsTrue(builder.Build(proj), "Build for TargetFrameworkVersion 17 should have succeeded");
                var manifestFile = Path.Combine(Root, builder.ProjectDirectory, proj.IntermediateOutputPath, "android", "AndroidManifest.xml");

                XDocument doc = XDocument.Load(manifestFile);
                var       ns  = doc.Root.GetNamespaceOfPrefix("android");
                var       screenOrientationXName = XName.Get("screenOrientation", ns.NamespaceName);
                var       targetSdkXName         = XName.Get("targetSdkVersion", ns.NamespaceName);

                var usesSdk = doc.XPathSelectElement("/manifest/uses-sdk");
                Assert.IsNotNull(usesSdk, "Failed to read the uses-sdk element");
                var targetSdk = usesSdk.Attribute(targetSdkXName);
                Assert.AreEqual("17", targetSdk.Value, "targetSdkVersion should have been 17");

                var activityElement = doc.XPathSelectElement("/manifest/application/activity");
                Assert.IsNotNull(activityElement, "Failed to read the activity element");
                var screenOrientation = activityElement.Attribute(screenOrientationXName);
                Assert.IsNotNull(screenOrientation, "activity element did not contain a android:screenOrientation attribute");
                Assert.AreEqual("sensorPortrait", screenOrientation.Value, "screenOrientation should have been sensorPortrait");

                builder.Cleanup();
                proj.TargetFrameworkVersion = "v4.1";
                proj.AndroidManifest        = string.Format(TargetSdkManifest, "16");
                Assert.IsTrue(builder.Build(proj), "Build for TargetFrameworkVersion 16 should have succeeded");

                doc     = XDocument.Load(manifestFile);
                usesSdk = doc.XPathSelectElement("/manifest/uses-sdk");
                Assert.IsNotNull(usesSdk, "Failed to read the uses-sdk element");
                targetSdk = usesSdk.Attribute(targetSdkXName);
                Assert.AreEqual("16", targetSdk.Value, "targetSdkVersion should have been 16");
                activityElement = doc.XPathSelectElement("/manifest/application/activity");
                Assert.IsNotNull(activityElement, "Failed to read the activity element");
                screenOrientation = activityElement.Attribute(screenOrientationXName);
                Assert.AreEqual("sensorPortrait", screenOrientation.Value, "screenOrientation for targetSdkVersion 16 should have been sensorPortrait");

                builder.Cleanup();
                builder.ThrowOnBuildFailure = false;
                proj.TargetFrameworkVersion = "v4.0.3";
                proj.AndroidManifest        = string.Format(TargetSdkManifest, "15");
                Assert.IsFalse(builder.Build(proj), "Build for TargetFrameworkVersion 15 should have failed");
                StringAssertEx.Contains(useAapt2 ? "APT2259: " : "APT1134: ", builder.LastBuildOutput);
                StringAssertEx.Contains(useAapt2 ? "APT2067" : "", builder.LastBuildOutput);
                StringAssertEx.Contains(Path.Combine("Properties", "AndroidManifest.xml"), builder.LastBuildOutput);
                StringAssertEx.Contains($"{(useAapt2 ? "2" : "1")} Error(s)", builder.LastBuildOutput);
            }
        }
		public void AppBundleSigned ()
		{
			var aab = Path.Combine (bin, "UnnamedProject.UnnamedProject-Signed.aab");
			FileAssert.Exists (aab);
			var contents = ListArchiveContents (aab);
			Assert.IsTrue (StringAssertEx.ContainsText (contents, "META-INF/MANIFEST.MF"), $"{aab} is not signed!");
		}
Exemple #13
0
        public void DotNetBuildXamarinForms()
        {
            var proj   = new XamarinFormsXASdkProject();
            var dotnet = CreateDotNetBuilder(proj);

            Assert.IsTrue(dotnet.Build(), "`dotnet build` should succeed");
            Assert.IsTrue(StringAssertEx.ContainsText(dotnet.LastBuildOutput, " 0 Warning(s)"), "Should have no MSBuild warnings.");
        }
        public void CheckSignApk([Values(true, false)] bool useApkSigner, [Values(true, false)] bool perAbiApk)
        {
            string ext            = Environment.OSVersion.Platform != PlatformID.Unix ? ".bat" : "";
            var    foundApkSigner = Directory.EnumerateDirectories(Path.Combine(AndroidSdkPath, "build-tools")).Any(dir => Directory.EnumerateFiles(dir, "apksigner" + ext).Any());

            if (useApkSigner && !foundApkSigner)
            {
                Assert.Ignore("Skipping test. Required build-tools verison which contains apksigner is not installed.");
            }
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
            };

            if (useApkSigner)
            {
                proj.SetProperty("AndroidUseApkSigner", "true");
            }
            else
            {
                proj.RemoveProperty("AndroidUseApkSigner");
            }
            proj.SetProperty(proj.ReleaseProperties, KnownProperties.AndroidCreatePackagePerAbi, perAbiApk);
            proj.SetProperty(proj.ReleaseProperties, KnownProperties.AndroidSupportedAbis, "armeabi-v7a;x86");
            using (var b = CreateApkBuilder(Path.Combine("temp", TestContext.CurrentContext.Test.Name))) {
                var bin = Path.Combine(Root, b.ProjectDirectory, proj.OutputPath);
                Assert.IsTrue(b.Build(proj), "First build failed");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, " 0 Warning(s)"),
                              "First build should not contain warnings!  Contains\n" +
                              string.Join("\n", b.LastBuildOutput.Where(line => line.Contains("warning"))));

                //Make sure the APKs are signed
                foreach (var apk in Directory.GetFiles(bin, "*-Signed.apk"))
                {
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        Assert.IsTrue(zip.Any(e => e.FullName == "META-INF/MANIFEST.MF"), $"APK file `{apk}` is not signed! It is missing `META-INF/MANIFEST.MF`.");
                    }
                }

                var item = proj.AndroidResources.First(x => x.Include() == "Resources\\values\\Strings.xml");
                item.TextContent = () => proj.StringsXml.Replace("${PROJECT_NAME}", "Foo");
                item.Timestamp   = null;
                Assert.IsTrue(b.Build(proj), "Second build failed");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, " 0 Warning(s)"),
                              "Second build should not contain warnings!  Contains\n" +
                              string.Join("\n", b.LastBuildOutput.Where(line => line.Contains("warning"))));

                //Make sure the APKs are signed
                foreach (var apk in Directory.GetFiles(bin, "*-Signed.apk"))
                {
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        Assert.IsTrue(zip.Any(e => e.FullName == "META-INF/MANIFEST.MF"), $"APK file `{apk}` is not signed! It is missing `META-INF/MANIFEST.MF`.");
                    }
                }
            }
        }
        void WarnAboutAppDomains(XamarinAndroidApplicationProject proj, string testName)
        {
            proj.MainActivity = proj.DefaultMainActivity.Replace("base.OnCreate (bundle);", "base.OnCreate (bundle);\nvar appDomain = System.AppDomain.CreateDomain (\"myDomain\");");
            var projDirectory = Path.Combine("temp", testName);

            using (var b = CreateApkBuilder(projDirectory)) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, "Warning: Use of AppDomain::CreateDomain"), "Should warn about creating AppDomain.");
            }
        }
Exemple #16
0
        public void Aapt2Disabled()
        {
            var proj = new XamarinAndroidApplicationProject();

            proj.SetProperty("AndroidUseAapt2", "False");
            using (var b = CreateApkBuilder("temp/Aapt2Disabled")) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, "Task \"Aapt2Link\" skipped"), "Aapt2Link task should be skipped!");
                Assert.IsTrue(b.Output.IsTargetSkipped("_CreateAapt2VersionCache"), "_CreateAapt2VersionCache target should be skipped!");
            }
        }
        void WarnAboutAppDomains(XamarinAndroidApplicationProject proj, string testName)
        {
            proj.MainActivity = proj.DefaultMainActivity.Replace("base.OnCreate (bundle);", "base.OnCreate (bundle);\nvar appDomain = System.AppDomain.CreateDomain (\"myDomain\");");
            var projDirectory = Path.Combine("temp", testName);

            using (var b = CreateApkBuilder(projDirectory)) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, "2 Warning(s)"), "MSBuild should count 2 warnings.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, "warning CS0618: 'AppDomain.CreateDomain(string)' is obsolete: 'AppDomain.CreateDomain will no longer be supported in .NET 5 and later."), "Should warn CS0618 about creating AppDomain.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, "warning XA2000: Use of AppDomain.CreateDomain()"), "Should warn XA2000 about creating AppDomain.");
            }
        }
        public void Edge(int limit, bool xamarinForms)
        {
            var testName = $"{nameof (Edge)}{xamarinForms}"
                           .PadRight(Files.MaxPath - BaseLength - limit, 'N');
            var proj = CreateProject(xamarinForms);

            using (var b = CreateApkBuilder(Path.Combine("temp", testName))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                Assert.IsTrue(b.Clean(proj), "Clean should have succeeded.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, $"Trying long path: {Files.LongPathPrefix}"), "A long path should be encountered.");
            }
        }
Exemple #19
0
        public void BundledWearApp()
        {
            var target = "_UpdateAndroidResgen";
            var path   = Path.Combine("temp", TestName);
            var app    = new XamarinAndroidApplicationProject {
                ProjectName             = "MyApp",
                AndroidUseSharedRuntime = false,
                EmbedAssembliesIntoApk  = true,
            };
            var wear = new XamarinAndroidWearApplicationProject {
                AndroidUseSharedRuntime = false,
                EmbedAssembliesIntoApk  = true,
            };

            app.References.Add(new BuildItem.ProjectReference($"..\\{wear.ProjectName}\\{wear.ProjectName}.csproj", wear.ProjectName, wear.ProjectGuid)
            {
                MetadataValues = "IsAppExtension=True"
            });

            using (var wearBuilder = CreateDllBuilder(Path.Combine(path, wear.ProjectName)))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.IsTrue(wearBuilder.Build(wear), "first wear build should have succeeded.");
                    // In .NET 5+, just check for a build error
                    if (Builder.UseDotNet)
                    {
                        appBuilder.ThrowOnBuildFailure = false;
                        Assert.IsFalse(appBuilder.Build(app), "'dotnet' app build should have failed.");
                        StringAssertEx.Contains($"error XA4312", appBuilder.LastBuildOutput, "Error should be XA4312");
                        return;
                    }
                    Assert.IsTrue(appBuilder.Build(app), "first app build should have succeeded.");
                    StringAssertEx.Contains($"warning XA4312", appBuilder.LastBuildOutput, "Warning should be XA4312");
                    // Build with no changes
                    Assert.IsTrue(wearBuilder.Build(wear, doNotCleanupOnUpdate: true), "second wear build should have succeeded.");
                    Assert.IsTrue(wearBuilder.Output.IsTargetSkipped(target), $"`{target}` in wear build should be skipped!");
                    Assert.IsTrue(appBuilder.Build(app, doNotCleanupOnUpdate: true), "second app build should have succeeded.");
                    Assert.IsTrue(appBuilder.LastBuildOutput.ContainsOccurances($"Skipping target \"{target}\"", 2), $"`{target}` in app build should be skipped!");
                    // Check the APK for the special Android Wear files
                    var files = new [] {
                        "res/raw/wearable_app.apk",
                        "res/xml/wearable_app_desc.xml"
                    };
                    var apk = Path.Combine(Root, appBuilder.ProjectDirectory, app.OutputPath, $"{app.PackageName}.apk");
                    FileAssert.Exists(apk);
                    using (var zipFile = ZipHelper.OpenZip(apk)) {
                        foreach (var file in files)
                        {
                            Assert.IsTrue(zipFile.ContainsEntry(file, caseSensitive: true), $"{file} should be in the apk!");
                        }
                    }
                }
        }
        public void Aapt2Disabled()
        {
            AssertAaptSupported(useAapt2: false);
            var proj = new XamarinAndroidApplicationProject();

            proj.AndroidUseAapt2 = false;
            using (var b = CreateApkBuilder()) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                Assert.IsFalse(StringAssertEx.ContainsText(b.LastBuildOutput, "Aapt2Link"), "Aapt2Link task should not run!");
                Assert.IsFalse(StringAssertEx.ContainsText(b.LastBuildOutput, "Aapt2Compile"), "Aapt2Compile task should not run!");
                Assert.IsFalse(StringAssertEx.ContainsText(b.LastBuildOutput, "_CreateAapt2VersionCache"), "_CreateAapt2VersionCache target should not run!");
            }
        }
Exemple #21
0
        public void LongPath()
        {
            if (LongPathsSupported)
            {
                Assert.Ignore("This environment supports long paths");
            }
            var file = NewFile(fileName: "foo".PadRight(MaxFileName, 'N'));
            var task = CreateTask();

            Assert.IsTrue(task.Execute(), "task.Execute() should have succeeded.");
            Assert.AreEqual(1, task.RemovedDirectories.Length, "Changes should have been made.");
            DirectoryAssert.DoesNotExist(tempDirectory);
            Assert.IsTrue(StringAssertEx.ContainsText(messages.Select(m => m.Message), $"Trying long path: {Files.LongPathPrefix}"), "A long path should be encountered.");
        }
        public void OverTheEdge(int limit, bool xamarinForms)
        {
            var testName = $"{nameof (Edge)}{xamarinForms}"
                           .PadRight(Files.MaxPath - BaseLength - limit, 'N');
            var proj = CreateProject(xamarinForms);

            using (var b = CreateApkBuilder(Path.Combine("temp", testName))) {
                b.ThrowOnBuildFailure = false;
                Assert.IsFalse(b.Build(proj), "Build should have failed.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, "XA5301"), "Should get MAX_PATH warning");
                b.ThrowOnBuildFailure = true;
                Assert.IsTrue(b.Clean(proj), "Clean should have succeeded.");
            }
        }
Exemple #23
0
        public void LongPath()
        {
            if (!IsWindows)
            {
                Assert.Ignore("MAX_PATH only applies on Windows");
            }
            var file = NewFile(fileName: "foo".PadRight(250, 'N'));
            var task = CreateTask();

            Assert.IsTrue(task.Execute(), "task.Execute() should have succeeded.");
            Assert.AreEqual(1, task.RemovedDirectories.Length, "Changes should have been made.");
            DirectoryAssert.DoesNotExist(tempDirectory);
            Assert.IsTrue(StringAssertEx.ContainsText(messages.Select(m => m.Message), $"Trying long path: {Files.LongPathPrefix}"), "A long path should be encountered.");
        }
        public void BuildBasicApplicationReleaseProfiledAotWithoutDefaultProfile()
        {
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
                AndroidEnableProfiledAot = true,
            };

            proj.SetProperty(proj.ActiveConfigurationProperties, "AndroidUseDefaultAotProfile", "false");
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                StringAssertEx.DoesNotContainRegex(@"\[aot-compiler stdout\] Using profile data file.*build.Xamarin.Android.startup.*\.aotprofile", b.LastBuildOutput, "Should not use default AOT profile", RegexOptions.IgnoreCase);
            }
        }
        public void BuildBasicBindingLibrary(string classParser)
        {
            var targets = new List <string> {
                "_ExportJarToXml",
                "GenerateBindings",
                "_CreateBindingResourceArchive",
                "_ResolveLibraryProjectImports",
                "CoreCompile",
            };

            if (!Builder.UseDotNet)
            {
                //TODO: .NET 5+ cannot support javadoc yet, due to missing mdoc
                targets.Add("_ExtractJavaDocJars");
                targets.Add("BuildDocumentation");
            }

            var proj = new XamarinAndroidBindingProject()
            {
                IsRelease = true,
            };

            proj.Jars.Add(new AndroidItem.EmbeddedJar("Jars\\svg-android.jar")
            {
                WebContent = "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/svg-android/svg-android.jar"
            });
            proj.AndroidClassParser = classParser;
            using (var b = CreateDllBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");

                //A list of properties we check exist in binding projects
                var properties = new [] {
                    "AndroidSdkBuildToolsVersion",
                    "AndroidSdkPlatformToolsVersion",
                    "AndroidSdkToolsVersion",
                    "AndroidNdkVersion",
                };
                foreach (var property in properties)
                {
                    Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, property + " = "), $"$({property}) should be set!");
                }

                Assert.IsTrue(b.Build(proj, doNotCleanupOnUpdate: true, saveProject: false), "second build should succeed");
                foreach (var target in targets)
                {
                    Assert.IsTrue(b.Output.IsTargetSkipped(target), $"`{target}` should be skipped on second build!");
                }
            }
        }
        public void BuildBasicApplicationReleaseProfiledAot()
        {
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
                AndroidEnableProfiledAot = true,
            };

            proj.SetProperty(proj.ActiveConfigurationProperties, "AndroidExtraAotOptions", "--verbose");
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Using profile data file.*build.Xamarin.Android.startup\.aotprofile", b.LastBuildOutput, "Should use default AOT profile", RegexOptions.IgnoreCase);
                StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Method.*emitted at", b.LastBuildOutput, "Should contain verbose AOT compiler output", RegexOptions.IgnoreCase);
            }
        }
        [Category("DotNetIgnore")]          // n/a on .NET 5+
        public void WarnAboutAppDomains([Values(true, false)] bool isRelease)
        {
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = isRelease
            };

            proj.MainActivity = proj.DefaultMainActivity.Replace("base.OnCreate (bundle);", "base.OnCreate (bundle);\nvar appDomain = System.AppDomain.CreateDomain (\"myDomain\");");
            using (var b = CreateApkBuilder()) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, "2 Warning(s)"), "MSBuild should count 2 warnings.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, "warning CS0618: 'AppDomain.CreateDomain(string)' is obsolete: 'AppDomain.CreateDomain will no longer be supported in .NET 5 and later."), "Should warn CS0618 about creating AppDomain.");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, "warning XA2000: Use of AppDomain.CreateDomain()"), "Should warn XA2000 about creating AppDomain.");
            }
        }
        public void DotNetBuild(string runtimeIdentifier, bool isRelease)
        {
            var abi  = MonoAndroidHelper.RuntimeIdentifierToAbi(runtimeIdentifier);
            var proj = new XASdkProject {
                IsRelease = isRelease
            };

            proj.OtherBuildItems.Add(new AndroidItem.InputJar("javaclasses.jar")
            {
                BinaryContent = () => Convert.FromBase64String(InlineData.JavaClassesJarBase64)
            });
            // TODO: bring back when Xamarin.Android.Bindings.Documentation.targets is working
            //proj.OtherBuildItems.Add (new BuildItem ("JavaSourceJar", "javasources.jar") {
            //	BinaryContent = () => Convert.FromBase64String (InlineData.JavaSourcesJarBase64)
            //});
            proj.SetProperty(KnownProperties.RuntimeIdentifier, runtimeIdentifier);

            var dotnet = CreateDotNetBuilder(proj);

            Assert.IsTrue(dotnet.Build(), "`dotnet build` should succeed");

            // TODO: run for release once illink warnings are gone
            // context: https://github.com/xamarin/xamarin-android/issues/4708
            if (!isRelease)
            {
                Assert.IsTrue(StringAssertEx.ContainsText(dotnet.LastBuildOutput, " 0 Warning(s)"), "Should have no MSBuild warnings.");
            }

            var outputPath   = Path.Combine(Root, dotnet.ProjectDirectory, proj.OutputPath, runtimeIdentifier);
            var assemblyPath = Path.Combine(outputPath, "UnnamedProject.dll");

            FileAssert.Exists(assemblyPath);
            using (var assembly = AssemblyDefinition.ReadAssembly(assemblyPath)) {
                var typeName = "Com.Xamarin.Android.Test.Msbuildtest.JavaSourceJarTest";
                var type     = assembly.MainModule.GetType(typeName);
                Assert.IsNotNull(type, $"{assemblyPath} should contain {typeName}");
            }

            var apk = Path.Combine(outputPath, "UnnamedProject.UnnamedProject.apk");

            FileAssert.Exists(apk);
            using (var zip = ZipHelper.OpenZip(apk)) {
                Assert.IsTrue(zip.ContainsEntry($"lib/{abi}/libmonodroid.so"), "libmonodroid.so should exist.");
                Assert.IsTrue(zip.ContainsEntry($"lib/{abi}/libmonosgen-2.0.so"), "libmonosgen-2.0.so should exist.");
            }
        }
Exemple #29
0
        public void GetDependencyNdkRequiredConditions(string property, bool ndkRequired)
        {
            var proj = new XamarinAndroidApplicationProject();

            proj.AotAssemblies = true;
            proj.SetProperty(property, "true");
            using (var builder = CreateApkBuilder()) {
                builder.Target = "GetAndroidDependencies";
                Assert.IsTrue(builder.Build(proj), "Build should have succeeded.");
                IEnumerable <string> taskOutput = builder.LastBuildOutput
                                                  .Select(x => x.Trim())
                                                  .SkipWhile(x => !x.StartsWith("Task \"CalculateProjectDependencies\""))
                                                  .SkipWhile(x => !x.StartsWith("Output Item(s):"))
                                                  .TakeWhile(x => !x.StartsWith("Done executing task \"CalculateProjectDependencies\""));
                if (ndkRequired)
                {
                    StringAssertEx.Contains("ndk-bundle", taskOutput, "ndk-bundle should be a dependency.");
                }
                else
                {
                    StringAssertEx.DoesNotContain("ndk-bundle", taskOutput, "ndk-bundle should not be a dependency.");
                }
            }
        }
Exemple #30
0
        public void TestAndroidStoreKey(bool useApkSigner, bool isRelease, string packageFormat, string androidKeyStore, string password, string expected, bool shouldInstall)
        {
            AssertHasDevices();
            if (DeviceSdkVersion >= 30 && !useApkSigner && packageFormat == "apk")
            {
                Assert.Ignore($"Test Skipped. jarsigner and {packageFormat} does not work with API 30 and above");
                return;
            }

            string path          = Path.Combine("temp", TestName.Replace(expected, expected.Replace("-", "_")));
            string storepassfile = Path.Combine(Root, path, "storepass.txt");
            string keypassfile   = Path.Combine(Root, path, "keypass.txt");

            byte [] data = GetKeystore();
            var     proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = isRelease
            };
            Dictionary <string, string> envVar = new Dictionary <string, string> ();

            if (password.StartsWith("env:", StringComparison.Ordinal))
            {
                envVar.Add("_MYPASSWORD", password.Replace("env:", string.Empty));
                proj.SetProperty("AndroidSigningStorePass", "env:_MYPASSWORD");
                proj.SetProperty("AndroidSigningKeyPass", "env:_MYPASSWORD");
            }
            else if (password.StartsWith("file:", StringComparison.Ordinal))
            {
                proj.SetProperty("AndroidSigningStorePass", $"file:{storepassfile}");
                proj.SetProperty("AndroidSigningKeyPass", $"file:{keypassfile}");
            }
            else
            {
                proj.SetProperty("AndroidSigningStorePass", password);
                proj.SetProperty("AndroidSigningKeyPass", password);
            }
            proj.SetAndroidSupportedAbis("armeabi-v7a", "x86");
            proj.SetProperty("AndroidKeyStore", androidKeyStore);
            proj.SetProperty("AndroidSigningKeyStore", "test.keystore");
            proj.SetProperty("AndroidSigningKeyAlias", "mykey");
            proj.SetProperty("AndroidPackageFormat", packageFormat);
            proj.SetProperty("AndroidUseApkSigner", useApkSigner.ToString());
            proj.OtherBuildItems.Add(new BuildItem(BuildActions.None, "test.keystore")
            {
                BinaryContent = () => data
            });
            proj.OtherBuildItems.Add(new BuildItem(BuildActions.None, "storepass.txt")
            {
                TextContent = () => password.Replace("file:", string.Empty),
                Encoding    = Encoding.ASCII,
            });
            proj.OtherBuildItems.Add(new BuildItem(BuildActions.None, "keypass.txt")
            {
                TextContent = () => password.Replace("file:", string.Empty),
                Encoding    = Encoding.ASCII,
            });
            using (var b = CreateApkBuilder(path, false, false)) {
                b.ThrowOnBuildFailure = false;
                Assert.IsTrue(b.Build(proj, environmentVariables: envVar), "Build should have succeeded.");
                if (packageFormat == "apk")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                b.BuildLogFile = "install.log";
                Assert.AreEqual(shouldInstall, b.Install(proj, doNotCleanupOnUpdate: true), $"Install should have {(shouldInstall ? "succeeded" : "failed")}.");
                if (packageFormat == "aab")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                if (!shouldInstall)
                {
                    return;
                }
                b.BuildLogFile = "uninstall.log";
                Assert.IsTrue(b.Uninstall(proj, doNotCleanupOnUpdate: true), "Uninstall should have succeeded.");
            }
        }