Пример #1
0
        public void LocalizedAssemblies_ShouldBeFastDeployed()
        {
            AssertCommercialBuild();
            AssertHasDevices();

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

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

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

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

                    var overrideContents = string.Empty;
                    foreach (var dir in GetOverrideDirectoryPaths(app.PackageName))
                    {
                        overrideContents += RunAdbCommand($"shell run-as {app.PackageName} find {dir}");
                    }
                    Assert.IsTrue(resourceFilesFromDisk.Any(), $"Unable to find any localized assemblies in {resourceFilesFromDisk}");
                    foreach (var res in resourceFilesFromDisk)
                    {
                        StringAssert.Contains(res, overrideContents, $"{res} did not exist in the .__override__ directory.\nFound:{overrideContents}");
                    }
                    appBuilder.BuildLogFile = "uninstall.log";
                    appBuilder.Uninstall(app);
                }
        }
        public void MissingSatelliteAssemblyInApp()
        {
            var proj = new XamarinAndroidApplicationProject {
                IsRelease       = true,
                OtherBuildItems =
                {
                    new BuildItem("EmbeddedResource", "Foo.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancel</value></data>")
                    },
                    new BuildItem("EmbeddedResource", "Foo.es.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancelar</value></data>")
                    }
                }
            };

            using (var b = CreateApkBuilder()) {
                b.Target = "Build";
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                b.Target = "SignAndroidPackage";
                Assert.IsTrue(b.Build(proj), "SignAndroidPackage should have succeeded.");

                var apk = Path.Combine(Root, b.ProjectDirectory,
                                       proj.IntermediateOutputPath, "android", "bin", $"{proj.PackageName}.apk");
                using (var zip = ZipHelper.OpenZip(apk)) {
                    Assert.IsTrue(zip.ContainsEntry($"assemblies/es/{proj.ProjectName}.resources.dll"), "Apk should contain satellite assemblies!");
                }
            }
        }
Пример #3
0
        public void OneTimeSetUp()
        {
            var path = Path.Combine("temp", TestName);

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

            var bytes = new byte [1024];

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

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

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

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

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

            intermediate = Path.Combine(projectDir, app.IntermediateOutputPath);
            bin          = Path.Combine(projectDir, app.OutputPath);
        }
Пример #4
0
 public static void AddCultureResourcesToProject(IShortFormProject proj, string filename, string dataName, CultureTypes types = CultureTypes.AllCultures)
 {
     foreach (var culture in CultureInfo.GetCultures(types))
     {
         proj.OtherBuildItems.Add(new BuildItem("EmbeddedResource", $"{filename}.{culture.Name}.resx")
         {
             TextContent = () => InlineData.ResxWithContents($"<data name=\"{dataName}\"><value>{culture.Name}</value></data>")
         });
     }
 }
Пример #5
0
        public void LocalizedAssemblies_ShouldBeFastDeployed()
        {
            AssertCommercialBuild();
            AssertHasDevices();

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

            using (var builder = CreateApkBuilder()) {
                Assert.IsTrue(builder.Install(proj), "Install should have succeeded.");
                var projectOutputPath     = Path.Combine(Root, builder.ProjectDirectory, proj.OutputPath);
                var resourceFilesFromDisk = Directory.EnumerateFiles(projectOutputPath, "*.resources.dll", SearchOption.AllDirectories)
                                            .Select(r => r = r.Replace(projectOutputPath, string.Empty).Replace("\\", "/"));

                var overrideContents = string.Empty;
                foreach (var dir in GetOverrideDirectoryPaths(proj.PackageName))
                {
                    overrideContents += RunAdbCommand($"shell find {dir}");
                }
                builder.Uninstall(proj);
                Assert.IsTrue(resourceFilesFromDisk.Any(), $"Unable to find any localized assemblies in {resourceFilesFromDisk}");
                foreach (var res in resourceFilesFromDisk)
                {
                    StringAssert.Contains(res, overrideContents, $"{res} did not exist in the .__override__ directory.\nFound:{overrideContents}");
                }
            }
        }
        public void MissingSatelliteAssemblyInLibrary()
        {
            var path = Path.Combine("temp", TestName);
            var lib  = new XamarinAndroidLibraryProject {
                ProjectName     = "Localization",
                OtherBuildItems =
                {
                    new BuildItem("EmbeddedResource", "Foo.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancel</value></data>")
                    },
                    new BuildItem("EmbeddedResource", "Foo.es.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancelar</value></data>")
                    }
                }
            };

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

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

            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName)))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.IsTrue(libBuilder.Build(lib), "Library Build should have succeeded.");
                    appBuilder.Target = "Build";
                    Assert.IsTrue(appBuilder.Build(app), "App Build should have succeeded.");
                    appBuilder.Target = "SignAndroidPackage";
                    Assert.IsTrue(appBuilder.Build(app), "App SignAndroidPackage should have succeeded.");

                    var apk = Path.Combine(Root, appBuilder.ProjectDirectory,
                                           app.IntermediateOutputPath, "android", "bin", $"{app.PackageName}.apk");
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        Assert.IsTrue(zip.ContainsEntry($"assemblies/es/{lib.ProjectName}.resources.dll"), "Apk should contain satellite assemblies!");
                    }
                }
        }
Пример #7
0
        public void DotNetBuild(string runtimeIdentifiers, bool isRelease)
        {
            var proj = new XASdkProject {
                IsRelease = isRelease,
                Sources   =
                {
                    new BuildItem("EmbeddedResource", "Foo.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancel</value></data>")
                    },
                    new BuildItem("EmbeddedResource", "Foo.es.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancelar</value></data>")
                    },
                }
            };

            proj.OtherBuildItems.Add(new AndroidItem.InputJar("javaclasses.jar")
            {
                BinaryContent = () => ResourceData.JavaSourceJarTestJar,
            });
            proj.OtherBuildItems.Add(new BuildItem("JavaSourceJar", "javaclasses-sources.jar")
            {
                BinaryContent = () => ResourceData.JavaSourceJarTestSourcesJar,
            });
            if (!runtimeIdentifiers.Contains(";"))
            {
                proj.SetProperty(KnownProperties.RuntimeIdentifier, runtimeIdentifiers);
            }
            else
            {
                proj.SetProperty(KnownProperties.RuntimeIdentifiers, runtimeIdentifiers);
            }

            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(FullProjectDirectory, proj.OutputPath);

            if (!runtimeIdentifiers.Contains(";"))
            {
                outputPath = Path.Combine(outputPath, runtimeIdentifiers);
            }

            var files = Directory.EnumerateFileSystemEntries(outputPath)
                        .Select(Path.GetFileName)
                        .OrderBy(f => f)
                        .ToArray();
            var expectedFiles = new[] {
                "es",
                $"{proj.ProjectName}.dll",
                $"{proj.ProjectName}.pdb",
                $"{proj.PackageName}.apk",
                $"{proj.PackageName}-Signed.apk",
                $"{proj.ProjectName}.xml",
            };

            CollectionAssert.AreEqual(expectedFiles, files, $"Expected: {string.Join (";", expectedFiles)}\n   Found: {string.Join (";", files)}");

            var assemblyPath = Path.Combine(outputPath, $"{proj.ProjectName}.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}");
            }

            bool expectEmbeddedAssembies = !(CommercialBuildAvailable && !isRelease);
            var  apkPath = Path.Combine(outputPath, "UnnamedProject.UnnamedProject.apk");

            FileAssert.Exists(apkPath);
            using (var apk = ZipHelper.OpenZip(apkPath)) {
                apk.AssertContainsEntry(apkPath, $"assemblies/{proj.ProjectName}.dll", shouldContainEntry: expectEmbeddedAssembies);
                apk.AssertContainsEntry(apkPath, $"assemblies/{proj.ProjectName}.pdb", shouldContainEntry: !CommercialBuildAvailable && !isRelease);
                apk.AssertContainsEntry(apkPath, $"assemblies/System.Linq.dll", shouldContainEntry: expectEmbeddedAssembies);
                apk.AssertContainsEntry(apkPath, $"assemblies/es/{proj.ProjectName}.resources.dll", shouldContainEntry: expectEmbeddedAssembies);
                var rids = runtimeIdentifiers.Split(';');
                foreach (var abi in rids.Select(MonoAndroidHelper.RuntimeIdentifierToAbi))
                {
                    apk.AssertContainsEntry(apkPath, $"lib/{abi}/libmonodroid.so");
                    apk.AssertContainsEntry(apkPath, $"lib/{abi}/libmonosgen-2.0.so");
                    if (rids.Length > 1)
                    {
                        apk.AssertContainsEntry(apkPath, $"assemblies/{abi}/System.Private.CoreLib.dll", shouldContainEntry: expectEmbeddedAssembies);
                        apk.AssertContainsEntry(apkPath, $"assemblies/{abi}/System.Collections.Concurrent.dll", shouldContainEntry: expectEmbeddedAssembies);
                    }
                    else
                    {
                        apk.AssertContainsEntry(apkPath, "assemblies/System.Private.CoreLib.dll", shouldContainEntry: expectEmbeddedAssembies);
                        apk.AssertContainsEntry(apkPath, "assemblies/System.Collections.Concurrent.dll", shouldContainEntry: expectEmbeddedAssembies);
                    }
                }
            }
        }
Пример #8
0
        public void DotNetBuild(string runtimeIdentifiers, bool isRelease)
        {
            var proj = new XASdkProject {
                IsRelease = isRelease,
                ExtraNuGetConfigSources =
                {
                    "https://pkgs.dev.azure.com/azure-public/vside/_packaging/xamarin-impl/nuget/v3/index.json"
                },
                PackageReferences =
                {
                    new Package {
                        Id = "Xamarin.AndroidX.AppCompat", Version = "1.2.0.7-net6preview01"
                    },
                    new Package {
                        Id = "Microsoft.AspNetCore.Components.WebView", Version = "6.0.0-preview.5.21301.17"
                    },
                    new Package {
                        Id = "Microsoft.Extensions.FileProviders.Embedded", Version = "6.0.0-preview.6.21306.3"
                    },
                    new Package {
                        Id = "Microsoft.JSInterop", Version = "6.0.0-preview.6.21306.3"
                    },
                    new Package {
                        Id = "System.Text.Json", Version = "6.0.0-preview.7.21323.3"
                    },
                },
                Sources =
                {
                    new BuildItem("EmbeddedResource", "Foo.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancel</value></data>")
                    },
                    new BuildItem("EmbeddedResource", "Foo.es.resx")
                    {
                        TextContent = () => InlineData.ResxWithContents("<data name=\"CancelButton\"><value>Cancelar</value></data>")
                    },
                }
            };

            proj.MainActivity = proj.DefaultMainActivity.Replace(": Activity", ": AndroidX.AppCompat.App.AppCompatActivity");
            proj.OtherBuildItems.Add(new AndroidItem.InputJar("javaclasses.jar")
            {
                BinaryContent = () => ResourceData.JavaSourceJarTestJar,
            });
            proj.OtherBuildItems.Add(new BuildItem("JavaSourceJar", "javaclasses-sources.jar")
            {
                BinaryContent = () => ResourceData.JavaSourceJarTestSourcesJar,
            });
            if (!runtimeIdentifiers.Contains(";"))
            {
                proj.SetProperty(KnownProperties.RuntimeIdentifier, runtimeIdentifiers);
            }
            else
            {
                proj.SetProperty(KnownProperties.RuntimeIdentifiers, runtimeIdentifiers);
            }

            var dotnet = CreateDotNetBuilder(proj);

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

            var outputPath             = Path.Combine(FullProjectDirectory, proj.OutputPath);
            var intermediateOutputPath = Path.Combine(FullProjectDirectory, proj.IntermediateOutputPath);

            if (!runtimeIdentifiers.Contains(";"))
            {
                outputPath             = Path.Combine(outputPath, runtimeIdentifiers);
                intermediateOutputPath = Path.Combine(intermediateOutputPath, runtimeIdentifiers);
            }

            var files = Directory.EnumerateFileSystemEntries(outputPath)
                        .Select(Path.GetFileName)
                        .OrderBy(f => f)
                        .ToArray();
            var expectedFiles = new[] {
                $"{proj.PackageName}.apk",
                $"{proj.PackageName}-Signed.apk",
                "es",
                $"{proj.ProjectName}.dll",
                $"{proj.ProjectName}.pdb",
                $"{proj.ProjectName}.runtimeconfig.json",
                $"{proj.ProjectName}.xml",
            };

            CollectionAssert.AreEqual(expectedFiles, files, $"Expected: {string.Join (";", expectedFiles)}\n   Found: {string.Join (";", files)}");

            var assemblyPath = Path.Combine(outputPath, $"{proj.ProjectName}.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 rids = runtimeIdentifiers.Split(';');

            if (isRelease)
            {
                // Check for stripped native libraries
                foreach (var rid in rids)
                {
                    FileAssert.Exists(Path.Combine(intermediateOutputPath, "native", rid, "libmono-android.release.so"));
                    FileAssert.Exists(Path.Combine(intermediateOutputPath, "native", rid, "libmonosgen-2.0.so"));
                }
            }

            bool expectEmbeddedAssembies = !(CommercialBuildAvailable && !isRelease);
            var  apkPath = Path.Combine(outputPath, $"{proj.PackageName}.apk");

            FileAssert.Exists(apkPath);
            using (var apk = ZipHelper.OpenZip(apkPath)) {
                apk.AssertContainsEntry(apkPath, $"assemblies/{proj.ProjectName}.dll", shouldContainEntry: expectEmbeddedAssembies);
                apk.AssertContainsEntry(apkPath, $"assemblies/{proj.ProjectName}.pdb", shouldContainEntry: !CommercialBuildAvailable && !isRelease);
                apk.AssertContainsEntry(apkPath, $"assemblies/System.Linq.dll", shouldContainEntry: expectEmbeddedAssembies);
                apk.AssertContainsEntry(apkPath, $"assemblies/es/{proj.ProjectName}.resources.dll", shouldContainEntry: expectEmbeddedAssembies);
                foreach (var abi in rids.Select(AndroidRidAbiHelper.RuntimeIdentifierToAbi))
                {
                    apk.AssertContainsEntry(apkPath, $"lib/{abi}/libmonodroid.so");
                    apk.AssertContainsEntry(apkPath, $"lib/{abi}/libmonosgen-2.0.so");
                    if (rids.Length > 1)
                    {
                        apk.AssertContainsEntry(apkPath, $"assemblies/{abi}/System.Private.CoreLib.dll", shouldContainEntry: expectEmbeddedAssembies);
                    }
                    else
                    {
                        apk.AssertContainsEntry(apkPath, "assemblies/System.Private.CoreLib.dll", shouldContainEntry: expectEmbeddedAssembies);
                    }
                }
            }
        }