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 CheckPerformanceOfManagedParser() { var path = Path.Combine("temp", TestName); CreateResourceDirectory(path); IBuildEngine engine = new MockBuildEngine(TestContext.Out); TaskLoggingHelper loggingHelper = new TaskLoggingHelper(engine, nameof(ManagedResourceParser)); string resPath = Path.Combine(Root, path, "res"); int platform = AndroidSdkResolver.GetMaxInstalledPlatform(); var flagFile = Path.Combine(Root, path, "AndroidResgen.flag"); var lp = new string [] { Path.Combine(Root, path, "lp", "res") }; Stopwatch sw = new Stopwatch(); long totalMS = 0; int i; for (i = 0; i < 100; i++) { var parser = new ManagedResourceParser() { Log = loggingHelper, JavaPlatformDirectory = Path.Combine(AndroidSdkDirectory, "platforms", $"android-{platform}"), ResourceFlagFile = flagFile, }; sw.Start(); var codeDom = parser.Parse(resPath, lp, isApp: true, resourceMap: new Dictionary <string, string> ()); sw.Stop(); TestContext.Out.WriteLine($"Pass {i} took {sw.ElapsedMilliseconds} ms"); totalMS += sw.ElapsedMilliseconds; sw.Reset(); Assert.AreEqual(20, codeDom.Members.Count, "Expected 20 Classes to be generated"); } TestContext.Out.WriteLine($"Average {totalMS / i} ms"); Assert.LessOrEqual(totalMS / i, 160, "Parser should have taken on average less than 160 ms."); }
[NonParallelizable] // Do not run environment modifying tests in parallel. public void InstallAndroidDependenciesTest() { AssertCommercialBuild(); // We need to grab the latest API level *before* changing env vars var apiLevel = AndroidSdkResolver.GetMaxInstalledPlatform(); var old = Environment.GetEnvironmentVariable("ANDROID_SDK_PATH"); try { string sdkPath = Path.Combine(Root, "temp", TestName, "android-sdk"); Environment.SetEnvironmentVariable("ANDROID_SDK_PATH", sdkPath); if (Directory.Exists(sdkPath)) { Directory.Delete(sdkPath, true); } Directory.CreateDirectory(sdkPath); var proj = new XamarinAndroidApplicationProject { TargetSdkVersion = apiLevel.ToString(), }; using (var b = CreateApkBuilder()) { b.CleanupAfterSuccessfulBuild = false; string defaultTarget = b.Target; b.Target = "InstallAndroidDependencies"; Assert.IsTrue(b.Build(proj, parameters: new string [] { "AcceptAndroidSDKLicenses=true" }), "InstallAndroidDependencies should have succeeded."); b.Target = defaultTarget; Assert.IsTrue(b.Build(proj, true), "build should have succeeded."); Assert.IsTrue(b.LastBuildOutput.ContainsText($"Output Property: _AndroidSdkDirectory={sdkPath}"), "_AndroidSdkDirectory was not set to new SDK path."); Assert.IsTrue(b.LastBuildOutput.ContainsText($"JavaPlatformJarPath={sdkPath}"), "JavaPlatformJarPath did not contain new SDK path."); } } finally { Environment.SetEnvironmentVariable("ANDROID_SDK_PATH", old); } }
static Version GetJdkVersion() { var jdkPath = AndroidSdkResolver.GetJavaSdkPath(); var releasePath = Path.Combine(jdkPath, "release"); if (!File.Exists(releasePath)) { return(null); } foreach (var line in File.ReadLines(releasePath)) { const string JavaVersionStart = "JAVA_VERSION=\""; if (!line.StartsWith(JavaVersionStart, StringComparison.OrdinalIgnoreCase)) { continue; } var value = line.Substring(JavaVersionStart.Length, line.Length - JavaVersionStart.Length - 1); int last = 0; for (last = 0; last < value.Length; ++last) { if (char.IsDigit(value, last) || value [last] == '.') { continue; } break; } return(Version.Parse(last == value.Length ? value : value.Substring(0, last))); } return(null); }
public void BuildProject() { testProjectPath = PrepareProject(ProjectName); string projectPath = Path.Combine(testProjectPath, $"{ProjectName}.csproj"); LocalBuilder builder = GetBuilder("EmbeddedDSO", testProjectPath); string targetAbis = Xamarin.Android.Tools.XABuildConfig.SupportedABIs.Replace(";", ":"); bool success = builder.Build(projectPath, "SignAndroidPackage", new [] { "UnitTestsMode=true", $"Configuration={XABuildPaths.Configuration}", $"AndroidSupportedTargetJitAbis=\"{targetAbis}\"", }); Assert.That(success, Is.True, "Should have been built"); androidSdkDir = AndroidSdkResolver.GetAndroidSdkPath(); }
public void Aapt2AndroidResgenExtraArgsAreSplit() { var path = Path.Combine(Root, "temp", TestName); Directory.CreateDirectory(path); var resPath = Path.Combine(path, "res"); var archivePath = Path.Combine(path, "flata"); var flatFilePath = Path.Combine(path, "flat"); Directory.CreateDirectory(resPath); Directory.CreateDirectory(archivePath); Directory.CreateDirectory(Path.Combine(resPath, "values")); Directory.CreateDirectory(Path.Combine(resPath, "layout")); File.WriteAllText(Path.Combine(resPath, "values", "strings.xml"), @"<?xml version='1.0' ?><resources><string name='foo'>foo</string></resources>"); File.WriteAllText(Path.Combine(resPath, "layout", "main.xml"), @"<?xml version='1.0' ?><LinearLayout xmlns:android='http://schemas.android.com/apk/res/android' />"); File.WriteAllText(Path.Combine(path, "AndroidManifest.xml"), @"<?xml version='1.0' ?><manifest xmlns:android='http://schemas.android.com/apk/res/android' package='Foo.Foo' />"); File.WriteAllText(Path.Combine(path, "foo.map"), @"a\nb"); var errors = new List <BuildErrorEventArgs> (); var warnings = new List <BuildWarningEventArgs> (); var messages = new List <BuildMessageEventArgs> (); IBuildEngine engine = new MockBuildEngine(TestContext.Out, errors, warnings, messages); var archives = new List <ITaskItem>(); CallAapt2Compile(engine, resPath, archivePath, flatFilePath); var outputFile = Path.Combine(path, "resources.apk"); int platform = AndroidSdkResolver.GetMaxInstalledPlatform(); string emitids = Path.Combine(path, "emitids.txt"); string Rtxt = Path.Combine(path, "R.txt"); var task = new Aapt2Link { BuildEngine = engine, ToolPath = GetPathToAapt2(), ResourceDirectories = new ITaskItem [] { new TaskItem(resPath) }, ManifestFiles = new ITaskItem [] { new TaskItem(Path.Combine(path, "AndroidManifest.xml")) }, CompiledResourceFlatArchive = new TaskItem(Path.Combine(archivePath, "compiled.flata")), OutputFile = outputFile, AssemblyIdentityMapFile = Path.Combine(path, "foo.map"), JavaPlatformJarPath = Path.Combine(AndroidSdkPath, "platforms", $"android-{platform}", "android.jar"), ExtraArgs = $@"--no-version-vectors -v --emit-ids ""{emitids}"" --output-text-symbols '{Rtxt}'" }; Assert.True(task.Execute(), $"task should have succeeded. {string.Join (" ", errors.Select (e => e.Message))}"); Assert.AreEqual(0, errors.Count, $"No errors should have been raised. {string.Join (" ", errors.Select (e => e.Message))}"); Assert.True(File.Exists(emitids), $"{emitids} should have been created."); Assert.True(File.Exists(Rtxt), $"{Rtxt} should have been created."); Directory.Delete(Path.Combine(Root, path), recursive: true); }
public void Setup() { engine = new MockBuildEngine(TestContext.Out, errors = new List <BuildErrorEventArgs> (), warnings = new List <BuildWarningEventArgs> (), messages = new List <BuildMessageEventArgs> ()); temp = Path.GetTempFileName(); keyToolPath = Path.Combine(AndroidSdkResolver.GetJavaSdkPath(), "bin"); }
public void CompareAaptAndManagedParserOutputWithCustomIds() { var path = Path.Combine("temp", TestName); CreateResourceDirectory(path); File.WriteAllText(Path.Combine(Root, path, "res", "layout", "custom.xml"), CustomId); File.WriteAllText(Path.Combine(Root, path, "foo.map"), @"a\nb"); Directory.CreateDirectory(Path.Combine(Root, path, "java")); string resPath = Path.Combine(Root, path, "res"); int platform = AndroidSdkResolver.GetMaxInstalledPlatform(); IBuildEngine engine = new MockBuildEngine(TestContext.Out); var aapt = new Aapt() { BuildEngine = engine, ToolPath = GetPathToAapt(), ResourceDirectory = resPath, ManifestFiles = new ITaskItem [] { new TaskItem(Path.Combine(Root, path, "AndroidManifest.xml")) }, ResourceOutputFile = Path.Combine(Root, path, "foo.apk"), AssemblyIdentityMapFile = Path.Combine(Root, path, "foo.map"), JavaPlatformJarPath = Path.Combine(AndroidSdkDirectory, "platforms", $"android-{platform}", "android.jar"), JavaDesignerOutputDirectory = Path.Combine(Root, path, "java"), ResourceSymbolsTextFileDirectory = Path.Combine(Root, path), AdditionalResourceDirectories = new ITaskItem [] { new TaskItem(Path.Combine(Root, path, "lp", "res")) }, AndroidUseLatestPlatformSdk = true, ApiLevel = $"{platform}", }; Assert.IsTrue(aapt.Execute(), "Aapt should have succeeded."); string rTxt = Path.Combine(Root, path, "R.txt"); FileAssert.Exists(rTxt, $"{rTxt} should have been created."); var task = new GenerateResourceDesigner { BuildEngine = engine }; task.UseManagedResourceGenerator = true; task.DesignTimeBuild = false; task.Namespace = "MonoAndroidApplication4.MonoAndroidApplication4"; task.NetResgenOutputFile = Path.Combine(Root, path, "Resource.designer.aapt.cs"); task.ProjectDir = Path.Combine(Root, path); task.ResourceDirectory = Path.Combine(Root, path, "res") + Path.DirectorySeparatorChar; task.Resources = new TaskItem [] { new TaskItem(Path.Combine(Root, path, "res", "values", "strings.xml"), new Dictionary <string, string> () { { "LogicalName", "values\\strings.xml" }, }), }; task.AdditionalResourceDirectories = new TaskItem [] { new TaskItem(Path.Combine(Root, path, "lp", "res")), }; task.ResourceFlagFile = Path.Combine(Root, path, "AndroidResgen.flag"); task.IsApplication = true; task.JavaPlatformJarPath = aapt.JavaPlatformJarPath; Assert.IsTrue(task.Execute(), "Task should have executed successfully."); string aaptDesigner = Path.Combine(Root, path, "Resource.designer.aapt.cs"); var aaptDesignerText = File.ReadAllText(aaptDesigner); StringAssert.Contains("MyCustomID", aaptDesignerText, ""); StringAssert.Contains("HelloWorldTextView", aaptDesignerText, ""); StringAssert.Contains("ACustomID", aaptDesignerText, ""); StringAssert.Contains("foo1", aaptDesignerText, ""); task.UseManagedResourceGenerator = true; task.DesignTimeBuild = true; task.NetResgenOutputFile = Path.Combine(Root, path, "Resource.designer.managedrtxt.cs"); Assert.IsTrue(task.Execute(), "Task should have executed successfully."); string managedDesignerRtxt = Path.Combine(Root, path, "Resource.designer.managedrtxt.cs"); CompareFilesIgnoreRuntimeInfoString(managedDesignerRtxt, aaptDesigner); File.WriteAllText(task.ResourceFlagFile, string.Empty); File.Delete(Path.Combine(Root, path, "R.txt.bak")); File.Move(rTxt, Path.Combine(Root, path, "R.txt.bak")); task.UseManagedResourceGenerator = true; task.DesignTimeBuild = true; task.NetResgenOutputFile = Path.Combine(Root, path, "Resource.designer.managed.cs"); Assert.IsTrue(task.Execute(), "Task should have executed successfully."); string managedDesigner = Path.Combine(Root, path, "Resource.designer.managed.cs"); var managedDesignerText = File.ReadAllText(managedDesigner); StringAssert.Contains("MyCustomID", managedDesignerText, ""); StringAssert.Contains("HelloWorldTextView", managedDesignerText, ""); StringAssert.Contains("ACustomID", managedDesignerText, ""); StringAssert.Contains("foo1", managedDesignerText, ""); Directory.Delete(Path.Combine(Root, path), recursive: true); }
public void CompareAapt2AndManagedParserOutput() { var path = Path.Combine("temp", TestName); CreateResourceDirectory(path); File.WriteAllText(Path.Combine(Root, path, "foo.map"), @"a\nb"); Directory.CreateDirectory(Path.Combine(Root, path, "java")); List <BuildErrorEventArgs> errors = new List <BuildErrorEventArgs> (); IBuildEngine engine = new MockBuildEngine(TestContext.Out, errors: errors); var aapt2Compile = new Aapt2Compile { BuildEngine = engine, ToolPath = GetPathToAapt2(), ResourceDirectories = new ITaskItem [] { new TaskItem(Path.Combine(Root, path, "lp", "res"), new Dictionary <string, string> { { "Hash", "lp" } }), new TaskItem(Path.Combine(Root, path, "res"), new Dictionary <string, string> { { "Hash", "compiled" } }), }, FlatArchivesDirectory = Path.Combine(Root, path), FlatFilesDirectory = Path.Combine(Root, path), }; Assert.IsTrue(aapt2Compile.Execute(), $"Aapt2 Compile should have succeeded. {string.Join (" ", errors.Select (x => x.Message))}"); int platform = AndroidSdkResolver.GetMaxInstalledPlatform(); string resPath = Path.Combine(Root, path, "res"); string rTxt = Path.Combine(Root, path, "R.txt"); var aapt2Link = new Aapt2Link { BuildEngine = engine, ToolPath = GetPathToAapt2(), ResourceDirectories = new ITaskItem [] { new TaskItem(resPath) }, ManifestFiles = new ITaskItem [] { new TaskItem(Path.Combine(Root, path, "AndroidManifest.xml")) }, AdditionalResourceArchives = new ITaskItem [] { new TaskItem(Path.Combine(Root, path, "lp.flata")) }, CompiledResourceFlatArchive = new TaskItem(Path.Combine(Root, path, "compiled.flata")), OutputFile = Path.Combine(Root, path, "foo.apk"), AssemblyIdentityMapFile = Path.Combine(Root, path, "foo.map"), JavaPlatformJarPath = Path.Combine(AndroidSdkDirectory, "platforms", $"android-{platform}", "android.jar"), JavaDesignerOutputDirectory = Path.Combine(Root, path, "java"), ResourceSymbolsTextFile = rTxt, }; Assert.IsTrue(aapt2Link.Execute(), "Aapt2 Link should have succeeded."); FileAssert.Exists(rTxt, $"{rTxt} should have been created."); var task = new GenerateResourceDesigner { BuildEngine = engine }; task.UseManagedResourceGenerator = true; task.DesignTimeBuild = false; task.Namespace = "MonoAndroidApplication4.MonoAndroidApplication4"; task.NetResgenOutputFile = Path.Combine(Root, path, "Resource.designer.aapt2.cs"); task.ProjectDir = Path.Combine(Root, path); task.ResourceDirectory = Path.Combine(Root, path, "res") + Path.DirectorySeparatorChar; task.Resources = new TaskItem [] { new TaskItem(Path.Combine(Root, path, "res", "values", "strings.xml"), new Dictionary <string, string> () { { "LogicalName", "values\\strings.xml" }, }), }; task.AdditionalResourceDirectories = new TaskItem [] { new TaskItem(Path.Combine(Root, path, "lp", "res")), }; task.ResourceFlagFile = Path.Combine(Root, path, "AndroidResgen.flag"); task.IsApplication = true; task.JavaPlatformJarPath = aapt2Link.JavaPlatformJarPath; Assert.IsTrue(task.Execute(), "Task should have executed successfully."); File.WriteAllText(task.ResourceFlagFile, string.Empty); File.Delete(Path.Combine(Root, path, "R.txt.bak")); File.Move(rTxt, Path.Combine(Root, path, "R.txt.bak")); task.UseManagedResourceGenerator = true; task.DesignTimeBuild = true; task.NetResgenOutputFile = Path.Combine(Root, path, "Resource.designer.managed.cs"); Assert.IsTrue(task.Execute(), "Task should have executed successfully."); string aapt2Designer = Path.Combine(Root, path, "Resource.designer.aapt2.cs"); string managedDesigner = Path.Combine(Root, path, "Resource.designer.managed.cs"); CompareFilesIgnoreRuntimeInfoString(managedDesigner, aapt2Designer); Directory.Delete(Path.Combine(Root, path), recursive: true); }
public void TestNdkUtil() { var log = new TaskLoggingHelper(engine, TestName); using (var builder = new Builder()) { var ndkDir = AndroidNdkPath; var sdkDir = AndroidSdkPath; MonoAndroidHelper.AndroidSdk = new AndroidSdkInfo((arg1, arg2) => { }, sdkDir, ndkDir, AndroidSdkResolver.GetJavaSdkPath()); NdkUtil.Init(log, ndkDir); var platforms = NdkUtil.GetSupportedPlatforms(log, ndkDir); Assert.AreNotEqual(0, platforms.Count(), "No platforms found"); var arch = AndroidTargetArch.X86; Assert.IsTrue(NdkUtil.ValidateNdkPlatform(log, ndkDir, arch, enableLLVM: false)); Assert.AreEqual(0, errors.Count, "NdkUtil.ValidateNdkPlatform should not have returned false."); int level = NdkUtil.GetMinimumApiLevelFor(arch, ndkDir); int expected = 16; Assert.AreEqual(expected, level, $"Min Api Level for {arch} should be {expected}."); var compilerNoQuotes = NdkUtil.GetNdkTool(ndkDir, arch, "gcc", level); Assert.AreEqual(0, errors.Count, "NdkUtil.GetNdkTool should not have errored."); Assert.NotNull(compilerNoQuotes, "NdkUtil.GetNdkTool returned null."); var gas = NdkUtil.GetNdkTool(ndkDir, arch, "as", level); Assert.AreEqual(0, errors.Count, "NdkUtil.GetNdkTool should not have errored."); Assert.NotNull(gas, "NdkUtil.GetNdkTool returned null."); var inc = NdkUtil.GetNdkPlatformIncludePath(ndkDir, arch, level); Assert.NotNull(inc, " NdkUtil.GetNdkPlatformIncludePath should not return null"); var libPath = NdkUtil.GetNdkPlatformLibPath(ndkDir, arch, level); Assert.NotNull(libPath, "NdkUtil.GetNdkPlatformLibPath should not return null"); string ld = NdkUtil.GetNdkTool(ndkDir, arch, "ld", level); Assert.AreEqual(0, errors.Count, "NdkUtil.GetNdkTool should not have errored."); Assert.NotNull(ld, "NdkUtil.GetNdkTool returned null."); } }
public void Aapt2Link([Values(true, false)] bool compilePerFile) { var path = Path.Combine(Root, "temp", TestName); Directory.CreateDirectory(path); var resPath = Path.Combine(path, "res"); var archivePath = Path.Combine(path, "flata"); var flatFilePath = Path.Combine(path, "flat"); Directory.CreateDirectory(resPath); Directory.CreateDirectory(archivePath); Directory.CreateDirectory(flatFilePath); Directory.CreateDirectory(Path.Combine(resPath, "values")); Directory.CreateDirectory(Path.Combine(resPath, "layout")); File.WriteAllText(Path.Combine(resPath, "values", "strings.xml"), @"<?xml version='1.0' ?><resources><string name='foo'>foo</string></resources>"); File.WriteAllText(Path.Combine(resPath, "layout", "main.xml"), @"<?xml version='1.0' ?><LinearLayout xmlns:android='http://schemas.android.com/apk/res/android' />"); var libPath = Path.Combine(path, "lp"); Directory.CreateDirectory(libPath); Directory.CreateDirectory(Path.Combine(libPath, "0", "res", "values")); Directory.CreateDirectory(Path.Combine(libPath, "1", "res", "values")); File.WriteAllText(Path.Combine(libPath, "0", "res", "values", "strings.xml"), @"<?xml version='1.0' ?><resources><string name='foo1'>foo1</string></resources>"); File.WriteAllText(Path.Combine(libPath, "1", "res", "values", "strings.xml"), @"<?xml version='1.0' ?><resources><string name='foo2'>foo2</string></resources>"); File.WriteAllText(Path.Combine(path, "AndroidManifest.xml"), @"<?xml version='1.0' ?><manifest xmlns:android='http://schemas.android.com/apk/res/android' package='Foo.Foo' />"); File.WriteAllText(Path.Combine(path, "foo.map"), @"a\nb"); var errors = new List <BuildErrorEventArgs> (); var warnings = new List <BuildWarningEventArgs> (); IBuildEngine engine = new MockBuildEngine(TestContext.Out, errors, warnings); var archives = new List <ITaskItem>(); if (compilePerFile) { foreach (var file in Directory.EnumerateFiles(resPath, "*.*", SearchOption.AllDirectories)) { CallAapt2Compile(engine, file, archivePath, flatFilePath); } } else { CallAapt2Compile(engine, resPath, archivePath, flatFilePath); } CallAapt2Compile(engine, Path.Combine(libPath, "0", "res"), archivePath, flatFilePath, archives); CallAapt2Compile(engine, Path.Combine(libPath, "1", "res"), archivePath, flatFilePath, archives); List <ITaskItem> items = new List <ITaskItem> (); if (compilePerFile) { // collect all the flat archives foreach (var file in Directory.EnumerateFiles(flatFilePath, "*.flat", SearchOption.AllDirectories)) { items.Add(new TaskItem(file)); } } int platform = AndroidSdkResolver.GetMaxInstalledPlatform(); var outputFile = Path.Combine(path, "resources.apk"); var task = new Aapt2Link { BuildEngine = engine, ToolPath = GetPathToAapt2(), ResourceDirectories = new ITaskItem [] { new TaskItem(resPath) }, ManifestFiles = new ITaskItem [] { new TaskItem(Path.Combine(path, "AndroidManifest.xml")) }, AdditionalResourceArchives = !compilePerFile?archives.ToArray() : null, CompiledResourceFlatArchive = !compilePerFile ? new TaskItem(Path.Combine(archivePath, "compiled.flata")) : null, CompiledResourceFlatFiles = compilePerFile ? items.ToArray() : null, OutputFile = outputFile, AssemblyIdentityMapFile = Path.Combine(path, "foo.map"), JavaPlatformJarPath = Path.Combine(AndroidSdkPath, "platforms", $"android-{platform}", "android.jar"), }; Assert.True(task.Execute(), $"task should have succeeded. {string.Join (";", errors.Select (x => x.Message))}"); Assert.AreEqual(0, errors.Count, "There should be no errors."); Assert.LessOrEqual(0, warnings.Count, "There should be 0 warnings."); Assert.True(File.Exists(outputFile), $"{outputFile} should have been created."); using (var apk = ZipHelper.OpenZip(outputFile)) { Assert.AreEqual(3, apk.EntryCount, $"{outputFile} should have 3 entries."); } Directory.Delete(Path.Combine(Root, path), recursive: true); }
public static void AssertValidEnvironmentSharedLibrary(string outputDirectoryRoot, string sdkDirectory, string ndkDirectory, string supportedAbis) { NdkUtil.Init(ndkDirectory); MonoAndroidHelper.AndroidSdk = new AndroidSdkInfo((arg1, arg2) => {}, sdkDirectory, ndkDirectory, AndroidSdkResolver.GetJavaSdkPath()); AndroidTargetArch arch; foreach (string abi in supportedAbis.Split(';')) { switch (abi) { case "armeabi-v7a": arch = AndroidTargetArch.Arm; break; case "arm64": case "arm64-v8a": case "aarch64": arch = AndroidTargetArch.Arm64; break; case "x86": arch = AndroidTargetArch.X86; break; case "x86_64": arch = AndroidTargetArch.X86_64; break; default: throw new Exception("Unsupported Android target architecture ABI: " + abi); } string envSharedLibrary = Path.Combine(outputDirectoryRoot, "app_shared_libraries", abi, "libxamarin-app.so"); Assert.IsTrue(File.Exists(envSharedLibrary), $"Application environment SharedLibrary '{envSharedLibrary}' must exist"); // API level doesn't matter in this case AssertSharedLibraryHasRequiredSymbols(envSharedLibrary, NdkUtil.GetNdkTool(ndkDirectory, arch, "readelf", 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."); } string keyfile = Path.Combine(Root, "temp", TestName, "release.keystore"); if (File.Exists(keyfile)) { File.Delete(keyfile); } string keyToolPath = Path.Combine(AndroidSdkResolver.GetJavaSdkPath(), "bin"); var engine = new MockBuildEngine(Console.Out); string pass = "******"; string alias = "release store"; var task = new AndroidCreateDebugKey { BuildEngine = engine, KeyStore = keyfile, StorePass = pass, KeyAlias = alias, KeyPass = pass, KeyAlgorithm = "RSA", Validity = 30, StoreType = "pkcs12", Command = "-genkeypair", ToolPath = keyToolPath, }; Assert.IsTrue(task.Execute(), "Task should have succeeded."); var proj = new XamarinAndroidApplicationProject() { IsRelease = true, }; proj.SetProperty(proj.ReleaseProperties, "AndroidUseApkSigner", useApkSigner); proj.SetProperty(proj.ReleaseProperties, "AndroidKeyStore", "True"); proj.SetProperty(proj.ReleaseProperties, "AndroidSigningKeyStore", keyfile); proj.SetProperty(proj.ReleaseProperties, "AndroidSigningKeyAlias", alias); proj.SetProperty(proj.ReleaseProperties, "AndroidSigningKeyPass", Uri.EscapeDataString(pass)); proj.SetProperty(proj.ReleaseProperties, "AndroidSigningStorePass", Uri.EscapeDataString(pass)); proj.SetProperty(proj.ReleaseProperties, KnownProperties.AndroidCreatePackagePerAbi, perAbiApk); if (perAbiApk) { proj.SetAndroidSupportedAbis("armeabi-v7a", "x86", "arm64-v8a", "x86_64"); } else { proj.SetAndroidSupportedAbis("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"); b.AssertHasNoWarnings(); //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`."); } } // Make sure the APKs have unique version codes if (perAbiApk) { int armManifestCode = GetVersionCodeFromIntermediateManifest(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "armeabi-v7a", "AndroidManifest.xml")); int x86ManifestCode = GetVersionCodeFromIntermediateManifest(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "x86", "AndroidManifest.xml")); int arm64ManifestCode = GetVersionCodeFromIntermediateManifest(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "arm64-v8a", "AndroidManifest.xml")); int x86_64ManifestCode = GetVersionCodeFromIntermediateManifest(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "x86_64", "AndroidManifest.xml")); var versionList = new List <int> { armManifestCode, x86ManifestCode, arm64ManifestCode, x86_64ManifestCode }; Assert.True(versionList.Distinct().Count() == versionList.Count, $"APK version codes were not unique - armeabi-v7a: {armManifestCode}, x86: {x86ManifestCode}, arm64-v8a: {arm64ManifestCode}, x86_64: {x86_64ManifestCode}"); } 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"); b.AssertHasNoWarnings(); //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`."); } } } int GetVersionCodeFromIntermediateManifest(string manifestFilePath) { var doc = XDocument.Load(manifestFilePath); var versionCode = doc.Descendants() .Where(e => e.Name == "manifest") .Select(m => m.Attribute("{http://schemas.android.com/apk/res/android}versionCode")).FirstOrDefault(); if (!int.TryParse(versionCode?.Value, out int parsedCode)) { Assert.Fail($"Unable to parse 'versionCode' value from manifest content: {File.ReadAllText (manifestFilePath)}."); } return(parsedCode); } }