diff --git a/Configuration.props b/Configuration.props index 4f97dd67381..e4ff79d9bf4 100644 --- a/Configuration.props +++ b/Configuration.props @@ -184,8 +184,9 @@ 5.0 7583922_latest $(AndroidSdkFullPath)\cmdline-tools\$(CommandLineToolsFolder)\bin - 7033400 - 30.3.5 + + 8129060 + 31.3.1 $(AndroidSdkFullPath)\emulator emulator $(AndroidNdkDirectory)\ndk-build @@ -242,12 +243,12 @@ - + True - + True diff --git a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/CreateAndroidEmulator.cs b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/CreateAndroidEmulator.cs index 3386ff2d4f0..8d8d1754a22 100644 --- a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/CreateAndroidEmulator.cs +++ b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/CreateAndroidEmulator.cs @@ -24,6 +24,7 @@ public class CreateAndroidEmulator : ToolTask public string ImageName {get; set;} = "XamarinAndroidTestRunner64"; public string DeviceName {get; set;} = "pixel_4"; + public string ImageType {get; set;} = "default"; public string DataPartitionSizeMB {get; set;} = "2048"; public string RamSizeMB {get; set;} = "2048"; @@ -32,6 +33,9 @@ public class CreateAndroidEmulator : ToolTask public override bool Execute () { + if (string.IsNullOrEmpty (ToolExe)) + ToolExe = "avdmanager"; + var dirs = string.IsNullOrEmpty (ToolPath) ? null : new [] { ToolPath }; @@ -43,7 +47,7 @@ public override bool Execute () ToolExe = filename; if (string.IsNullOrEmpty (TargetId) && !string.IsNullOrEmpty (SdkVersion)) { - TargetId = "system-images;android-" + SdkVersion + ";default;" + AndroidAbi; + TargetId = $"system-images;android-{SdkVersion};{ImageType};{AndroidAbi}"; } var env = new List (); diff --git a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/RunInstrumentationTests.cs b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/RunInstrumentationTests.cs index 4345b514a18..eb03232b392 100644 --- a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/RunInstrumentationTests.cs +++ b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/RunInstrumentationTests.cs @@ -19,7 +19,8 @@ public class RunInstrumentationTests : Adb const int StateGetLogcat = 1; const int StateClearLogcat = 2; const int StatePullFiles = 3; - const int MaxState = StatePullFiles; + const int StateRunAsCatFiles = 4; + const int MaxState = StateRunAsCatFiles; public string TestFixture { get; set; } @@ -41,6 +42,8 @@ public class RunInstrumentationTests : Adb public string LogLevel { get; set; } + public int ApiLevel { get; set; } + int currentState = -1; int instrumentationExitCode = 99; string targetTestResultsPath; @@ -98,10 +101,17 @@ public override bool Execute () ArgumentsString = $"{AdbTarget} {AdbOptions} logcat -c", IgnoreExitCode = true, }, - new CommandInfo { ArgumentsGenerator = () => $"{AdbTarget} {AdbOptions} pull \"{targetTestResultsPath}\" \"{NUnit2TestResultsFile}\"", - ShouldRun = () => !String.IsNullOrEmpty (targetTestResultsPath) + ShouldRun = () => !String.IsNullOrEmpty (targetTestResultsPath) && ApiLevel != 30, + IgnoreExitCode = true, + }, + new CommandInfo { + ArgumentsGenerator = () => $"{AdbTarget} {AdbOptions} shell run-as {PackageName} cat \"{targetTestResultsPath}\"", + ShouldRun = () => !String.IsNullOrEmpty (targetTestResultsPath) && ApiLevel == 30, + StdoutFilePath = NUnit2TestResultsFile, + StdoutAppend = false, + IgnoreExitCode = true, }, }; } diff --git a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/StartAndroidEmulator.cs b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/StartAndroidEmulator.cs index 18fd79b80f7..4dd077bf49b 100644 --- a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/StartAndroidEmulator.cs +++ b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/StartAndroidEmulator.cs @@ -34,6 +34,7 @@ public class StartAndroidEmulator : Task public string ToolPath {get; set;} public string ToolExe {get; set;} public string LogcatFile {get; set;} + public bool ShowWindow {get; set;} = true; public override bool Execute () { @@ -69,7 +70,8 @@ void Run (string emulator) return; var port = string.IsNullOrEmpty (Port) ? "" : $" -port {Port}"; - var arguments = $"{Arguments ?? string.Empty} -verbose -logcat-output \"{LogcatFile}\" -no-boot-anim -no-audio -no-snapshot -cache-size 512 -timezone \"Etc/UTC\" -avd {ImageName}{port}"; + var showWindow = ShowWindow ? "" : " -no-window"; + var arguments = $"{Arguments ?? string.Empty} -verbose -detect-image-hang -logcat-output \"{LogcatFile}\" -no-boot-anim -no-audio -no-snapshot -cache-size 512 -timezone \"Etc/UTC\" {showWindow}{port} -avd {ImageName}"; Log.LogMessage (MessageImportance.Low, $"Tool {emulator} execution started with arguments: {arguments}"); var psi = new ProcessStartInfo () { FileName = emulator, diff --git a/build-tools/automation/azure-pipelines-nightly.yaml b/build-tools/automation/azure-pipelines-nightly.yaml index 7b6a3e3f264..1b7eb512983 100644 --- a/build-tools/automation/azure-pipelines-nightly.yaml +++ b/build-tools/automation/azure-pipelines-nightly.yaml @@ -74,18 +74,31 @@ stages: Android21-x86: avdApiLevel: 21 avdAbi: x86 + avdType: default Android23-x86: avdApiLevel: 23 avdAbi: x86 + avdType: default Android24-x86: avdApiLevel: 24 avdAbi: x86 + avdType: default Android26-x86_64: avdApiLevel: 26 avdAbi: x86_64 + avdType: default Android28-x86_64: avdApiLevel: 28 avdAbi: x86_64 + avdType: default + Android30-x86_64: + avdApiLevel: 30 + avdAbi: x86_64 + avdType: default + Android31-x86_64: + avdApiLevel: 31 + avdAbi: x86_64 + avdType: default pool: vmImage: $(HostedMacImage) workspace: @@ -113,15 +126,15 @@ stages: inputs: solution: tests/Mono.Android-Tests/Mono.Android-Tests.csproj configuration: $(XA.Build.Configuration) - msbuildArguments: /t:InstallAvdImage;AcquireAndroidTarget /p:TestAvdApiLevel=$(avdApiLevel) /p:TestAvdAbi=$(avdAbi) /bl:$(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/install-emulator-$(avdApiLevel).binlog + msbuildArguments: /t:InstallAvdImage;AcquireAndroidTarget /p:TestAvdApiLevel=$(avdApiLevel) /p:TestAvdAbi=$(avdAbi) /p:TestAvdType=$(avdType) /bl:$(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/install-emulator-$(avdApiLevel).binlog - template: yaml-templates/apk-instrumentation.yaml parameters: configuration: $(XA.Build.Configuration) - testName: Mono.Android_Tests-$(avdApiLevel)-$(avdAbi) + testName: Mono.Android_Tests-$(avdApiLevel)-$(avdAbi)-$(avdType) project: tests/Mono.Android-Tests/Mono.Android-Tests.csproj testResultsFiles: TestResult-Mono.Android_Tests-$(XA.Build.Configuration).xml - extraBuildArgs: /p:TestAvdApiLevel=$(avdApiLevel) /p:TestAvdAbi=$(avdAbi) + extraBuildArgs: /p:TestAvdApiLevel=$(avdApiLevel) /p:TestAvdAbi=$(avdAbi) /p:TestAvdType=$(avdType) artifactSource: bin/Test$(XA.Build.Configuration)/Mono.Android_Tests-Signed.apk artifactFolder: Default @@ -130,13 +143,13 @@ stages: inputs: solution: tests/Mono.Android-Tests/Mono.Android-Tests.csproj configuration: $(XA.Build.Configuration) - msbuildArguments: /t:AcquireAndroidTarget,ReleaseAndroidTarget /p:TestAvdApiLevel=$(avdApiLevel) /p:TestAvdAbi=$(avdAbi) /bl:$(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/shutdown-emulator.binlog + msbuildArguments: /t:AcquireAndroidTarget,ReleaseAndroidTarget /p:TestAvdApiLevel=$(avdApiLevel) /p:TestAvdAbi=$(avdAbi) /p:TestAvdType=$(avdType) /bl:$(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/shutdown-emulator.binlog condition: always() - template: yaml-templates/upload-results.yaml parameters: configuration: $(XA.Build.Configuration) - artifactName: Test Results - Emulator $(avdApiLevel)-$(avdAbi) - macOS + artifactName: Test Results - Emulator $(avdApiLevel)-$(avdAbi)-$(avdType) - macOS - template: yaml-templates/fail-on-issue.yaml diff --git a/build-tools/automation/azure-pipelines.yaml b/build-tools/automation/azure-pipelines.yaml index 5afdc1047b9..ab2368dd5f8 100644 --- a/build-tools/automation/azure-pipelines.yaml +++ b/build-tools/automation/azure-pipelines.yaml @@ -996,6 +996,7 @@ stages: node_id: 1 job_name: mac_msbuilddevice_tests_1 job_suffix: Legacy + nunit_categories: '&& cat != Debugger' provisionatorChannel: ${{ parameters.provisionatorChannel }} - template: yaml-templates/run-msbuild-device-tests.yaml @@ -1003,6 +1004,7 @@ stages: node_id: 2 job_name: mac_msbuilddevice_tests_2 job_suffix: Legacy + nunit_categories: '&& cat != Debugger' provisionatorChannel: ${{ parameters.provisionatorChannel }} - template: yaml-templates/run-msbuild-device-tests.yaml @@ -1010,6 +1012,16 @@ stages: node_id: 3 job_name: mac_msbuilddevice_tests_3 job_suffix: Legacy + nunit_categories: '&& cat != Debugger' + provisionatorChannel: ${{ parameters.provisionatorChannel }} + + - template: yaml-templates/run-msbuild-device-tests.yaml + parameters: + node_id: 4 + job_name: mac_msbuilddevice_tests_with_debugger + job_suffix: Legacy + jdkTestFolder: $(XA.Jdk11.Folder) + nunit_categories: '&& cat == Debugger' provisionatorChannel: ${{ parameters.provisionatorChannel }} # Check - "Xamarin.Android (MSBuild Emulator Tests macOS - One .NET)" @@ -1040,6 +1052,15 @@ stages: target_framework: 'net6.0' provisionatorChannel: ${{ parameters.provisionatorChannel }} + - template: yaml-templates/run-msbuild-device-tests.yaml + parameters: + node_id: 4 + job_name: mac_dotnetdevice_tests_4 + job_suffix: One .NET + nunit_categories: $(DotNetNUnitCategories) + target_framework: 'net6.0' + provisionatorChannel: ${{ parameters.provisionatorChannel }} + - stage: designer_tests displayName: Designer Tests dependsOn: mac_build diff --git a/build-tools/automation/yaml-templates/run-msbuild-device-tests.yaml b/build-tools/automation/yaml-templates/run-msbuild-device-tests.yaml index 05ed310672c..5ad51b43315 100644 --- a/build-tools/automation/yaml-templates/run-msbuild-device-tests.yaml +++ b/build-tools/automation/yaml-templates/run-msbuild-device-tests.yaml @@ -73,8 +73,8 @@ jobs: useDotNet: ${{ eq(parameters.target_framework, 'net6.0') }} testRunTitle: MSBuildDeviceIntegration On Device - macOS-NoNode - ${{ parameters.job_suffix }} testAssembly: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/MSBuildDeviceIntegration/${{ parameters.target_framework }}/MSBuildDeviceIntegration.dll - nunitConsoleExtraArgs: --where "cat != Node-1 && cat != Node-2 && cat != Node-3 && cat != SystemApplication && cat != TimeZoneInfo && cat != SmokeTests ${{ parameters.nunit_categories }}" - dotNetTestExtraArgs: --filter "TestCategory != Node-1 & TestCategory != Node-2 & TestCategory != Node-3 & TestCategory != TimeZoneInfo ${{ parameters.nunit_categories }}" + nunitConsoleExtraArgs: --where "cat != Node-1 && cat != Node-2 && cat != Node-3 && cat != Node-4 && cat != SystemApplication && cat != TimeZoneInfo && cat != SmokeTests ${{ parameters.nunit_categories }}" + dotNetTestExtraArgs: --filter "TestCategory != Node-1 & TestCategory != Node-2 & TestCategory != Node-3 & TestCategory != Node-4 & TestCategory != TimeZoneInfo ${{ parameters.nunit_categories }}" testResultsFile: TestResult-MSBuildDeviceIntegration-${{ parameters.job_name }}-NoNode-$(XA.Build.Configuration).xml - task: MSBuild@1 diff --git a/build-tools/check-boot-times/Program.cs b/build-tools/check-boot-times/Program.cs index f274c87c2f3..85789c408ac 100644 --- a/build-tools/check-boot-times/Program.cs +++ b/build-tools/check-boot-times/Program.cs @@ -130,9 +130,10 @@ static async Task GetBootTime (bool coldBoot) { var times = new List (); int errors = 0; + var timeoutInMS = (int) TimeSpan.FromMinutes (15).TotalMilliseconds; Stopwatch sw = new Stopwatch (); - var token = coldBoot ? "emulator: INFO: boot time" : "onGuestSendCommand"; + var token = coldBoot ? "boot completed" : "onGuestSendCommand"; for (int i = 0; i < executionTimes; i++) { await CloseEmulator (); @@ -162,7 +163,7 @@ bool validation (string data, ManualResetEvent mre) bool hasTimedOut = false; sw.Reset (); sw.Start (); - if (!await RunProcess (emulatorPath, $"-avd {deviceName} {bootOptions} -verbose", 300000, validation, async () => { + if (!await RunProcess (emulatorPath, $"-avd {deviceName} {bootOptions} -verbose -detect-image-hang", timeoutInMS, validation, async () => { hasTimedOut = true; await ForceKillEmulator (); })) { diff --git a/build-tools/scripts/TestApks.targets b/build-tools/scripts/TestApks.targets index 42b846c8286..1b080efabef 100644 --- a/build-tools/scripts/TestApks.targets +++ b/build-tools/scripts/TestApks.targets @@ -19,11 +19,14 @@ 29 x86_64 - system-images;android-$(TestAvdApiLevel);default;$(TestAvdAbi) + default + system-images;android-$(TestAvdApiLevel);$(TestAvdType);$(TestAvdAbi) XamarinAndroidTestRunner$(TestAvdApiLevel)-$(TestAvdAbi) <_AdbEmulatorPort>5570 + <_AdbEmulatorShowWindow Condition=" '$(RunningOnCI)' == 'True' And '$(_AdbEmulatorShowWindow)' == '' ">False + <_AdbEmulatorShowWindow Condition=" '$(_AdbEmulatorShowWindow)' == '' ">True <_ApkSizesReferenceDirectory>$(MSBuildThisFileDirectory)..\..\tests\apk-sizes-reference - 5 + 10 $([MSBuild]::Multiply($(AvdLaunchTimeoutMinutes), 60)) $([MSBuild]::Multiply($(AvdLaunchTimeoutSeconds), 1000)) <_LogcatFilenameBase>$(MSBuildThisFileDirectory)..\..\bin\Test$(Configuration)\logcat-$(Configuration)$(TestsFlavor) @@ -58,6 +61,7 @@ SdkVersion="$(TestAvdApiLevel)" TargetId="$(SdkManagerImageName)" ImageName="$(TestAvdName)" + ImageType="$(TestAvdType)" ToolExe="$(AvdManagerToolExe)" ToolPath="$(CommandLineToolsBinPath)" RamSizeMB="3072" @@ -71,6 +75,7 @@ ImageName="$(TestAvdName)" LogcatFile="$(_LogcatFilenameBase)-full.txt" Port="$(_AdbEmulatorPort)" + ShowWindow="$(_AdbEmulatorShowWindow)" ToolExe="$(EmulatorToolExe)" ToolPath="$(EmulatorToolPath)"> @@ -83,7 +88,7 @@ Arguments="$(_AdbTarget) wait-for-device" ToolExe="$(AdbToolExe)" ToolPath="$(AdbToolPath)" - Timeout="120000" + Timeout="$(AvdLaunchTimeoutMS)" WriteOutputAsMessage="True" /> (); foreach (var fileMatch in testConfigFiles) { - Utilities.CopyFilesSimple (Directory.GetFiles (testConfigDir, fileMatch), destinationRoot, false); + // Handle files which might appear in multiple filters + // eg logcat-Relase-full.log will appear in both logcat* AND *log + foreach (var file in Directory.GetFiles (testConfigDir, fileMatch)) { + if (matchedFiles.Contains (file)) + continue; + matchedFiles.Add (file); + } } + Utilities.CopyFilesSimple (matchedFiles, destinationRoot, false); } var testConfigCompatDir = Path.Combine (testConfigDir, "compatibility"); diff --git a/samples/VSAndroidApp/Properties/AndroidManifest.xml b/samples/VSAndroidApp/Properties/AndroidManifest.xml index 64fca08fbf8..c48b180aa79 100644 --- a/samples/VSAndroidApp/Properties/AndroidManifest.xml +++ b/samples/VSAndroidApp/Properties/AndroidManifest.xml @@ -1,9 +1,9 @@  - - + diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/DeviceTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/DeviceTest.cs index fb14f67d0c3..43189393291 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/DeviceTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/DeviceTest.cs @@ -52,6 +52,14 @@ public void DeviceSetup () CreateGuestUser (GuestUserName); } + [OneTimeTearDown] + public void DeviceTearDown () + { + // make sure we are not on a guest user anymore. + SwitchUser (); + DeleteGuestUser(GuestUserName); + } + [SetUp] public void CheckDevice () { @@ -71,6 +79,7 @@ protected override void CleanupTest () string local = Path.Combine (outputDir, "screenshot.png"); string deviceLog = Path.Combine (outputDir, "logcat-failed.log"); string remote = "/data/local/tmp/screenshot.png"; + string localUi = Path.Combine (outputDir, "ui.xml"); RunAdbCommand ($"shell screencap {remote}"); var output = RunAdbCommand ($"logcat -d"); File.WriteAllText (deviceLog, output); @@ -81,6 +90,13 @@ protected override void CleanupTest () } else { TestContext.WriteLine ($"{local} did not exist!"); } + var ui = GetUI (timeoutInSeconds: 0); + ui.Save (localUi); + if (File.Exists (localUi)) { + TestContext.AddTestAttachment (localUi); + } else { + TestContext.WriteLine ($"{localUi} did not exist!"); + } } ClearAdbLogcat (); @@ -183,7 +199,7 @@ protected static bool MonitorAdbLogcat (Func action, string logcat } } - protected static bool WaitForDebuggerToStart (string logcatFilePath, int timeout = 60) + protected static bool WaitForDebuggerToStart (string logcatFilePath, int timeout = 120) { bool result = MonitorAdbLogcat ((line) => { return line.IndexOf ("Trying to initialize the debugger with options:", StringComparison.OrdinalIgnoreCase) > 0; @@ -191,7 +207,7 @@ protected static bool WaitForDebuggerToStart (string logcatFilePath, int timeout return result; } - static Regex regex = new Regex (@"\s*(\++)(?\d)s(?\d+)ms", RegexOptions.Compiled | RegexOptions.ExplicitCapture); + static Regex regex = new Regex (@"\s*(\++)(?\d+)s(?\d+)ms", RegexOptions.Compiled | RegexOptions.ExplicitCapture); protected static bool WaitForPermissionActivity (string logcatFilePath, int timeout = 5) { @@ -203,6 +219,12 @@ protected static bool WaitForPermissionActivity (string logcatFilePath, int time return result; } + protected static void ClearBlockingDialogs () + { + ClickButton ("", "android:id/aerr_wait", "Wait"); + WaitFor ((int)TimeSpan.FromSeconds (2).TotalMilliseconds); + } + protected static bool WaitForAppBuiltForOlderAndroidWarning (string packageName, string logcatFilePath, int timeout = 5) { bool result = MonitorAdbLogcat ((line) => { @@ -213,12 +235,12 @@ protected static bool WaitForAppBuiltForOlderAndroidWarning (string packageName, return result; } - protected static bool WaitForActivityToStart (string activityNamespace, string activityName, string logcatFilePath, int timeout = 60) + protected static bool WaitForActivityToStart (string activityNamespace, string activityName, string logcatFilePath, int timeout = 120) { return WaitForActivityToStart (activityNamespace, activityName, logcatFilePath, out TimeSpan time, timeout); } - protected static bool WaitForActivityToStart (string activityNamespace, string activityName, string logcatFilePath, out TimeSpan startupTime, int timeout = 60) + protected static bool WaitForActivityToStart (string activityNamespace, string activityName, string logcatFilePath, out TimeSpan startupTime, int timeout = 120) { startupTime = TimeSpan.Zero; string capturedLine = string.Empty; @@ -235,12 +257,16 @@ protected static bool WaitForActivityToStart (string activityNamespace, string a return result; } - protected static XDocument GetUI () + protected static XDocument GetUI (int timeoutInSeconds = 120) { var ui = RunAdbCommand ("exec-out uiautomator dump /dev/tty"); + int time = 0; while (ui.Contains ("ERROR:")) { ui = RunAdbCommand ("exec-out uiautomator dump /dev/tty"); WaitFor (1); + time += 1; + if (time * 1000 > timeoutInSeconds) + break; } ui = ui.Replace ("UI hierchary dumped to: /dev/tty", string.Empty).Trim (); try { @@ -250,18 +276,17 @@ protected static XDocument GetUI () } } - protected static (int x, int y, int w, int h) GetControlBounds (string packageName, string uiElement, string text) + protected static (int x, int y, int w, int h)? GetControlBounds (string packageName, string uiElement, string text, int timeoutInSeconds = 120) { var regex = new Regex (@"[(0-9)]\d*", RegexOptions.Compiled); - var result = (x: 0, y: 0, w: 0, h: 0); - var uiDoc = GetUI (); + var uiDoc = GetUI (timeoutInSeconds); var node = uiDoc.XPathSelectElement ($"//node[contains(@resource-id,'{uiElement}')]"); if (node == null) node = uiDoc.XPathSelectElement ($"//node[contains(@content-desc,'{uiElement}')]"); if (node == null) node = uiDoc.XPathSelectElement ($"//node[contains(@text,'{text}')]"); if (node == null) - return result; + return null; var bounds = node.Attribute ("bounds"); var matches = regex.Matches (bounds.Value); int.TryParse (matches [0].Value, out int x); @@ -271,10 +296,13 @@ protected static (int x, int y, int w, int h) GetControlBounds (string packageNa return (x: x, y: y, w: w, h: h); } - protected static void ClickButton (string packageName, string buttonName, string buttonText) + protected static bool ClickButton (string packageName, string buttonName, string buttonText, int timeoutInSeconds = 30) { - var bounds = GetControlBounds (packageName, buttonName, buttonText); - RunAdbInput ("input tap", bounds.x + ((bounds.w - bounds.x) / 2), bounds.y + ((bounds.h - bounds.y) / 2)); + var bounds = GetControlBounds (packageName, buttonName, buttonText, timeoutInSeconds); + if (!bounds.HasValue) + return false; + RunAdbInput ("input tap", bounds.Value.x + ((bounds.Value.w - bounds.Value.x) / 2), bounds.Value.y + ((bounds.Value.h - bounds.Value.y) / 2)); + return true; } /// @@ -313,7 +341,7 @@ protected static string [] GetOverrideDirectoryPaths (string packageName) protected static void CreateGuestUser (string username) { - if (GetUserId (username) != -1) + if (GetUserId (username) == -1) RunAdbCommand ($"shell pm create-user --guest {username}"); } @@ -327,7 +355,9 @@ protected static void DeleteGuestUser (string username) protected static int GetUserId (string username) { string output = RunAdbCommand ($"shell pm list users"); - Regex regex = new Regex (@"UserInfo{(?\d+):" + username, RegexOptions.Compiled); + if (string.IsNullOrEmpty (username)) + username = "Owner"; + Regex regex = new Regex ($@"UserInfo{{(?\d+):{username}", RegexOptions.Compiled); Console.WriteLine (output); var match = regex.Match (output); if (match.Success) { @@ -336,7 +366,7 @@ protected static int GetUserId (string username) return -1; } - protected static bool SwitchUser (string username) + protected static bool SwitchUser (string username = "") { int userId = GetUserId (username); if (userId == -1) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index 1d90657fd1a..22d1f013e52 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,37 +5,37 @@ "Size": 3032 }, "assemblies/Java.Interop.dll": { - "Size": 54984 + "Size": 55094 }, "assemblies/Mono.Android.dll": { - "Size": 87771 + "Size": 87709 }, "assemblies/rc.bin": { - "Size": 1045 + "Size": 1083 }, "assemblies/System.Linq.dll": { - "Size": 10157 + "Size": 10116 }, "assemblies/System.Private.CoreLib.dll": { - "Size": 521019 + "Size": 519296 }, "assemblies/System.Runtime.CompilerServices.Unsafe.dll": { - "Size": 1184 + "Size": 1163 }, "assemblies/System.Runtime.dll": { - "Size": 2410 + "Size": 2369 }, "assemblies/UnnamedProject.dll": { - "Size": 3544 + "Size": 3543 }, "classes.dex": { "Size": 345328 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 382760 + "Size": 382776 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3176048 + "Size": 3192432 }, "lib/arm64-v8a/libSystem.IO.Compression.Native.so": { "Size": 776216 @@ -44,10 +44,10 @@ "Size": 84064 }, "lib/arm64-v8a/libSystem.Security.Cryptography.Native.Android.so": { - "Size": 150024 + "Size": 150032 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 12424 + "Size": 12440 }, "META-INF/BNDLTOOL.RSA": { "Size": 1213 @@ -83,5 +83,5 @@ "Size": 1904 } }, - "PackageSize": 2705399 + "PackageSize": 2701303 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index 56915b5f6ea..2694418af3e 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -5,184 +5,184 @@ "Size": 3568 }, "assemblies/FormsViewGroup.dll": { - "Size": 7251 + "Size": 7247 }, "assemblies/Java.Interop.dll": { - "Size": 61908 + "Size": 62006 }, "assemblies/Mono.Android.dll": { - "Size": 442164 + "Size": 441706 }, "assemblies/mscorlib.dll": { - "Size": 3795 + "Size": 3798 }, "assemblies/netstandard.dll": { - "Size": 5495 + "Size": 5499 }, "assemblies/rc.bin": { "Size": 1083 }, "assemblies/System.Collections.Concurrent.dll": { - "Size": 11223 + "Size": 11227 }, "assemblies/System.Collections.dll": { "Size": 16736 }, "assemblies/System.Collections.NonGeneric.dll": { - "Size": 8438 + "Size": 8439 }, "assemblies/System.ComponentModel.dll": { - "Size": 1956 + "Size": 1961 }, "assemblies/System.ComponentModel.Primitives.dll": { - "Size": 2562 + "Size": 2566 }, "assemblies/System.ComponentModel.TypeConverter.dll": { - "Size": 5965 + "Size": 5968 }, "assemblies/System.Console.dll": { - "Size": 6528 + "Size": 6530 }, "assemblies/System.Core.dll": { - "Size": 1924 + "Size": 1928 }, "assemblies/System.Diagnostics.TraceSource.dll": { - "Size": 6754 + "Size": 6756 }, "assemblies/System.dll": { - "Size": 2271 + "Size": 2275 }, "assemblies/System.Drawing.dll": { - "Size": 1954 + "Size": 1957 }, "assemblies/System.Drawing.Primitives.dll": { - "Size": 12200 + "Size": 12199 }, "assemblies/System.IO.Compression.dll": { - "Size": 17214 + "Size": 17218 }, "assemblies/System.IO.IsolatedStorage.dll": { - "Size": 10565 + "Size": 10566 }, "assemblies/System.Linq.dll": { - "Size": 19471 + "Size": 19474 }, "assemblies/System.Linq.Expressions.dll": { - "Size": 182079 + "Size": 182081 }, "assemblies/System.Net.Http.dll": { - "Size": 65835 + "Size": 65831 }, "assemblies/System.Net.Primitives.dll": { - "Size": 22366 + "Size": 22364 }, "assemblies/System.Net.Requests.dll": { - "Size": 3729 + "Size": 3731 }, "assemblies/System.ObjectModel.dll": { "Size": 11970 }, "assemblies/System.Private.CoreLib.dll": { - "Size": 757439 + "Size": 757425 }, "assemblies/System.Private.DataContractSerialization.dll": { "Size": 191072 }, "assemblies/System.Private.Uri.dll": { - "Size": 43673 + "Size": 43677 }, "assemblies/System.Private.Xml.dll": { - "Size": 220174 + "Size": 220171 }, "assemblies/System.Private.Xml.Linq.dll": { - "Size": 17100 + "Size": 17101 }, "assemblies/System.Runtime.CompilerServices.Unsafe.dll": { "Size": 1214 }, "assemblies/System.Runtime.dll": { - "Size": 2553 + "Size": 2557 }, "assemblies/System.Runtime.Serialization.dll": { - "Size": 1886 + "Size": 1889 }, "assemblies/System.Runtime.Serialization.Formatters.dll": { - "Size": 2632 + "Size": 2634 }, "assemblies/System.Runtime.Serialization.Primitives.dll": { - "Size": 3936 + "Size": 3940 }, "assemblies/System.Security.Cryptography.Algorithms.dll": { - "Size": 6810 + "Size": 6809 }, "assemblies/System.Security.Cryptography.Primitives.dll": { "Size": 2968 }, "assemblies/System.Text.RegularExpressions.dll": { - "Size": 76705 + "Size": 76698 }, "assemblies/System.Xml.dll": { - "Size": 1777 + "Size": 1779 }, "assemblies/UnnamedProject.dll": { - "Size": 117240 + "Size": 117239 }, "assemblies/Xamarin.AndroidX.Activity.dll": { - "Size": 6076 + "Size": 6069 }, "assemblies/Xamarin.AndroidX.AppCompat.AppCompatResources.dll": { - "Size": 6099 + "Size": 6095 }, "assemblies/Xamarin.AndroidX.AppCompat.dll": { - "Size": 112593 + "Size": 112590 }, "assemblies/Xamarin.AndroidX.CardView.dll": { - "Size": 6816 + "Size": 6809 }, "assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": { - "Size": 16609 + "Size": 16603 }, "assemblies/Xamarin.AndroidX.Core.dll": { - "Size": 96724 + "Size": 96723 }, "assemblies/Xamarin.AndroidX.DrawerLayout.dll": { - "Size": 14275 + "Size": 14273 }, "assemblies/Xamarin.AndroidX.Fragment.dll": { - "Size": 39933 + "Size": 39924 }, "assemblies/Xamarin.AndroidX.Legacy.Support.Core.UI.dll": { - "Size": 6139 + "Size": 6132 }, "assemblies/Xamarin.AndroidX.Lifecycle.Common.dll": { - "Size": 6595 + "Size": 6592 }, "assemblies/Xamarin.AndroidX.Lifecycle.LiveData.Core.dll": { - "Size": 6675 + "Size": 6671 }, "assemblies/Xamarin.AndroidX.Lifecycle.ViewModel.dll": { - "Size": 3275 + "Size": 3273 }, "assemblies/Xamarin.AndroidX.Loader.dll": { - "Size": 12676 + "Size": 12671 }, "assemblies/Xamarin.AndroidX.RecyclerView.dll": { - "Size": 84690 + "Size": 84688 }, "assemblies/Xamarin.AndroidX.SavedState.dll": { - "Size": 5082 + "Size": 5077 }, "assemblies/Xamarin.AndroidX.SwipeRefreshLayout.dll": { - "Size": 10390 + "Size": 10382 }, "assemblies/Xamarin.AndroidX.ViewPager.dll": { - "Size": 17994 + "Size": 17986 }, "assemblies/Xamarin.Forms.Core.dll": { "Size": 528450 }, "assemblies/Xamarin.Forms.Platform.Android.dll": { - "Size": 385000 + "Size": 384996 }, "assemblies/Xamarin.Forms.Platform.dll": { "Size": 56878 @@ -191,16 +191,16 @@ "Size": 60774 }, "assemblies/Xamarin.Google.Android.Material.dll": { - "Size": 40136 + "Size": 40134 }, "classes.dex": { - "Size": 3483796 + "Size": 3458288 }, "lib/arm64-v8a/libmonodroid.so": { "Size": 382776 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3171952 + "Size": 3192432 }, "lib/arm64-v8a/libSystem.IO.Compression.Native.so": { "Size": 776216 @@ -212,7 +212,7 @@ "Size": 150032 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 133232 + "Size": 133192 }, "META-INF/android.support.design_material.version": { "Size": 12 @@ -779,7 +779,7 @@ "Size": 470 }, "res/drawable-hdpi-v4/icon.png": { - "Size": 4762 + "Size": 4791 }, "res/drawable-hdpi-v4/notification_bg_low_normal.9.png": { "Size": 212 @@ -1967,5 +1967,5 @@ "Size": 341228 } }, - "PackageSize": 7938591 + "PackageSize": 7930399 } \ No newline at end of file diff --git a/src/Xamarin.Android.NUnitLite/Gui/Instrumentations/TestSuiteInstrumentation.cs b/src/Xamarin.Android.NUnitLite/Gui/Instrumentations/TestSuiteInstrumentation.cs index 9c1d4c1eb53..aceff344af5 100644 --- a/src/Xamarin.Android.NUnitLite/Gui/Instrumentations/TestSuiteInstrumentation.cs +++ b/src/Xamarin.Android.NUnitLite/Gui/Instrumentations/TestSuiteInstrumentation.cs @@ -60,11 +60,14 @@ public override void OnStart () Log.Info (TAG, "NUnit automated tests started"); var testResult = AndroidRunner.Runner.Run (AndroidRunner.GetSetupTestTarget (arguments), TargetContext); var resultsFile = GetResultsPath (); + Log.Info (TAG, $"NUnit resultsFile {resultsFile}"); if (resultsFile != null) { var startTime = DateTime.Now; var resultsXml = new NUnit2XmlOutputWriter (startTime); resultsXml.WriteResultFile (testResult, resultsFile); - results.PutString ("nunit2-results-path", ToAdbPath (resultsFile)); + Log.Info (TAG, $"NUnit resultsFile {resultsFile} written"); + results.PutString ("nunit2-results-path", resultsFile); + Log.Info (TAG, $"NUnit PutString {resultsFile} done."); } Log.Info (TAG, "NUnit automated tests completed"); int run = 0, passed = 0, skipped = 0, inconclusive = 0; @@ -103,47 +106,18 @@ public override void OnStart () string GetResultsPath () { - Java.IO.File resultsPathFile = GetExternalFilesDir (); - var usePathFile = resultsPathFile != null && resultsPathFile.Exists (); - var resultsPath = usePathFile - ? resultsPathFile.AbsolutePath - : Path.Combine (Context.FilesDir.AbsolutePath, ".__override__"); + string pid = Guid.NewGuid ().ToString (); + Java.IO.File resultsPathFile = null; +#if __ANDROID_19__ + int sdk = ((int)Build.VERSION.SdkInt); + if (sdk >= 19) + resultsPathFile = TargetContext.GetExternalFilesDir (null); +#endif + bool usePathFile = resultsPathFile != null && resultsPathFile.Exists (); + string resultsPath = usePathFile ? resultsPathFile.AbsolutePath : TargetContext.FilesDir.AbsolutePath; if (!usePathFile && !Directory.Exists (resultsPath)) Directory.CreateDirectory (resultsPath); - return Path.Combine (resultsPath, "TestResults.xml"); - } - - Java.IO.File GetExternalFilesDir () - { - if (((int)Build.VERSION.SdkInt) < 19) - return null; - string type = null; -#if __ANDROID_19__ - type = global::Android.OS.Environment.DirectoryDocuments; -#else // !__ANDROID_19__ - type = global::Android.OS.Environment.DirectoryDownloads; -#endif // !__ANDROID_19__ - return Context.GetExternalFilesDir (type); - } - - // On some Android targets, the external storage directory is "emulated", - // in which case the paths used on-device by the application are *not* - // paths that can be used off-device with `adb pull`. - // For example, `Contxt.GetExternalFilesDir()` may return `/storage/emulated/foo`, - // but `adb pull /storage/emulated/foo` will *fail*; instead, we may need - // `adb pull /mnt/shell/emulated/foo`. - // The `$EMULATED_STORAGE_SOURCE` and `$EMULATED_STORAGE_TARGET` environment - // variables control the "on-device" (`$EMULATED_STORAGE_TARGET`) and - // "off-device" (`$EMULATED_STORAGE_SOURCE`) directory prefixes - string ToAdbPath (string path) - { - var source = System.Environment.GetEnvironmentVariable ("EMULATED_STORAGE_SOURCE"); - var target = System.Environment.GetEnvironmentVariable ("EMULATED_STORAGE_TARGET"); - - if (!string.IsNullOrEmpty (source) && !string.IsNullOrEmpty (target) && path.StartsWith (target, StringComparison.Ordinal)) { - return path.Replace (target, source); - } - return path; + return Path.Combine (resultsPath, $"TestResults_{(pid.Replace ("-", "_"))}.xml"); } protected abstract void AddTests (); diff --git a/tests/EmbeddedDSOs/EmbeddedDSO/Properties/AndroidManifest.xml b/tests/EmbeddedDSOs/EmbeddedDSO/Properties/AndroidManifest.xml index 99a124bf8ec..78abbbd92a6 100644 --- a/tests/EmbeddedDSOs/EmbeddedDSO/Properties/AndroidManifest.xml +++ b/tests/EmbeddedDSOs/EmbeddedDSO/Properties/AndroidManifest.xml @@ -1,6 +1,6 @@  - + diff --git a/tests/MSBuildDeviceIntegration/Tests/AotProfileTests.cs b/tests/MSBuildDeviceIntegration/Tests/AotProfileTests.cs index 3ade7ecd684..3bc35032b0b 100644 --- a/tests/MSBuildDeviceIntegration/Tests/AotProfileTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/AotProfileTests.cs @@ -26,7 +26,7 @@ public void BuildBasicApplicationAndAotProfileIt () var proj = new XamarinAndroidApplicationProject () { IsRelease = true, }; - proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64"); AddDotNetProfilerNativeLibraries (proj); var port = 9000 + new Random ().Next (1000); proj.SetProperty ("AndroidAotProfilerPort", port.ToString ()); diff --git a/tests/MSBuildDeviceIntegration/Tests/BundleToolTests.cs b/tests/MSBuildDeviceIntegration/Tests/BundleToolTests.cs index 143aa370863..aa546d6d10d 100644 --- a/tests/MSBuildDeviceIntegration/Tests/BundleToolTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/BundleToolTests.cs @@ -19,7 +19,7 @@ public class BundleToolTests : DeviceTest new object[] { true }, }; - static readonly string [] Abis = new [] { "armeabi-v7a", "arm64-v8a", "x86" }; + static readonly string [] Abis = new [] { "armeabi-v7a", "arm64-v8a", "x86", "x86_64" }; XamarinAndroidLibraryProject lib; XamarinAndroidApplicationProject app; ProjectBuilder libBuilder, appBuilder; diff --git a/tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs b/tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs index 3011e2e0ad2..b8e7bc22c7d 100755 --- a/tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs @@ -13,7 +13,7 @@ namespace Xamarin.Android.Build.Tests { [TestFixture] - [Category ("UsesDevice"), Category ("Node-3")] + [Category ("UsesDevice")] public class DebuggingTest : DeviceTest { [TearDown] public void ClearDebugProperties () @@ -43,15 +43,17 @@ void SetTargetFrameworkAndManifest(XamarinAndroidApplicationProject proj, Builde } [Test] + [Category ("Node-3")] public void ApplicationRunsWithoutDebugger ([Values (false, true)] bool isRelease, [Values (false, true)] bool extractNativeLibs, [Values (false, true)] bool useEmbeddedDex) { AssertHasDevices (); + SwitchUser (); var proj = new XamarinFormsAndroidApplicationProject () { IsRelease = isRelease, }; if (isRelease || !CommercialBuildAvailable) { - proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64"); } proj.SetDefaultTargetDevice (); if (Builder.UseDotNet && isRelease) { @@ -79,9 +81,11 @@ public void ApplicationRunsWithoutDebugger ([Values (false, true)] bool isReleas } [Test] + [Category ("Node-3")] public void ClassLibraryMainLauncherRuns ([Values (true, false)] bool preloadAssemblies) { AssertHasDevices (); + SwitchUser (); var path = Path.Combine ("temp", TestName); @@ -89,7 +93,7 @@ public void ClassLibraryMainLauncherRuns ([Values (true, false)] bool preloadAss ProjectName = "MyApp", }; if (!CommercialBuildAvailable) { - app.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + app.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64"); } app.SetDefaultTargetDevice (); app.SetProperty ("AndroidEnablePreloadAssemblies", preloadAssemblies.ToString ()); @@ -162,17 +166,26 @@ public void ClassLibraryMainLauncherRuns ([Values (true, false)] bool preloadAss }; #pragma warning restore 414 - [Test, Category ("Debugger")] + [Test, Category ("Debugger"), Category ("Node-4")] [TestCaseSource (nameof (DebuggerCustomAppTestCases))] + [Retry(5)] public void CustomApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool activityStarts) { AssertCommercialBuild (); AssertHasDevices (); + SwitchUser (); + + var path = Path.Combine (Root, "temp", TestName); + if (Directory.Exists (path)) { + TestContext.Out.WriteLine ($"Deleting previous run at '{path}'"); + Directory.Delete (path,recursive:true); + } + var proj = new XamarinAndroidApplicationProject () { IsRelease = false, AndroidFastDeploymentType = fastDevType, }; - proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64"); proj.SetProperty ("EmbedAssembliesIntoApk", embedAssemblies.ToString ()); proj.SetDefaultTargetDevice (); proj.Sources.Add (new BuildItem.Source ("MyApplication.cs") { @@ -198,7 +211,7 @@ public override void OnCreate () } "), }); - using (var b = CreateApkBuilder (Path.Combine ("temp", TestName))) { + using (var b = CreateApkBuilder (path)) { SetTargetFrameworkAndManifest (proj, b); Assert.True (b.Install (proj), "Project should have installed."); @@ -220,7 +233,7 @@ public override void OnCreate () int port = rnd.Next (10000, 20000); TestContext.Out.WriteLine ($"{port}"); var args = new SoftDebuggerConnectArgs ("", IPAddress.Loopback, port) { - MaxConnectionAttempts = 10, + MaxConnectionAttempts = 2000, // we need a long delay here to get a reliable connection }; var startInfo = new SoftDebuggerStartInfo (args) { WorkingDirectory = Path.Combine (b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets"), @@ -237,18 +250,18 @@ public override void OnCreate () "AndroidAttachDebugger=True", }), "Project should have run."); - // do we expect the app to start? - Assert.AreEqual (activityStarts, WaitForDebuggerToStart (Path.Combine (Root, b.ProjectDirectory, "logcat.log")), "Activity should have started"); - if (!activityStarts) - return; - // 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); }; + // do we expect the app to start? + Assert.AreEqual (activityStarts, WaitForDebuggerToStart (Path.Combine (Root, b.ProjectDirectory, "logcat.log")), "Debugger should have started"); + if (!activityStarts) + return; + Assert.False (session.HasExited, "Target should not have exited."); session.Run (startInfo, options); var expectedTime = TimeSpan.FromSeconds (1); var actualTime = ProfileFor (() => session.IsConnected); + Assert.True (session.IsConnected, "Debugger should have connected but it did not."); TestContext.Out.WriteLine ($"Debugger connected in {actualTime}"); Assert.LessOrEqual (actualTime, expectedTime, $"Debugger should have connected within {expectedTime} but it took {actualTime}."); // we need to wait here for a while to allow the breakpoints to hit @@ -328,20 +341,29 @@ public override void OnCreate () }; #pragma warning restore 414 - [Test, Category ("SmokeTests"), Category ("Debugger")] + [Test, Category ("SmokeTests"), Category ("Debugger"), Category ("Node-4")] [TestCaseSource (nameof(DebuggerTestCases))] + [Retry (5)] public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool allowDeltaInstall, string username, string debugType) { AssertCommercialBuild (); AssertHasDevices (); + SwitchUser (); + WaitFor (5000); + + var path = Path.Combine (Root, "temp", TestName); + if (Directory.Exists (path)) { + TestContext.Out.WriteLine ($"Deleting previous run at '{path}'"); + Directory.Delete (path,recursive:true); + } - var path = Path.Combine ("temp", TestName); int userId = GetUserId (username); List parameters = new List (); if (userId >= 0) parameters.Add ($"AndroidDeviceUserId={userId}"); if (SwitchUser (username)) { - WaitFor (5); + WaitFor (5000); + ClearBlockingDialogs (); ClickButton ("", "android:id/button1", "Yes continue"); } @@ -368,7 +390,7 @@ public Foo () }; app.MainPage = app.MainPage.Replace ("InitializeComponent ();", "InitializeComponent (); new Foo ();"); app.AddReference (lib); - app.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + app.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64"); app.SetProperty (KnownProperties._AndroidAllowDeltaInstall, allowDeltaInstall.ToString ()); if (!string.IsNullOrEmpty (debugType)) { app.SetProperty ("DebugType", debugType); @@ -412,7 +434,7 @@ public Foo () int port = rnd.Next (10000, 20000); TestContext.Out.WriteLine ($"{port}"); var args = new SoftDebuggerConnectArgs ("", IPAddress.Loopback, port) { - MaxConnectionAttempts = 10, + MaxConnectionAttempts = 2000, }; var startInfo = new SoftDebuggerStartInfo (args) { WorkingDirectory = Path.Combine (appBuilder.ProjectDirectory, app.IntermediateOutputPath, "android", "assets"), @@ -431,17 +453,24 @@ public Foo () Assert.True (appBuilder.RunTarget (app, "_Run", doNotCleanupOnUpdate: true, parameters: parameters.ToArray ()), "Project should have run."); - Assert.IsTrue (WaitForDebuggerToStart (Path.Combine (Root, appBuilder.ProjectDirectory, "logcat.log")), "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.LogWriter += (isStderr, text) => { + TestContext.Out.WriteLine (text); + }; + session.OutputWriter += (isStderr, text) => { + TestContext.Out.WriteLine (text); + }; + session.DebugWriter += (level, category, message) => { + TestContext.Out.WriteLine (message); + }; + Assert.IsTrue (WaitForDebuggerToStart (Path.Combine (Root, appBuilder.ProjectDirectory, "logcat.log")), "Debugger should have started"); session.Run (startInfo, options); - WaitFor (TimeSpan.FromSeconds (30), () => session.IsConnected); + TestContext.Out.WriteLine ($"Detected debugger startup in log"); + Assert.False (session.HasExited, "Target should not have exited."); + 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 + TestContext.Out.WriteLine ($"Debugger connected."); TimeSpan timeout = TimeSpan.FromSeconds (60); int expected = 4; while (session.IsConnected && breakcountHitCount < 3 && timeout >= TimeSpan.Zero) { @@ -452,7 +481,8 @@ public Foo () Assert.AreEqual (expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}"); breakcountHitCount = 0; ClearAdbLogcat (); - ClickButton (app.PackageName, "myXFButton", "CLICK ME"); + ClearBlockingDialogs (); + Assert.True (ClickButton (app.PackageName, "myXFButton", "CLICK ME"), "Button should have been clicked!"); while (session.IsConnected && breakcountHitCount < 1 && timeout >= TimeSpan.Zero) { Thread.Sleep (10); timeout = timeout.Subtract (TimeSpan.FromMilliseconds (10)); diff --git a/tests/MSBuildDeviceIntegration/Tests/DeleteBinObjTest.cs b/tests/MSBuildDeviceIntegration/Tests/DeleteBinObjTest.cs index b536634bc2c..783b4d58af0 100644 --- a/tests/MSBuildDeviceIntegration/Tests/DeleteBinObjTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/DeleteBinObjTest.cs @@ -50,7 +50,9 @@ void RunTest (string name, string sln, string csproj, string version, string rev "IntermediateOutputPath=" + Path.Combine ("obj", isRelease ? "Release" : "Debug", "90") + Path.DirectorySeparatorChar }; if (isRelease || !CommercialBuildAvailable) { - parameters.Add (KnownProperties.AndroidSupportedAbis + "=\"armeabi-v7a;x86\""); + parameters.Add (KnownProperties.AndroidSupportedAbis + "=\"armeabi-v7a;x86;x86_64\""); + } else { + parameters.Add (KnownProperties.AndroidSupportedAbis + "=\"armeabi-v7a;arm64-v8a;x86;x86_64\""); } if (HasDevices) { Assert.IsTrue (builder.Install (project, doNotCleanupOnUpdate: true, parameters: parameters.ToArray (), saveProject: false), diff --git a/tests/MSBuildDeviceIntegration/Tests/DeploymentTest.cs b/tests/MSBuildDeviceIntegration/Tests/DeploymentTest.cs index c78bca35f76..26096b0cf25 100644 --- a/tests/MSBuildDeviceIntegration/Tests/DeploymentTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/DeploymentTest.cs @@ -38,7 +38,7 @@ public void BeforeDeploymentTests () RunAdbCommand ("shell settings put global auto_time_zone 0"); proj = new XamarinFormsAndroidApplicationProject (); - proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64"); var mainPage = proj.Sources.First (x => x.Include () == "MainPage.xaml.cs"); var source = mainPage.TextContent ().Replace ("InitializeComponent ();", @"InitializeComponent (); Console.WriteLine ($""TimeZoneInfoNative={Java.Util.TimeZone.Default.ID}""); @@ -60,6 +60,7 @@ public void BeforeDeploymentTests () "; Assert.IsTrue (builder.Build (proj), "Build should have succeeded."); + builder.BuildLogFile = "install.log"; Assert.IsTrue (builder.Install (proj), "Install should have succeeded."); } @@ -69,8 +70,18 @@ public void AfterDeploymentTests () if (HasDevices && proj != null) RunAdbCommand ($"uninstall {proj.PackageName}"); - if (TestContext.CurrentContext.Result.FailCount == 0 && builder != null && Directory.Exists (Path.Combine (Root, builder.ProjectDirectory))) - Directory.Delete (Path.Combine (Root, builder.ProjectDirectory), recursive: true); + if (builder != null) + return; + + string output = Path.Combine (Root, builder.ProjectDirectory); + if (TestContext.CurrentContext.Result.FailCount == 0 && Directory.Exists (output)) { + Directory.Delete (output, recursive: true); + return; + } + + foreach (var file in Directory.GetFiles (output, "*.log", SearchOption.AllDirectories)) { + TestContext.AddTestAttachment (file, Path.GetFileName (output)); + } } [Test] @@ -135,8 +146,10 @@ public void CheckResouceIsOverridden ([Values (true, false)] bool useAapt2) WaitForPermissionActivity (Path.Combine (Root, builder.ProjectDirectory, "permission-logcat.log")); WaitForActivityToStart (app.PackageName, "MainActivity", Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log"), 15); + ClearBlockingDialogs (); XDocument ui = GetUI (); XElement node = ui.XPathSelectElement ($"//node[contains(@resource-id,'myButton')]"); + Assert.IsNotNull (node , "Could not find `my-Button` in the user interface. Check the screenshot of the test failure."); StringAssert.AreEqualIgnoringCase ("Click Me! One", node.Attribute ("text").Value, "Text of Button myButton should have been \"Click Me! One\""); b.BuildLogFile = "clean.log"; Assert.IsTrue (b.Clean (app, doNotCleanupOnUpdate: true), "Clean should have suceeded."); @@ -185,6 +198,7 @@ public void CheckXamarinFormsAppDeploysAndAButtonWorks () WaitForActivityToStart (proj.PackageName, "MainActivity", Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log"), 15); ClearAdbLogcat (); + ClearBlockingDialogs (); ClickButton (proj.PackageName, "myXFButton", "CLICK ME"); Assert.IsTrue (MonitorAdbLogcat ((line) => { return line.Contains ("Button was Clicked!"); diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index dcc77f12b11..6c36e6a6083 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -41,7 +41,7 @@ public void GlobalLayoutEvent_ShouldRegisterAndFire_OnActivityLaunch ([Values (f TargetSdkVersion = null, }; if (isRelease || !CommercialBuildAvailable) { - proj.SetAndroidSupportedAbis ("armeabi-v7a", "arm64-v8a", "x86"); + proj.SetAndroidSupportedAbis ("armeabi-v7a", "arm64-v8a", "x86", "x86_64"); } proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", $@"button.ViewTreeObserver.GlobalLayout += Button_ViewTreeObserver_GlobalLayout; @@ -190,7 +190,7 @@ public void SmokeTestBuildAndRunWithSpecialCharacters () ProjectName = testName, IsRelease = true, }; - proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64"); proj.SetDefaultTargetDevice (); using (var builder = CreateApkBuilder (Path.Combine (rootPath, proj.ProjectName))){ Assert.IsTrue (builder.Install (proj), "Install should have succeeded."); @@ -494,7 +494,7 @@ public void JsonDeserializationCreatesJavaHandle ([Values (false, true)] bool is }; if (isRelease || !CommercialBuildAvailable) { - proj.SetAndroidSupportedAbis ("armeabi-v7a", "arm64-v8a", "x86"); + proj.SetAndroidSupportedAbis ("armeabi-v7a", "arm64-v8a", "x86", "x86_64"); } proj.References.Add (new BuildItem.Reference ("System.Runtime.Serialization")); diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs index 7cc5bf0ada0..12bf43c3770 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs @@ -38,7 +38,7 @@ public void ReInstallIfUserUninstalled ([Values (false, true)] bool isRelease) IsRelease = isRelease, }; if (isRelease) { - proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64"); } using (var builder = CreateApkBuilder ()) { Assert.IsTrue (builder.Build (proj)); @@ -69,7 +69,7 @@ public void InstallAndUnInstall ([Values (false, true)] bool isRelease) if (isRelease) { // Set debuggable=true to allow run-as command usage with a release build proj.AndroidManifest = proj.AndroidManifest.Replace ("Mono.Android-Tests Properties\AndroidManifest.xml armeabi-v7a;x86 + $(AndroidSupportedAbis);x86_64 true All true @@ -45,6 +46,7 @@ None false true + true true @@ -53,6 +55,7 @@ 4 false true + true r8 diff --git a/tests/Mono.Android-Tests/Properties/AndroidManifest.xml b/tests/Mono.Android-Tests/Properties/AndroidManifest.xml index a67c4caa579..3a108a7ade0 100644 --- a/tests/Mono.Android-Tests/Properties/AndroidManifest.xml +++ b/tests/Mono.Android-Tests/Properties/AndroidManifest.xml @@ -1,6 +1,6 @@  - + diff --git a/tests/Mono.Android-Tests/Runtime-AppBundle/Properties/AndroidManifest.xml b/tests/Mono.Android-Tests/Runtime-AppBundle/Properties/AndroidManifest.xml index 88d4e606197..b4953758066 100644 --- a/tests/Mono.Android-Tests/Runtime-AppBundle/Properties/AndroidManifest.xml +++ b/tests/Mono.Android-Tests/Runtime-AppBundle/Properties/AndroidManifest.xml @@ -1,6 +1,6 @@  - + diff --git a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/AndroidManifest.xml b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/AndroidManifest.xml index 7ef0c18d3a7..aae3d489b4b 100644 --- a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/AndroidManifest.xml +++ b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/tests/Mono.Android-Tests/Runtime-MultiDex/Properties/AndroidManifest.xml b/tests/Mono.Android-Tests/Runtime-MultiDex/Properties/AndroidManifest.xml index adfa8536d7b..cb56511ab2d 100644 --- a/tests/Mono.Android-Tests/Runtime-MultiDex/Properties/AndroidManifest.xml +++ b/tests/Mono.Android-Tests/Runtime-MultiDex/Properties/AndroidManifest.xml @@ -1,6 +1,6 @@  - + diff --git a/tests/Mono.Android-Tests/System.Net/NetworkInterfaces.cs b/tests/Mono.Android-Tests/System.Net/NetworkInterfaces.cs index d850ceae07d..f6515799427 100644 --- a/tests/Mono.Android-Tests/System.Net/NetworkInterfaces.cs +++ b/tests/Mono.Android-Tests/System.Net/NetworkInterfaces.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.NetworkInformation; using Java.Net; @@ -9,7 +10,7 @@ using MNetworkInterface = System.Net.NetworkInformation.NetworkInterface; using JNetworkInterface = Java.Net.NetworkInterface; -namespace System.NetTests +namespace System.NetTests { [TestFixture] public class NetworkInterfacesTest @@ -73,7 +74,7 @@ bool AddressesAreEqual (List one, List two) return false; if (one.Count != two.Count) return false; - + foreach (IPAddress addr in one) { if (!two.Contains (addr)) return false; @@ -181,6 +182,9 @@ byte[] GetHardwareAddress (MNetworkInterface inf) // Map to android's idea of device address if (bytes.Length == 0 || inf.NetworkInterfaceType == NetworkInterfaceType.Tunnel) return null; + // if all the bytes are zero return null like Java does. + if (bytes.All (x => x == 0)) + return null; return bytes; } diff --git a/tests/TestRunner.Core/TestInstrumentation.cs b/tests/TestRunner.Core/TestInstrumentation.cs index 3095f10ce4d..0f9abf5fcee 100644 --- a/tests/TestRunner.Core/TestInstrumentation.cs +++ b/tests/TestRunner.Core/TestInstrumentation.cs @@ -62,7 +62,7 @@ string FindTestAssembly (string name) if (aname == null) return null; - + foreach (string dir in TestAssemblyDirectories) { if (String.IsNullOrEmpty (dir)) continue; @@ -244,7 +244,7 @@ void LogDeviceInfo () LogPaddedInfo ("VERSION.Release", Build.VERSION.Release, alignColumn); LogPaddedInfo ("VERSION.Sdk", Build.VERSION.Sdk, alignColumn); LogPaddedInfo ("VERSION.SdkInt", Build.VERSION.SdkInt.ToString (), alignColumn); - LogPaddedInfo ("Device Date/Time", DateTime.UtcNow.ToString (), alignColumn); + LogPaddedInfo ("Device Date/Time", DateTime.UtcNow.ToString (), alignColumn); // FIXME: add data about how the app was compiled (e.g. ARMvX, LLVM, Linker options) } @@ -285,7 +285,7 @@ bool RunTests (ref Bundle results) results.PutLong (ResultInconclusiveTests, runner.InconclusiveTests); results.PutLong (ResultTotalTests, runner.TotalTests); results.PutLong (ResultFilteredTests, runner.FilteredTests); - results.PutString (ResultResultsFilePath, ToAdbPath (resultsFilePath)); + results.PutString (ResultResultsFilePath, ToAdbPath(resultsFilePath)); Log.Info (LogTag, $"Passed: {runner.PassedTests}, Failed: {runner.FailedTests}, Skipped: {runner.SkippedTests}, Inconclusive: {runner.InconclusiveTests}, Total: {runner.TotalTests}, Filtered: {runner.FilteredTests}"); @@ -380,7 +380,7 @@ protected HashSet LoadExcludedTests (TextReader reader) string line = reader.ReadLine ()?.Trim (); if (line == null) return excludedTestNames; - + if (line.Length == 0 || line.StartsWith ("#", StringComparison.Ordinal)) continue; @@ -407,7 +407,9 @@ string ToAdbPath (string path) string source = global::System.Environment.GetEnvironmentVariable ("EMULATED_STORAGE_SOURCE")?.Trim (); string target = global::System.Environment.GetEnvironmentVariable ("EMULATED_STORAGE_TARGET")?.Trim (); - if (!String.IsNullOrEmpty (source) && !String.IsNullOrEmpty (target) && path.StartsWith (target, StringComparison.Ordinal)) { + if (!String.IsNullOrEmpty (source) && !String.IsNullOrEmpty (target) && + path.StartsWith (target, StringComparison.Ordinal) && + ((int)Build.VERSION.SdkInt) <= 28) { return path.Replace (target, source); } diff --git a/tests/TestRunner.Core/TestRunner.cs b/tests/TestRunner.Core/TestRunner.cs index b24051fd431..886063a53bf 100644 --- a/tests/TestRunner.Core/TestRunner.cs +++ b/tests/TestRunner.Core/TestRunner.cs @@ -97,18 +97,21 @@ protected virtual string GetResultsFilePath () { if (String.IsNullOrEmpty (ResultsFileName)) throw new InvalidOperationException ("Runner didn't specify a valid results file name"); - + + string pid = Guid.NewGuid ().ToString (); + Java.IO.File resultsPathFile = null; #if __ANDROID_19__ - if (((int)Build.VERSION.SdkInt) >= 19) - resultsPathFile = Context.GetExternalFilesDir (global::Android.OS.Environment.DirectoryDocuments); + int sdk = ((int)Build.VERSION.SdkInt); + if (sdk >= 19) + resultsPathFile = Context.GetExternalFilesDir (null); #endif bool usePathFile = resultsPathFile != null && resultsPathFile.Exists (); - string resultsPath = usePathFile ? resultsPathFile.AbsolutePath : Path.Combine (Context.FilesDir.AbsolutePath, ".__override__"); + string resultsPath = usePathFile ? resultsPathFile.AbsolutePath : Context.FilesDir.AbsolutePath; if (!usePathFile && !Directory.Exists (resultsPath)) Directory.CreateDirectory (resultsPath); - return Path.Combine (resultsPath, ResultsFileName); + return Path.Combine (resultsPath, $"{(pid.Replace ("-", "_"))}_{ResultsFileName}"); } } }