diff --git a/eng/helix_xharness.proj b/eng/helix_xharness.proj index 8778486c692d..1f92825306e9 100644 --- a/eng/helix_xharness.proj +++ b/eng/helix_xharness.proj @@ -3,9 +3,14 @@ test/devices/ $(BUILD_BUILDNUMBER) default - osx.15.arm64.maui.open - osx.15.arm64.maui.open - ubuntu.2204.amd64.android.33.open + + osx.15.arm64.maui.open + osx.15.arm64.maui.open + ubuntu.2204.amd64.android.33.open + + osx.15.arm64.iphone.maui + osx.15.arm64.iphone.maui + ubuntu.2204.amd64.android.33 true maui true @@ -110,7 +115,7 @@ 02:00:00 01:15:00 00:10:00 - $([System.IO.Directory]::GetDirectories('$(ScenariosDir)Controls.DeviceTests/Release/$(TargetFrameworkToTest)-ios/', '*.app', System.IO.SearchOption.AllDirectories)) + $([System.IO.Directory]::GetDirectories('$(ScenariosDir)Controls.DeviceTests/Release/net11.0-ios/', '*.app', System.IO.SearchOption.AllDirectories)) xharness apple test --target "$target" --app "$app" --output-directory "$output_directory" --timeout "$timeout" --launch-timeout "$launch_timeout" --set-env="TestFilter=Category=%(Identity)" @@ -119,27 +124,27 @@ 02:00:00 01:15:00 00:10:00 - $([System.IO.Directory]::GetDirectories('$(ScenariosDir)Controls.DeviceTests/Release/$(TargetFrameworkToTest)-ios/', '*.app', System.IO.SearchOption.AllDirectories)) + $([System.IO.Directory]::GetDirectories('$(ScenariosDir)Controls.DeviceTests/Release/net11.0-ios/', '*.app', System.IO.SearchOption.AllDirectories)) xharness apple test --target "$target" --app "$app" --output-directory "$output_directory" --timeout "$timeout" --launch-timeout "$launch_timeout" --set-env="TestFilter=SkipCategories=$(ControlsTestCategoriesToSkipForRestOfTests)" - + ios-simulator-64 02:00:00 01:00:00 - + ios-simulator-64 02:00:00 01:00:00 - + ios-simulator-64 02:00:00 01:00:00 - + ios-simulator-64 02:00:00 01:00:00 @@ -148,7 +153,7 @@ - + maccatalyst 02:00:00 01:00:00 @@ -158,7 +163,7 @@ - <_apks Include="%(_MAUIScenarioSearch.PayloadDirectory)/Release/$(TargetFrameworkToTest)-android/**/*Signed.apk" /> + <_apks Include="%(_MAUIScenarioSearch.PayloadDirectory)/Release/net10.0-android/**/*Signed.apk" /> 02:00:00 01:00:00 diff --git a/eng/pipelines/arcade/stage-device-tests.yml b/eng/pipelines/arcade/stage-device-tests.yml index 5084754e7e5e..f0b4a1d95b6d 100644 --- a/eng/pipelines/arcade/stage-device-tests.yml +++ b/eng/pipelines/arcade/stage-device-tests.yml @@ -46,6 +46,9 @@ parameters: - name: checkoutDirectory type: string default: $(System.DefaultWorkingDirectory) +- name: HelixAccessToken + type: string + default: '' stages: - stage: devicetests_build @@ -71,7 +74,7 @@ stages: jobs: - job: builddevice_tests displayName: Build Device Tests (Mono) - timeoutInMinutes: 60 + timeoutInMinutes: 120 variables: - name: _BuildConfig value: ${{ parameters.BuildConfiguration }} @@ -145,7 +148,11 @@ stages: - template: /eng/common/templates-official/steps/send-to-helix.yml parameters: HelixProjectPath: ${{ parameters.helixProject }} - HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsIOS_ + ${{ if eq(parameters.runAsPublic, true) }}: + HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsIOS_ /p:HelixInternal=False + ${{ else }}: + HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsIOS_ /p:HelixInternal=True + HelixAccessToken: ${{ parameters.HelixAccessToken }} HelixConfiguration: $(_BuildConfig) IncludeDotNetCli: true DisplayNamePrefix: DeviceTestsIOS @@ -176,7 +183,7 @@ stages: jobs: - job: device_tests_maccatalyst displayName: Run DeviceTests MacCatalyst (Mono) - timeoutInMinutes: 60 + timeoutInMinutes: 240 variables: - name: _BuildConfig value: ${{ parameters.BuildConfiguration }} @@ -195,7 +202,11 @@ stages: - template: /eng/common/templates-official/steps/send-to-helix.yml parameters: HelixProjectPath: ${{ parameters.helixProject }} - HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsMacCatalyst_ + ${{ if eq(parameters.runAsPublic, true) }}: + HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsMacCatalyst_ /p:HelixInternal=False + ${{ else }}: + HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsMacCatalyst_ /p:HelixInternal=True + HelixAccessToken: ${{ parameters.HelixAccessToken }} HelixConfiguration: $(_BuildConfig) IncludeDotNetCli: true DisplayNamePrefix: DeviceTestsMacCatalyst @@ -243,7 +254,11 @@ stages: - template: /eng/common/templates-official/steps/send-to-helix.yml parameters: HelixProjectPath: ${{ parameters.helixProject }} - HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsAndroid_ + ${{ if eq(parameters.runAsPublic, true) }}: + HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsAndroid_ /p:HelixInternal=False + ${{ else }}: + HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsAndroid_ /p:HelixInternal=True + HelixAccessToken: ${{ parameters.HelixAccessToken }} HelixConfiguration: $(_BuildConfig) IncludeDotNetCli: true DisplayNamePrefix: DeviceTestsAndroid @@ -272,7 +287,7 @@ stages: jobs: - job: builddevice_tests_coreclr displayName: Build Device Tests (CoreCLR) - timeoutInMinutes: 60 + timeoutInMinutes: 120 variables: - name: _BuildConfig value: ${{ parameters.BuildConfiguration }} @@ -346,7 +361,11 @@ stages: - template: ${{ iif(eq(parameters.runAsPublic, 'true'), '/eng/common/templates/steps/send-to-helix.yml', '/eng/common/templates-official/steps/send-to-helix.yml@self') }} parameters: HelixProjectPath: ${{ parameters.helixProject }} - HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsAndroid_CoreCLR_ + ${{ if eq(parameters.runAsPublic, true) }}: + HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsAndroid_CoreCLR_ /p:HelixInternal=False + ${{ else }}: + HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsAndroid_CoreCLR_ /p:HelixInternal=True + HelixAccessToken: ${{ parameters.HelixAccessToken }} HelixConfiguration: $(_BuildConfig) IncludeDotNetCli: true DisplayNamePrefix: DeviceTestsAndroid_CoreCLR @@ -394,7 +413,7 @@ stages: - template: ${{ iif(eq(parameters.runAsPublic, 'true'), '/eng/common/templates/steps/send-to-helix.yml', '/eng/common/templates-official/steps/send-to-helix.yml@self') }} parameters: HelixProjectPath: ${{ parameters.helixProject }} - HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix="_$(_BuildConfig)_CoreCLR" /p:TestRunNamePrefix="DeviceTestsIOS_CoreCLR_" + HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsIOS_CoreCLR_ HelixConfiguration: $(_BuildConfig) IncludeDotNetCli: true DisplayNamePrefix: DeviceTestsIOS_CoreCLR @@ -444,7 +463,7 @@ stages: - template: ${{ iif(eq(parameters.runAsPublic, 'true'), '/eng/common/templates/steps/send-to-helix.yml', '/eng/common/templates-official/steps/send-to-helix.yml@self') }} parameters: HelixProjectPath: ${{ parameters.helixProject }} - HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix="_$(_BuildConfig)_CoreCLR" /p:TestRunNamePrefix="DeviceTestsMacCatalyst_CoreCLR_" + HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsMacCatalyst_CoreCLR_ HelixConfiguration: $(_BuildConfig) IncludeDotNetCli: true DisplayNamePrefix: DeviceTestsMacCatalyst_CoreCLR diff --git a/eng/pipelines/ci-device-tests.yml b/eng/pipelines/ci-device-tests.yml index 2d97beb06379..617e1987fcad 100644 --- a/eng/pipelines/ci-device-tests.yml +++ b/eng/pipelines/ci-device-tests.yml @@ -47,10 +47,36 @@ variables: - template: /eng/common/templates/variables/pool-providers.yml@self - template: /eng/pipelines/common/variables.yml@self - template: /eng/pipelines/arcade/variables.yml@self +# Include Helix access token for internal builds +- ${{ if eq(variables['System.TeamProject'], 'internal') }}: + - group: DotNet-HelixApi-Access parameters: -- name: windowsPool +# Internal pools (dnceng) +- name: windowsPoolInternal + type: object + default: + name: NetCore1ESPool-Internal + demands: + - ImageOverride -equals 1es-windows-2022 + image: 1es-windows-2022 + os: Windows + +- name: macOSTestPoolInternal + type: object + default: + name: Azure Pipelines + vmImage: macOS-15 + +- name: macOSPoolInternal + type: object + default: + name: Azure Pipelines + vmImage: macOS-15 + +# Public pools (dnceng-public) +- name: windowsPoolPublic type: object default: name: NetCore-Public @@ -59,13 +85,13 @@ parameters: image: 1es-windows-2022-open os: Windows -- name: macOSTestPool +- name: macOSTestPoolPublic type: object default: name: MAUI vmImage: MAUI -- name: macOSPool +- name: macOSPoolPublic type: object default: name: MAUI @@ -84,10 +110,17 @@ stages: # Use Helix for iOS / Android and MacCatalyst Device Tests - template: /eng/pipelines/arcade/stage-device-tests.yml@self parameters: - buildPool: ${{ parameters.macOSPool }} - testPool: ${{ parameters.windowsPool }} - runAsPublic: true - TargetFrameworkVersion: net11.0 + # Select pools based on pipeline - internal vs public + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + buildPool: ${{ parameters.macOSPoolInternal }} + testPool: ${{ parameters.windowsPoolInternal }} + runAsPublic: false + HelixAccessToken: $(HelixApiAccessToken) + ${{ else }}: + buildPool: ${{ parameters.macOSPoolPublic }} + testPool: ${{ parameters.windowsPoolPublic }} + runAsPublic: true + TargetFrameworkVersion: ${{ targetFrameworkVersion.tfm }} prepareSteps: - template: /eng/pipelines/common/provision.yml@self parameters: @@ -104,7 +137,10 @@ stages: # Just use the old way for Windows Device Tests - template: common/device-tests.yml parameters: - windowsPool: ${{ parameters.windowsPool }} + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + windowsPool: ${{ parameters.windowsPoolInternal }} + ${{ else }}: + windowsPool: ${{ parameters.windowsPoolPublic }} targetFrameworkVersion: ${{ targetFrameworkVersion }} windowsVersions: [ 'packaged', 'unpackaged' ] skipProvisioning: true diff --git a/eng/pipelines/ci-uitests.yml b/eng/pipelines/ci-uitests.yml index 6a821cb21202..cb1526b6d4fd 100644 --- a/eng/pipelines/ci-uitests.yml +++ b/eng/pipelines/ci-uitests.yml @@ -62,7 +62,8 @@ parameters: type: boolean default: false - - name: androidPool + # Internal pools (dnceng) + - name: androidPoolInternal type: object default: name: MAUI @@ -70,14 +71,54 @@ parameters: demands: - Agent.OSArchitecture -equals ARM64 - - name: androidPoolLinux + - name: androidPoolLinuxInternal + type: object + default: + name: NetCore1ESPool-Internal + demands: + - ImageOverride -equals 1ESPT-Ubuntu22.04 + + - name: iosPoolInternal + type: object + default: + name: MAUI + vmImage: MAUI + + - name: windowsBuildPoolInternal + type: object + default: + name: NetCore1ESPool-Internal + demands: + - ImageOverride -equals 1es-windows-2022 + + - name: windowsPoolInternal + type: object + default: + name: NetCore1ESPool-Internal + demands: + - ImageOverride -equals 1es-windows-2022 + + - name: macosPoolInternal + type: object + default: + name: Azure Pipelines + vmImage: macOS-15 + + # Public pools (dnceng-public) + - name: androidPoolPublic + type: object + default: + name: MAUI + vmImage: MAUI + + - name: androidPoolLinuxPublic type: object default: name: MAUI-DNCENG demands: - ImageOverride -equals 1ESPT-Ubuntu22.04 - - name: iosPool + - name: iosPoolPublic type: object default: name: MAUI @@ -85,21 +126,21 @@ parameters: demands: - Agent.OSArchitecture -equals ARM64 - - name: windowsBuildPool + - name: windowsBuildPoolPublic type: object default: name: NetCore-Public demands: - ImageOverride -equals 1es-windows-2022-open - - name: windowsPool + - name: windowsPoolPublic type: object default: name: NetCore-Public demands: - ImageOverride -equals 1es-windows-2022-open - - name: macosPool + - name: macosPoolPublic type: object default: name: Azure Pipelines @@ -109,12 +150,21 @@ stages: - template: common/ui-tests.yml parameters: - androidPool: ${{ parameters.androidPool }} - androidLinuxPool: ${{ parameters.androidPoolLinux }} - iosPool: ${{ parameters.iosPool }} - windowsPool: ${{ parameters.windowsPool }} - windowsBuildPool: ${{ parameters.windowsBuildPool }} - macosPool: ${{ parameters.macosPool }} + # Select pools based on pipeline - internal vs public + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + androidPool: ${{ parameters.androidPoolInternal }} + androidLinuxPool: ${{ parameters.androidPoolLinuxInternal }} + iosPool: ${{ parameters.iosPoolInternal }} + windowsPool: ${{ parameters.windowsPoolInternal }} + windowsBuildPool: ${{ parameters.windowsBuildPoolInternal }} + macosPool: ${{ parameters.macosPoolInternal }} + ${{ else }}: + androidPool: ${{ parameters.androidPoolPublic }} + androidLinuxPool: ${{ parameters.androidPoolLinuxPublic }} + iosPool: ${{ parameters.iosPoolPublic }} + windowsPool: ${{ parameters.windowsPoolPublic }} + windowsBuildPool: ${{ parameters.windowsBuildPoolPublic }} + macosPool: ${{ parameters.macosPoolPublic }} # BuildNativeAOT is false by default, but true in devdiv environment BuildNativeAOT: ${{ or(parameters.BuildNativeAOT, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv'))) }} RunNativeAOT: ${{ parameters.RunNativeAOT }} diff --git a/eng/pipelines/ci.yml b/eng/pipelines/ci.yml index 939132f68ef1..fbeec182faec 100644 --- a/eng/pipelines/ci.yml +++ b/eng/pipelines/ci.yml @@ -94,6 +94,7 @@ parameters: - ImageOverride -equals 1es-windows-2022-open os: windows +# Typically X64 pools but XCode 26.2 isn't available yet for the Azure Pipelines X64 Pools - name: MacOSPool type: object default: @@ -101,21 +102,33 @@ parameters: vmImage: MAUI os: macOS label: macOS +# Switch back to this once XCode 26.2 is available on Azure Pipelines +# name: Azure Pipelines +# vmImage: $(HostedMacImage) +# os: macOS +# label: macOS # ARM64 macOS pool (Apple Silicon) - name: MacOSPoolArm64 type: object default: - name: Azure Pipelines - vmImage: macOS-15-arm64 + name: MAUI + vmImage: MAUI os: macOS label: macOS-arm64 +# Switch back to this once XCode 26.2 is available on Azure Pipelines +# name: Azure Pipelines +# vmImage: macOS-15-arm64 +# os: macOS +# label: macOS-arm64 # Condition for MacOSPool comparison lanes (non-ARM64) -# Runs on: (non-PR on main/net*.0/release/*/inflight/*) OR (PR targeting net*.0/release/*/inflight/*) +# Currently disabled - both pools use MAUI self-hosted since Xcode 26.2 isn't available on Azure Pipelines x64. +# Re-enable once Azure Pipelines has Xcode 26.2 on x64 pools. +# Original condition: or(and(ne(variables['Build.Reason'], 'PullRequest'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), and(startsWith(variables['Build.SourceBranch'], 'refs/heads/net'), endsWith(variables['Build.SourceBranch'], '.0')), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/inflight/'))), and(eq(variables['Build.Reason'], 'PullRequest'), or(and(startsWith(variables['System.PullRequest.TargetBranch'], 'net'), endsWith(variables['System.PullRequest.TargetBranch'], '.0')), startsWith(variables['System.PullRequest.TargetBranch'], 'release/'), startsWith(variables['System.PullRequest.TargetBranch'], 'inflight/')))) - name: macOSPoolLaneCondition type: string - default: or(and(ne(variables['Build.Reason'], 'PullRequest'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), and(startsWith(variables['Build.SourceBranch'], 'refs/heads/net'), endsWith(variables['Build.SourceBranch'], '.0')), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/inflight/'))), and(eq(variables['Build.Reason'], 'PullRequest'), or(and(startsWith(variables['System.PullRequest.TargetBranch'], 'net'), endsWith(variables['System.PullRequest.TargetBranch'], '.0')), startsWith(variables['System.PullRequest.TargetBranch'], 'release/'), startsWith(variables['System.PullRequest.TargetBranch'], 'inflight/')))) + default: false stages: diff --git a/eng/pipelines/common/provision.yml b/eng/pipelines/common/provision.yml index 4c82b903e4f9..0584e7f1e275 100644 --- a/eng/pipelines/common/provision.yml +++ b/eng/pipelines/common/provision.yml @@ -192,6 +192,17 @@ steps: continueOnError: true timeoutInMinutes: 30 + # Also install iOS 18.5 simulator for integration tests that require it + - script: | + echo "Installing iOS 18.5 simulator runtime for integration tests..." + sudo xcodebuild -downloadPlatform iOS -buildVersion 18.5 || { + echo "Warning: Failed to install iOS 18.5 simulator. Tests requiring this version may fail." + } + displayName: Install iOS 18.5 Simulator (for integration tests) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) + continueOnError: true + timeoutInMinutes: 30 + # Provision Additional Software - ${{ if or(eq(variables['System.TeamProject'], 'DevDiv'), ne(parameters.skipProvisionator, true)) }}: # Prepare macOS diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs index 7a565c955a5c..67d0fa430bae 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs @@ -1,4 +1,4 @@ -#if TEST_FAILS_ON_WINDOWS //related issues: https://github.com/dotnet/maui/issues/15994 +#if TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS //related issues: https://github.com/dotnet/maui/issues/33507, https://github.com/dotnet/maui/issues/15994 using NUnit.Framework; using UITest.Appium; using UITest.Core; diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18896.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18896.cs index 475420d26f16..65acc5141cd1 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18896.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18896.cs @@ -1,4 +1,4 @@ -#if TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS//Related issues : https://github.com/dotnet/maui/issues/18811, https://github.com/dotnet/maui/issues/15994 +#if TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS//Related issues : https://github.com/dotnet/maui/issues/33507, https://github.com/dotnet/maui/issues/18811, https://github.com/dotnet/maui/issues/15994 using NUnit.Framework; using UITest.Appium; using UITest.Core;