From 0f87a89c0f6206f9286d630f0da44bbb26970e69 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Tue, 20 Jun 2023 20:06:28 -0400 Subject: [PATCH] [tests] Remove `XASdkDeployTests` Most of our time intensive tests are in deploy and debug scenarios, and we have some duplication there that can be cleaned up. The `XASdkDeployTests` class has been removed, and non duplicated tests from this class have been moved into `InstallAndRunTests`. The `DotNetInstallAndRun` tests have been paired down to two tests for `net7.0-android` Debug and Release. The other permutations should be covered by existing install and run tests. The `DotNetDebug` tests have been removed, as they were effectively duplicates of `ApplicationRunsWithDebuggerAndBreaks`. The `Debugger` tests have had their connection settings adjusted to try fewer times to connect but wait longer in between attempts. We will now only wait for up to 5 minutes to connect rather than ~17 minutes. --- .../Tests/DebuggingTest.cs | 34 ++- .../Tests/InstallAndRunTests.cs | 102 ++++++++ .../Tests/XASdkDeployTests.cs | 247 ------------------ 3 files changed, 132 insertions(+), 251 deletions(-) delete mode 100644 tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs diff --git a/tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs b/tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs index 712bd184795..3722cc00f9d 100755 --- a/tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs @@ -16,6 +16,9 @@ namespace Xamarin.Android.Build.Tests [Category ("UsesDevice")] public class DebuggingTest : DeviceTest { + const int DEBUGGER_MAX_CONNECTIONS = 100; + const int DEBUGGER_CONNECTION_TIMEOUT = 3000; + [TearDown] public void ClearDebugProperties () { @@ -242,7 +245,8 @@ public override void OnCreate () int port = rnd.Next (10000, 20000); TestContext.Out.WriteLine ($"{port}"); var args = new SoftDebuggerConnectArgs ("", IPAddress.Loopback, port) { - MaxConnectionAttempts = 2000, // we need a long delay here to get a reliable connection + MaxConnectionAttempts = DEBUGGER_MAX_CONNECTIONS, // we need a long delay here to get a reliable connection + TimeBetweenConnectionAttempts = DEBUGGER_CONNECTION_TIMEOUT, }; var startInfo = new SoftDebuggerStartInfo (args) { WorkingDirectory = Path.Combine (b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets"), @@ -299,6 +303,15 @@ public override void OnCreate () /* allowDeltaInstall */ false, /* user */ null, /* packageFormat */ "apk", + /* useLatestSdk */ true, + }, + new object[] { + /* embedAssemblies */ true, + /* fastDevType */ "Assemblies", + /* allowDeltaInstall */ false, + /* user */ null, + /* packageFormat */ "apk", + /* useLatestSdk */ false, }, new object[] { /* embedAssemblies */ false, @@ -306,6 +319,7 @@ public override void OnCreate () /* allowDeltaInstall */ false, /* user */ null, /* packageFormat */ "apk", + /* useLatestSdk */ true, }, new object[] { /* embedAssemblies */ false, @@ -313,6 +327,7 @@ public override void OnCreate () /* allowDeltaInstall */ true, /* user */ null, /* packageFormat */ "apk", + /* useLatestSdk */ true, }, new object[] { /* embedAssemblies */ false, @@ -320,6 +335,7 @@ public override void OnCreate () /* allowDeltaInstall */ false, /* user */ null, /* packageFormat */ "apk", + /* useLatestSdk */ true, }, new object[] { /* embedAssemblies */ false, @@ -327,6 +343,7 @@ public override void OnCreate () /* allowDeltaInstall */ true, /* user */ null, /* packageFormat */ "apk", + /* useLatestSdk */ true, }, new object[] { /* embedAssemblies */ true, @@ -334,6 +351,7 @@ public override void OnCreate () /* allowDeltaInstall */ false, /* user */ DeviceTest.GuestUserName, /* packageFormat */ "apk", + /* useLatestSdk */ true, }, new object[] { /* embedAssemblies */ false, @@ -341,6 +359,7 @@ public override void OnCreate () /* allowDeltaInstall */ false, /* user */ DeviceTest.GuestUserName, /* packageFormat */ "apk", + /* useLatestSdk */ true, }, new object[] { /* embedAssemblies */ true, @@ -348,6 +367,7 @@ public override void OnCreate () /* allowDeltaInstall */ false, /* user */ null, /* packageFormat */ "aab", + /* useLatestSdk */ true, }, new object[] { /* embedAssemblies */ true, @@ -355,14 +375,15 @@ public override void OnCreate () /* allowDeltaInstall */ false, /* user */ DeviceTest.GuestUserName, /* packageFormat */ "aab", + /* useLatestSdk */ true, }, }; #pragma warning restore 414 - [Test, Category ("Debugger")] + [Test, Category ("Debugger"), Category ("WearOS")] [TestCaseSource (nameof(DebuggerTestCases))] [Retry (5)] - public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool allowDeltaInstall, string username, string packageFormat) + public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool allowDeltaInstall, string username, string packageFormat, bool useLatestSdk) { AssertCommercialBuild (); SwitchUser (); @@ -405,6 +426,10 @@ public Foo () EmbedAssembliesIntoApk = embedAssemblies, AndroidFastDeploymentType = fastDevType }; + if (!useLatestSdk) { + lib.TargetFramework = "net7.0-android"; + app.TargetFramework = "net7.0-android"; + } app.SetProperty ("AndroidPackageFormat", packageFormat); app.MainPage = app.MainPage.Replace ("InitializeComponent ();", "InitializeComponent (); new Foo ();"); app.AddReference (lib); @@ -465,7 +490,8 @@ public Foo () int port = rnd.Next (10000, 20000); TestContext.Out.WriteLine ($"{port}"); var args = new SoftDebuggerConnectArgs ("", IPAddress.Loopback, port) { - MaxConnectionAttempts = 2000, + MaxConnectionAttempts = DEBUGGER_MAX_CONNECTIONS, + TimeBetweenConnectionAttempts = DEBUGGER_CONNECTION_TIMEOUT, }; var startInfo = new SoftDebuggerStartInfo (args) { WorkingDirectory = Path.Combine (appBuilder.ProjectDirectory, app.IntermediateOutputPath, "android", "assets"), diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 3a5875955bb..b2d530f3d5b 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Text.RegularExpressions; using System.Xml.Linq; using System.Xml.XPath; @@ -1137,5 +1138,106 @@ public void CheckResouceIsOverridden ([Values (true, false)] bool useAapt2) } } + [Test] + [Category ("WearOS")] + public void DotNetInstallAndRunPreviousSdk ([Values (false, true)] bool isRelease) + { + var proj = new XamarinFormsAndroidApplicationProject () { + TargetFramework = "net7.0-android", + IsRelease = isRelease, + EnableDefaultItems = true, + }; + + var builder = CreateApkBuilder (); + Assert.IsTrue (builder.Build (proj), "`dotnet build` should succeed"); + RunProjectAndAssert (proj, builder); + + WaitForPermissionActivity (Path.Combine (Root, builder.ProjectDirectory, "permission-logcat.log")); + bool didLaunch = WaitForActivityToStart (proj.PackageName, "MainActivity", + Path.Combine (Root, builder.ProjectDirectory, "logcat.log"), 30); + Assert.IsTrue(didLaunch, "Activity should have started."); + } + + [Test] + public void TypeAndMemberRemapping ([Values (false, true)] bool isRelease) + { + var proj = new XamarinAndroidApplicationProject () { + IsRelease = isRelease, + EnableDefaultItems = true, + OtherBuildItems = { + new AndroidItem._AndroidRemapMembers ("RemapActivity.xml") { + Encoding = Encoding.UTF8, + TextContent = () => ResourceData.RemapActivityXml, + }, + new AndroidItem.AndroidJavaSource ("RemapActivity.java") { + Encoding = new UTF8Encoding (encoderShouldEmitUTF8Identifier: false), + TextContent = () => ResourceData.RemapActivityJava, + Metadata = { + { "Bind", "True" }, + }, + }, + }, + }; + proj.MainActivity = proj.DefaultMainActivity.Replace (": Activity", ": global::Example.RemapActivity"); + var builder = CreateApkBuilder (); + Assert.IsTrue (builder.Build (proj), "`dotnet build` should succeed"); + RunProjectAndAssert (proj, builder); + var appStartupLogcatFile = Path.Combine (Root, builder.ProjectDirectory, "logcat.log"); + bool didLaunch = WaitForActivityToStart (proj.PackageName, "MainActivity", appStartupLogcatFile); + Assert.IsTrue (didLaunch, "MainActivity should have launched!"); + var logcatOutput = File.ReadAllText (appStartupLogcatFile); + + StringAssert.Contains ( + "RemapActivity.onMyCreate() invoked!", + logcatOutput, + "Activity.onCreate() wasn't remapped to RemapActivity.onMyCreate()!" + ); + StringAssert.Contains ( + "ViewHelper.mySetOnClickListener() invoked!", + logcatOutput, + "View.setOnClickListener() wasn't remapped to ViewHelper.mySetOnClickListener()!" + ); + } + + [Test] + public void SupportDesugaringStaticInterfaceMethods () + { + var proj = new XamarinAndroidApplicationProject () { + IsRelease = true, + EnableDefaultItems = true, + OtherBuildItems = { + new AndroidItem.AndroidJavaSource ("StaticMethodsInterface.java") { + Encoding = new UTF8Encoding (encoderShouldEmitUTF8Identifier: false), + TextContent = () => ResourceData.IdmStaticMethodsInterface, + Metadata = { + { "Bind", "True" }, + }, + }, + }, + }; + + // Note: To properly test, Desugaring must be *enabled*, which requires that + // `$(SupportedOSPlatformVersion)` be *less than* 23. 21 is currently the default, + // but set this explicitly anyway just so that this implicit requirement is explicit. + proj.SupportedOSPlatformVersion = "21"; + + proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", @" + Console.WriteLine ($""# jonp static interface default method invocation; IStaticMethodsInterface.Value={Example.IStaticMethodsInterface.Value}""); +"); + var builder = CreateApkBuilder (); + Assert.IsTrue (builder.Build (proj), "`dotnet build` should succeed"); + RunProjectAndAssert (proj, builder); + var appStartupLogcatFile = Path.Combine (Root, builder.ProjectDirectory, "logcat.log"); + bool didLaunch = WaitForActivityToStart (proj.PackageName, "MainActivity", appStartupLogcatFile); + Assert.IsTrue (didLaunch, "MainActivity should have launched!"); + var logcatOutput = File.ReadAllText (appStartupLogcatFile); + + StringAssert.Contains ( + "IStaticMethodsInterface.Value=3", + logcatOutput, + "Was IStaticMethodsInterface.Value executed?" + ); + } + } } diff --git a/tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs b/tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs deleted file mode 100644 index b33989a16a1..00000000000 --- a/tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs +++ /dev/null @@ -1,247 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net; -using System.Reflection; -using System.Text; -using System.Threading; -using Mono.Debugging.Client; -using Mono.Debugging.Soft; -using NUnit.Framework; -using Xamarin.ProjectTools; - -#if !NET472 -namespace Xamarin.Android.Build.Tests -{ - [Obsolete ("De-dupe and migrate these tests to InstallAndRunTests.cs")] - [TestFixture] - [Category ("UsesDevice"), Category ("WearOS")] - public class XASdkDeployTests : DeviceTest - { - static object [] DotNetInstallAndRunSource = new object [] { - new object[] { - /* isRelease */ false, - /* xamarinForms */ false, - /* targetFramework*/ "net8.0-android", - }, - new object[] { - /* isRelease */ true, - /* xamarinForms */ false, - /* targetFramework*/ "net8.0-android", - }, - new object[] { - /* isRelease */ false, - /* xamarinForms */ true, - /* targetFramework*/ "net8.0-android", - }, - new object[] { - /* isRelease */ true, - /* xamarinForms */ true, - /* targetFramework*/ "net8.0-android", - }, - new object[] { - /* isRelease */ true, - /* xamarinForms */ false, - /* targetFramework*/ "net7.0-android", - }, - new object[] { - /* isRelease */ false, - /* xamarinForms */ true, - /* targetFramework*/ "net7.0-android", - }, - new object[] { - /* isRelease */ true, - /* xamarinForms */ true, - /* targetFramework*/ "net7.0-android", - }, - }; - - [Test] - [TestCaseSource (nameof (DotNetInstallAndRunSource))] - public void DotNetInstallAndRun (bool isRelease, bool xamarinForms, string targetFramework) - { - XamarinAndroidApplicationProject proj; - if (xamarinForms) { - proj = new XamarinFormsAndroidApplicationProject { - IsRelease = isRelease, - EnableDefaultItems = true, - }; - } else { - proj = new XamarinAndroidApplicationProject { - IsRelease = isRelease, - EnableDefaultItems = true, - }; - } - proj.TargetFramework = targetFramework; - var builder = CreateApkBuilder (); - Assert.IsTrue (builder.Build (proj), "`dotnet build` should succeed"); - RunProjectAndAssert (proj, builder); - - WaitForPermissionActivity (Path.Combine (Root, builder.ProjectDirectory, "permission-logcat.log")); - bool didLaunch = WaitForActivityToStart (proj.PackageName, "MainActivity", - Path.Combine (Root, builder.ProjectDirectory, "logcat.log"), 30); - Assert.IsTrue(didLaunch, "Activity should have started."); - } - - [Test] - public void TypeAndMemberRemapping ([Values (false, true)] bool isRelease) - { - var proj = new XamarinAndroidApplicationProject () { - IsRelease = isRelease, - EnableDefaultItems = true, - OtherBuildItems = { - new AndroidItem._AndroidRemapMembers ("RemapActivity.xml") { - Encoding = Encoding.UTF8, - TextContent = () => ResourceData.RemapActivityXml, - }, - new AndroidItem.AndroidJavaSource ("RemapActivity.java") { - Encoding = new UTF8Encoding (encoderShouldEmitUTF8Identifier: false), - TextContent = () => ResourceData.RemapActivityJava, - Metadata = { - { "Bind", "True" }, - }, - }, - }, - }; - proj.MainActivity = proj.DefaultMainActivity.Replace (": Activity", ": global::Example.RemapActivity"); - var builder = CreateApkBuilder (); - Assert.IsTrue (builder.Build (proj), "`dotnet build` should succeed"); - RunProjectAndAssert (proj, builder); - var appStartupLogcatFile = Path.Combine (Root, builder.ProjectDirectory, "logcat.log"); - bool didLaunch = WaitForActivityToStart (proj.PackageName, "MainActivity", appStartupLogcatFile); - Assert.IsTrue (didLaunch, "MainActivity should have launched!"); - var logcatOutput = File.ReadAllText (appStartupLogcatFile); - - StringAssert.Contains ( - "RemapActivity.onMyCreate() invoked!", - logcatOutput, - "Activity.onCreate() wasn't remapped to RemapActivity.onMyCreate()!" - ); - StringAssert.Contains ( - "ViewHelper.mySetOnClickListener() invoked!", - logcatOutput, - "View.setOnClickListener() wasn't remapped to ViewHelper.mySetOnClickListener()!" - ); - } - - [Test] - public void SupportDesugaringStaticInterfaceMethods () - { - var proj = new XamarinAndroidApplicationProject () { - IsRelease = true, - EnableDefaultItems = true, - OtherBuildItems = { - new AndroidItem.AndroidJavaSource ("StaticMethodsInterface.java") { - Encoding = new UTF8Encoding (encoderShouldEmitUTF8Identifier: false), - TextContent = () => ResourceData.IdmStaticMethodsInterface, - Metadata = { - { "Bind", "True" }, - }, - }, - }, - }; - - // Note: To properly test, Desugaring must be *enabled*, which requires that - // `$(SupportedOSPlatformVersion)` be *less than* 23. 21 is currently the default, - // but set this explicitly anyway just so that this implicit requirement is explicit. - proj.SupportedOSPlatformVersion = "21"; - - proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", @" - Console.WriteLine ($""# jonp static interface default method invocation; IStaticMethodsInterface.Value={Example.IStaticMethodsInterface.Value}""); -"); - var builder = CreateApkBuilder (); - Assert.IsTrue (builder.Build (proj), "`dotnet build` should succeed"); - RunProjectAndAssert (proj, builder); - var appStartupLogcatFile = Path.Combine (Root, builder.ProjectDirectory, "logcat.log"); - bool didLaunch = WaitForActivityToStart (proj.PackageName, "MainActivity", appStartupLogcatFile); - Assert.IsTrue (didLaunch, "MainActivity should have launched!"); - var logcatOutput = File.ReadAllText (appStartupLogcatFile); - - StringAssert.Contains ( - "IStaticMethodsInterface.Value=3", - logcatOutput, - "Was IStaticMethodsInterface.Value executed?" - ); - } - - [Test] - [Category ("Debugger")] - [Retry(5)] - public void DotNetDebug ([Values("net7.0-android", "net8.0-android")] string targetFramework) - { - AssertCommercialBuild (); - - var proj = new XamarinAndroidApplicationProject () { - EnableDefaultItems = true, - TargetFramework = targetFramework, - }; - proj.SetRuntimeIdentifier (DeviceAbi); - string runtimeId = proj.GetProperty (KnownProperties.RuntimeIdentifier); - - var builder = CreateApkBuilder (); - - Assert.IsTrue (builder.Install (proj), "Install should succeed."); - - bool breakpointHit = false; - ManualResetEvent resetEvent = new ManualResetEvent (false); - var sw = new Stopwatch (); - // setup the debugger - var session = new SoftDebuggerSession (); - try { - session.Breakpoints = new BreakpointStore { - { Path.Combine (Root, builder.ProjectDirectory, "MainActivity.cs"), 10 }, - }; - session.TargetHitBreakpoint += (sender, e) => { - Console.WriteLine ($"BREAK {e.Type}"); - breakpointHit = true; - session.Continue (); - }; - var rnd = new Random (); - int port = rnd.Next (10000, 20000); - TestContext.Out.WriteLine ($"{port}"); - var args = new SoftDebuggerConnectArgs ("", IPAddress.Loopback, port) { - MaxConnectionAttempts = 10, - }; - var startInfo = new SoftDebuggerStartInfo (args) { - WorkingDirectory = Path.Combine (builder.ProjectDirectory, proj.IntermediateOutputPath, runtimeId, "android", "assets"), - }; - var options = new DebuggerSessionOptions () { - EvaluationOptions = EvaluationOptions.DefaultOptions, - }; - options.EvaluationOptions.UseExternalTypeResolver = true; - builder.BuildLogFile = Path.Combine (Root, builder.ProjectDirectory, "run.log"); - Assert.True (builder.RunTarget (proj, "Run", parameters: new [] { - $"AndroidSdbTargetPort={port}", - $"AndroidSdbHostPort={port}", - "AndroidAttachDebugger=True", - }), "Project should have run."); - WaitForPermissionActivity (Path.Combine (Root, builder.ProjectDirectory, "permission-logcat.log")); - Assert.IsTrue (WaitForDebuggerToStart (Path.Combine (Root, builder.ProjectDirectory, "logcat.log"), 120), "Activity should have started"); - // we need to give a bit of time for the debug server to start up. - WaitFor (2000); - session.LogWriter += (isStderr, text) => { Console.WriteLine (text); }; - session.OutputWriter += (isStderr, text) => { Console.WriteLine (text); }; - session.DebugWriter += (level, category, message) => { Console.WriteLine (message); }; - session.Run (startInfo, options); - WaitFor (TimeSpan.FromSeconds (30), () => session.IsConnected); - Assert.True (session.IsConnected, "Debugger should have connected but it did not."); - // we need to wait here for a while to allow the breakpoints to hit - // but we need to timeout - TimeSpan timeout = TimeSpan.FromSeconds (60); - while (session.IsConnected && !breakpointHit && timeout >= TimeSpan.Zero) { - Thread.Sleep (10); - timeout = timeout.Subtract (TimeSpan.FromMilliseconds (10)); - } - WaitFor (2000); - Assert.IsTrue (breakpointHit, "Should have a breakpoint"); - } catch (Exception ex) { - Assert.Fail($"Exception occurred {ex}"); - } finally { - session.Exit (); - } - } - } -} -#endif