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