Merge branch 'microsoft:main' into joncamp/qnn_fixes

This commit is contained in:
Jon Campbell 2025-02-04 16:31:47 -08:00 committed by GitHub
commit 6035faf2ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 446 additions and 179 deletions

View file

@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"browserstack-sdk": {
"version": "1.16.13",
"commands": [
"browserstack-sdk"
],
"rollForward": false
}
}
}

View file

@ -0,0 +1,68 @@
using Newtonsoft.Json;
using NUnit.Framework.Interfaces;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Android;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android
{
public class BrowserStackTest
{
public AndroidDriver driver;
public BrowserStackTest()
{}
[SetUp]
public void Init()
{
var androidOptions = new AppiumOptions {
AutomationName = "UIAutomator2",
PlatformName = "Android",
};
driver = new AndroidDriver(new Uri("http://127.0.0.1:4723/wd/hub"), androidOptions);
}
/// <summary>
/// Passes the correct test status to BrowserStack and ensures the driver quits.
/// </summary>
[TearDown]
public void Dispose()
{
try
{
// According to
// https://www.browserstack.com/docs/app-automate/appium/set-up-tests/mark-tests-as-pass-fail
// BrowserStack doesn't know whether test assertions have passed or failed. Below handles
// passing the test status to BrowserStack along with any relevant information.
if (TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed)
{
String failureMessage = TestContext.CurrentContext.Result.Message;
String jsonToSendFailure =
String.Format("browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": " +
"{\"status\":\"failed\", \"reason\": {0}}}",
JsonConvert.ToString(failureMessage));
((IJavaScriptExecutor)driver).ExecuteScript(jsonToSendFailure);
}
else
{
((IJavaScriptExecutor)driver)
.ExecuteScript("browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": " +
"{\"status\":\"passed\", \"reason\": \"\"}}");
}
}
finally
{
// will run even if exception is thrown by previous block
((AndroidDriver)driver).Quit();
}
}
}
}

View file

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Appium.WebDriver" Version="5.0.0-rc.5" />
<PackageReference Include="BrowserStack.TestAdapter" Version="0.13.13" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="3.13.0" />
<PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,48 @@
# BrowserStack Android test
This project will run the Android MAUI tests on BrowserStack, which allows you to run automated tests on a variety of mobile devices.
## Context
Microsoft.ML.OnnxRuntime.Tests.MAUI uses DeviceRunners.VisualRunners to allow running the unit tests (found in Microsoft.ML.OnnxRuntime.Tests.Common) across multiple devices. DeviceRunners.VisualRunners provides a simple UI with a button that will run the unit tests and a panel with the unit test results.
In order to automate the process of running the unit tests across mobile devices, Appium is used for UI testing orchestration (it provides a way to interact with the UI), and BrowserStack automatically runs these Appium tests across different mobile devices.
This project does not include the capability to start an Appium server locally or attach to a local emulator or device.
## Build & run instructions
### Requirements
* A BrowserStack account with access to App Automate
* You can set BrowserStack credentials as environment variables as shown [here](https://www.browserstack.com/docs/app-automate/appium/getting-started/c-sharp/nunit/integrate-your-tests#CLI)
* ONNXRuntime NuGet package
1. You can either download the [stable NuGet package](https://www.nuget.org/packages/Microsoft.ML.OnnxRuntime) then follow the instructions from [NativeLibraryInclude.props file](../Microsoft.ML.OnnxRuntime.Tests.Common/NativeLibraryInclude.props) to use the downloaded .nupkg file
2. Or follow the [build instructions](https://onnxruntime.ai/docs/build/android.html) to build the Android package locally
* The dotnet workloads for maui and maui-android, which will not always automatically install correctly
1. `dotnet workload install maui`
2. `dotnet workload install maui-android`
* [Appium](https://appium.io/docs/en/latest/quickstart/) and the [UiAutomator2 driver](https://appium.io/docs/en/latest/quickstart/uiauto2-driver/)
### Run instructions
1. Build the Microsoft.ML.OnnxRuntime.Tests.MAUI project into a signed APK.
1. Run the following: `dotnet publish -c Release -f net8.0-android` in the Microsoft.ML.OnnxRuntime.Tests.MAUI directory.
2. Search for the APK files generated. They should be located in `bin\Release\net8.0-android\publish`.
3. If they're in a different location, edit the `browserstack.yml` file to target the path to the signed APK.
2. Ensure you've set the BrowserStack credentials as environment variables.
3. Run the following in the Microsoft.ML.OnnxRuntime.Tests.Android.BrowserStack directory: `dotnet test`
4. Navigate to the [BrowserStack App Automate dashboard](https://app-automate.browserstack.com/dashboard/v2/builds) to see your test running!
## Troubleshooting & Resources
### BrowserStack Resources
- [Configuration docs](https://www.browserstack.com/docs/app-automate/appium/sdk-params#test-context) for browserstack.yml
- [Configuration generator](https://www.browserstack.com/docs/app-automate/capabilities) for browserstack.yml
- [Integration guide](https://www.browserstack.com/docs/app-automate/appium/getting-started/c-sharp/nunit/integrate-your-tests#CLI)
### Troubleshooting
- Issues building the MAUI app:
- Make sure that the maui and maui-android workloads are installed correctly by running `dotnet workload list`
- If you believe the issues are workload related, you can also try running `dotnet workload repair` (this has personally never worked for me)
- Try running `dotnet clean`. However, this does not fully remove all the previous intermediaries. If you're still running into the errors, manually deleting the bin and obj folders can sometimes resolve them.
- After building the MAUI app, try installing on an emulator and clicking the "Run All" button to ensure that everything is working. (If you are missing the ONNXRuntime package, it will not show up as an error until you click "Run All".)
- Running the MAUI app from Visual Studio will not replicate running it through BrowserStack. Instead, use `adb install [path to signed apk]` to install the app then use the emulator to launch the app.
- Issues with the Android.BrowserStack test app: there is an Appium Doctor package on npm -- run `npm install @appium/doctor --location=global` then `appium-doctor --android` and follow the directed instructions. Some errors with Appium on Android will not appear until runtime.
- Connection refused by Appium server: this can happen if you already have an Appium server running locally. If you do, stop the Appium server then try `dotnet test` again.
- App is crashing on BrowserStack or it emits an error that it cannot run this APK file: make sure that you are passing in the correct signed APK from the publish folder.
- It appears that a test runs on CLI but a build is not launched on BrowserStack: this happens when the BrowserStack Test Adapter cannot find the browserstack.yml file (which has to be named "browserstack.yml" -- do not be tricked by BrowserStack's article on custom-named configuration files)

View file

@ -0,0 +1,123 @@
using OpenQA.Selenium.Appium;
using OpenQA.Selenium;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android
{
/// <summary>
/// This class contains a single test: RunAll, which interacts with the UI from
/// https://github.com/mattleibow/DeviceRunners/tree/main by clicking the "Run All" button and checking the number
/// of passed and failed tests.
///
/// It searches for elements on the page using Appium's WebDriver. These searches use the XPath attributes.
///
/// Launching the MAUI test app in Appium Inspector will allow you to see the exact XPath attributes for each
/// element.
/// </summary>
[TestFixture]
public class RunAllTest : BrowserStackTest
{
public AppiumElement FindAppiumElement(String xpathQuery, String text)
{
IReadOnlyCollection<AppiumElement> appiumElements = driver.FindElements(By.XPath(xpathQuery));
foreach (var element in appiumElements)
{
if (element.Text.Contains(text))
{
return element;
}
}
// was unable to find given element
throw new Exception(String.Format("Could not find {0}: {1} on the page.", xpathQuery, text));
}
public AppiumElement FindAppiumElementThenClick(String xpathQuery, String text)
{
AppiumElement appiumElement = FindAppiumElement(xpathQuery, text);
appiumElement.Click();
return appiumElement;
}
public (int, int) GetPassFailCount()
{
int numPassed = -1;
int numFailed = -1;
IReadOnlyCollection<AppiumElement> labelElements =
driver.FindElements(By.XPath("//android.widget.TextView"));
for (int i = 0; i < labelElements.Count; i++)
{
AppiumElement element = labelElements.ElementAt(i);
if (element.Text.Equals("✔"))
{
i++;
numPassed = int.Parse(labelElements.ElementAt(i).Text);
}
if (element.Text.Equals("⛔"))
{
i++;
numFailed = int.Parse(labelElements.ElementAt(i).Text);
break;
}
}
Assert.That(numPassed, Is.GreaterThanOrEqualTo(0), "Could not find number passed label.");
Assert.That(numFailed, Is.GreaterThanOrEqualTo(0), "Could not find number failed label.");
return (numPassed, numFailed);
}
[Test]
public async Task ClickRunAllTest()
{
// XAML for the main page:
// https://github.com/mattleibow/DeviceRunners/blob/cba7644e07b305ba64dc930b01c3eee55ef2b93d/src/DeviceRunners.VisualRunners.Maui/App/Pages/HomePage.xaml
AppiumElement runAllButton = FindAppiumElementThenClick("//android.widget.Button", "Run All");
while (!runAllButton.Enabled)
{
// waiting for unit tests to execute
await Task.Delay(500);
}
var (numPassed, numFailed) = GetPassFailCount();
if (numFailed == 0)
{
return;
}
// click into test results if tests have failed
FindAppiumElementThenClick("//android.widget.TextView", "⛔");
await Task.Delay(500);
// Brings you to the test assembly page
// XAML for test assembly page:
// https://github.com/mattleibow/DeviceRunners/blob/cba7644e07b305ba64dc930b01c3eee55ef2b93d/src/DeviceRunners.VisualRunners.Maui/App/Pages/TestAssemblyPage.xaml
FindAppiumElementThenClick("//android.widget.EditText", "All");
await Task.Delay(100);
FindAppiumElementThenClick("//android.widget.TextView", "Failed");
await Task.Delay(500);
StringBuilder sb = new StringBuilder();
sb.AppendLine("PASSED TESTS: " + numPassed + " | FAILED TESTS: " + numFailed);
IReadOnlyCollection<AppiumElement> textResults = driver.FindElements(By.XPath("//android.widget.TextView"));
foreach (var element in textResults)
{
sb.AppendLine(element.Text);
}
Assert.That(numFailed, Is.EqualTo(0), sb.ToString());
}
}
}

View file

@ -0,0 +1,13 @@
app: ..\Microsoft.ML.OnnxRuntime.Tests.MAUI\bin\Release\net8.0-android\publish\ORT.CSharp.Tests.MAUI-Signed.apk
platforms:
- platformName: android
deviceName: Samsung Galaxy S22 Ultra
platformVersion: 12.0
browserstackLocal: true
buildName: ORT android test
buildIdentifier: ${BUILD_NUMBER}
projectName: ORT-UITests
debug: true
networkLogs: false
testContextOptions:
skipSessionStatus: true

View file

@ -1,125 +1,139 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OnnxRuntimeRoot>$(ProjectDir)..\..\..</OnnxRuntimeRoot>
</PropertyGroup>
<PropertyGroup>
<OnnxRuntimeRoot>$(ProjectDir)..\..\..</OnnxRuntimeRoot>
</PropertyGroup>
<Import Project="../Microsoft.ML.OnnxRuntime.Tests.Common/NativeLibraryInclude.props" />
<Import Project="../Microsoft.ML.OnnxRuntime.Tests.Common/NativeLibraryInclude.props" />
<!-- General app properties -->
<PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<!-- General app properties -->
<PropertyGroup>
<!-- TODO: Currently running into build issues with net8.0-ios and net8.0-maccatalyst that is
blocking packaging pipelines.
(Empty ResolveFrameworkReference.RuntimePackPath for Microsoft.NETCore.App)
<!-- Note for MacCatalyst:
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
Disabling those targets until the issues are resolved. -->
<!-- <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks> -->
<OutputType>Exe</OutputType>
<RootNamespace>Microsoft.ML.OnnxRuntime.Tests.MAUI</RootNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<!-- some of the helper packages don't have strong named assemblies. -->
<NoWarn>8002</NoWarn>
<TargetFrameworks>net8.0-android</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<!-- These are copied from the sample. TBD what we really need. -->
<DefineConstants Condition="'$(CI)' != 'true'">$(DefineConstants);INCLUDE_FAILING_TESTS</DefineConstants>
<DefineConstants Condition="'$(TestingMode)' == 'NonInteractiveVisual'">$(DefineConstants);MODE_NON_INTERACTIVE_VISUAL</DefineConstants>
<DefineConstants Condition="'$(TestingMode)' == 'XHarness'">$(DefineConstants);MODE_XHARNESS</DefineConstants>
<!-- Note for MacCatalyst:
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
<!-- Display name -->
<ApplicationTitle>Microsoft.ML.OnnxRuntime.Tests.MAUI</ApplicationTitle>
<OutputType>Exe</OutputType>
<RootNamespace>Microsoft.ML.OnnxRuntime.Tests.MAUI</RootNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<!-- some of the helper packages don't have strong named assemblies. -->
<NoWarn>8002</NoWarn>
<!-- App Identifier. MUST be short or you get a misleading error about not being able to deploy the app -->
<ApplicationId>ORT.CSharp.Tests.MAUI</ApplicationId>
<!-- These are copied from the sample. TBD what we really need. -->
<DefineConstants Condition="'$(CI)' != 'true'">$(DefineConstants);INCLUDE_FAILING_TESTS</DefineConstants>
<DefineConstants Condition="'$(TestingMode)' == 'NonInteractiveVisual'">$(DefineConstants);MODE_NON_INTERACTIVE_VISUAL</DefineConstants>
<DefineConstants Condition="'$(TestingMode)' == 'XHarness'">$(DefineConstants);MODE_XHARNESS</DefineConstants>
<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<!-- Display name -->
<ApplicationTitle>Microsoft.ML.OnnxRuntime.Tests.MAUI</ApplicationTitle>
<SupportedOSPlatformVersion Condition="'$(IsIOSTarget)' == 'true'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="'$(IsMacCatalystTarget)' == 'true'">13.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="'$(IsAndroidTarget)' == 'true'">30.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="'$(IsWindowsTarget)' == 'true'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="'$(IsWindowsTarget)' == 'true'">10.0.17763.0</TargetPlatformMinVersion>
<!-- App Identifier. MUST be short or you get a misleading error about not being able to deploy the app -->
<ApplicationId>ORT.CSharp.Tests.MAUI</ApplicationId>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\OnnxRuntime.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<SupportedOSPlatformVersion Condition="'$(IsIOSTarget)' == 'true'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="'$(IsMacCatalystTarget)' == 'true'">13.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="'$(IsAndroidTarget)' == 'true'">30.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="'$(IsWindowsTarget)' == 'true'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="'$(IsWindowsTarget)' == 'true'">10.0.17763.0</TargetPlatformMinVersion>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\OnnxRuntime.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<!-- NOTE: The xUnit framework doesn't pickup the tests defined within the referenced
Microsoft.ML.OnnxRuntime.Tests.Common project -->
<ItemGroup>
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\InferenceTest.cs">
<Link>InferenceTest.cs</Link>
</Compile>
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\OrtIoBindingAllocationTest.cs">
<Link>OrtIoBindingAllocationTest.cs</Link>
</Compile>
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\Tensors\TensorTests.cs">
<Link>TensorTests.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.ML.OnnxRuntime\Microsoft.ML.OnnxRuntime.csproj" name="Microsoft.ML.OnnxRuntime" />
<ProjectReference Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\Microsoft.ML.OnnxRuntime.Tests.Common.csproj" name="Microsoft.ML.OnnxRuntime.Tests.Common" />
<ProjectReference Include="..\Microsoft.ML.OnnxRuntime.Tests.Devices\Microsoft.ML.OnnxRuntime.Tests.Devices.csproj" name="Microsoft.ML.OnnxRuntime.Tests.Devices" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DeviceRunners.VisualRunners.Maui" Version="0.1.0-preview.2" />
<PackageReference Include="DeviceRunners.VisualRunners.Xunit" Version="0.1.0-preview.2" />
<PackageReference Include="DeviceRunners.XHarness.Maui" Version="0.1.0-preview.2" />
<PackageReference Include="DeviceRunners.XHarness.Xunit" Version="0.1.0-preview.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="Microsoft.DotNet.XHarness.TestRunners.Xunit" Version="9.0.0-prerelease.24374.1" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.70" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.70" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.utility" Version="2.9.0" />
</ItemGroup>
<ItemGroup Condition="$(IsIOSTarget)=='true' OR $(IsMacCatalystTarget)=='true'">
<!-- need the dummy ORT Extensions package to resolve the RegisterCustomOps symbol. -->
<PackageReference Include="Microsoft.ML.OnnxRuntime.Extensions.Dummy" Version="0.12.0" />
</ItemGroup>
<Target Name="RemoveVisualStudioTestRunner" BeforeTargets="_ComputeAppxPackagePayload">
<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
<_VisualStudioTestRunnerFiles Include="@(PackagingOutputs)" Condition="$([System.String]::Copy('%(PackagingOutputs.FullPath)').Contains('xunit.runner.visualstudio'))" />
<PackagingOutputs Remove="@(_VisualStudioTestRunnerFiles)" />
</ItemGroup>
</Target>
<!-- NOTE: The xUnit framework doesn't pickup the tests defined within the referenced
Microsoft.ML.OnnxRuntime.Tests.Common project -->
<ItemGroup>
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\InferenceTest.cs">
<Link>InferenceTest.cs</Link>
</Compile>
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\OrtIoBindingAllocationTest.cs">
<Link>OrtIoBindingAllocationTest.cs</Link>
</Compile>
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\Tensors\TensorTests.cs">
<Link>TensorTests.cs</Link>
</Compile>
</ItemGroup>
<Target Name="CleanPublishFolder" AfterTargets="Clean">
<RemoveDir Directories="$(PublishDir)" />
</Target>
<ItemGroup>
<ProjectReference
Include="..\..\src\Microsoft.ML.OnnxRuntime\Microsoft.ML.OnnxRuntime.csproj"
name="Microsoft.ML.OnnxRuntime" />
<ProjectReference
Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\Microsoft.ML.OnnxRuntime.Tests.Common.csproj"
name="Microsoft.ML.OnnxRuntime.Tests.Common" />
<ProjectReference
Include="..\Microsoft.ML.OnnxRuntime.Tests.Devices\Microsoft.ML.OnnxRuntime.Tests.Devices.csproj"
name="Microsoft.ML.OnnxRuntime.Tests.Devices" />
</ItemGroup>
<PropertyGroup Condition="'$(IsAndroidTarget)' !='true'">
<GenerateProgramFile>false</GenerateProgramFile>
<DefaultLanguage>en</DefaultLanguage>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DeviceRunners.VisualRunners.Maui" Version="0.1.0-preview.2" />
<PackageReference Include="DeviceRunners.VisualRunners.Xunit" Version="0.1.0-preview.2" />
<PackageReference Include="DeviceRunners.XHarness.Maui" Version="0.1.0-preview.2" />
<PackageReference Include="DeviceRunners.XHarness.Xunit" Version="0.1.0-preview.2" />
<PackageReference Include="Microsoft.DotNet.XHarness.TestRunners.Xunit" Version="9.0.0-prerelease.24374.1" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.70" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.70" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.utility" Version="2.9.0" />
</ItemGroup>
<PropertyGroup Condition="'$(IsAndroidTarget)' == 'true'">
<AndroidPackageFormat>apk</AndroidPackageFormat>
</PropertyGroup>
<ItemGroup Condition="$(IsIOSTarget)=='true' OR $(IsMacCatalystTarget)=='true'">
<!-- need the dummy ORT Extensions package to resolve the RegisterCustomOps symbol. -->
<PackageReference Include="Microsoft.ML.OnnxRuntime.Extensions.Dummy" Version="0.12.0" />
</ItemGroup>
<Target Name="RemoveVisualStudioTestRunner" BeforeTargets="_ComputeAppxPackagePayload">
<ItemGroup>
<_VisualStudioTestRunnerFiles
Include="@(PackagingOutputs)"
Condition="$([System.String]::Copy('%(PackagingOutputs.FullPath)').Contains('xunit.runner.visualstudio'))" />
<PackagingOutputs Remove="@(_VisualStudioTestRunnerFiles)" />
</ItemGroup>
</Target>
</Project>

View file

@ -1401,6 +1401,15 @@ std::unique_ptr<std::set<BrokenTest>> GetBrokenTests(const std::string& provider
"output=Y:expected 1 (3f800000), got 4 (40800000), diff: 3, tol=0.002 idx=24. 13 of 49 differ. CPU test passed."});
broken_tests->insert({"convtranspose_group_2", "Segmentation fault (core dumped). CPU test passed."});
broken_tests->insert({"convtranspose_group_2_image_3", "Segmentation fault (core dumped). CPU test passed."});
// Fails with QNN 2.31 on Windows x64 for CPU
broken_tests->insert({"gelu_tanh_2", "y:expected -0.0131778 (bc57e7d5), got -0.0136333 (bc5f5e38), diff: 0.000455472, tol=2.31778e-05."});
broken_tests->insert({"convtranspose_pad", "Access violation 0xc000005 from call graphAddNode."});
broken_tests->insert({"convtranspose_pads", "Access violation 0xc000005 from call graphAddNode."});
broken_tests->insert({"convtranspose_output_shape", "Access violation 0xc000005 from call graphAddNode."});
broken_tests->insert({"convtranspose_kernel_shape", "Access violation 0xc000005 from call graphAddNode."});
broken_tests->insert({"convtranspose_1d", "Access violation 0xc000005 from call graphAddNode."});
broken_tests->insert({"convtranspose", "Access violation 0xc000005 from call graphAddNode."});
broken_tests->insert({"averagepool_2d_ceil", "result differs. expected 13.5 (41580000), got 0 (0)"});
}
#ifdef DISABLE_CONTRIB_OPS

View file

@ -497,7 +497,9 @@ TEST_F(QnnCPUBackendTests, Convf32_AutoPadLower) {
}
// Tests ConvTranspose's auto_pad value "SAME_LOWER" (compares to CPU EP).
TEST_F(QnnCPUBackendTests, ConvTransposef32_AutoPadLower) {
// 2.31 Exception from qnn_interface.graphAddNode
// unknown file: error: SEH exception with code 0xc0000005 thrown in the test body
TEST_F(QnnCPUBackendTests, DISABLED_ConvTransposef32_AutoPadLower) {
RunCPUConvOpTest("ConvTranspose",
TestInputDef<float>({1, 1, 3, 3}, false, -3.0f, 3.0f), // Random dynamic input
TestInputDef<float>({1, 2, 2, 2}, false, -1.0f, 1.0f), // Random dynamic weights
@ -638,7 +640,9 @@ TEST_F(QnnCPUBackendTests, ConvTranspose1Df32_StaticWeights_DefaultBias) {
}
// Test 1D ConvTranspose with dynamic weights (implemented in QNN EP as 2D convolution with height of 1).
TEST_F(QnnCPUBackendTests, ConvTranspose1Df32_DynamicWeights_DefaultBias) {
// 2.31 Exception from qnn_interface.graphAddNode
// unknown file: error: SEH exception with code 0xc0000005 thrown in the test body
TEST_F(QnnCPUBackendTests, DISABLED_ConvTranspose1Df32_DynamicWeights_DefaultBias) {
std::vector<float> input_data = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
RunCPUConvOpTest("ConvTranspose",
TestInputDef<float>({1, 2, 4}, false, input_data), // Dynamic input
@ -1142,11 +1146,7 @@ TEST_F(QnnHTPBackendTests, Conv_PerChannel_UnsupportedAxis) {
// QnnDsp <I> QnnGraph_finalize done. status 0x3ea
// onnxruntime::qnn::QnnModel::FinalizeGraphs] Failed to finalize QNN graph.
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, Conv3D_U8S8S32_PerChannel) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_Conv3D_U8S8S32_PerChannel) {
#endif
std::vector<int64_t> input_shape = {1, 2, 4, 4, 4};
std::vector<int64_t> weight_shape = {3, 2, 2, 2, 2};
std::vector<int64_t> bias_shape = {3};
@ -1212,11 +1212,7 @@ TEST_F(QnnHTPBackendTests, ConvDepthwiseU8S8S32_PerChannel) {
// QnnDsp <I> QnnGraph_finalize done. status 0x3ea
// onnxruntime::qnn::QnnModel::FinalizeGraphs] Failed to finalize QNN graph.
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, Conv3D_U8S8S32_PerChannel2) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_Conv3D_U8S8S32_PerChannel2) {
#endif
std::vector<int64_t> input_shape = {1, 2, 4, 4, 4};
std::vector<int64_t> weight_shape = {2, 1, 2, 2, 2};
std::vector<int64_t> bias_shape = {2};
@ -1302,11 +1298,7 @@ TEST_F(QnnHTPBackendTests, ConvTranspose_PerChannel_UnsupportedAxis) {
// ConvTranspose3D per-channel
// Disable it for 2.21 since it failed, re-enabled it for 2.22
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, ConvTranspose3D_U8S8S32_PerChannel) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_ConvTranspose3D_U8S8S32_PerChannel) {
#endif
std::vector<int64_t> input_shape = {1, 2, 4, 4, 4};
std::vector<int64_t> weight_shape = {2, 3, 2, 2, 2};
std::vector<int64_t> bias_shape = {3};
@ -1371,11 +1363,7 @@ TEST_F(QnnHTPBackendTests, ConvU16S8S32_PerChannel) {
// QnnDsp <I> QnnGraph_finalize done. status 0x3ea
// onnxruntime::qnn::QnnModel::FinalizeGraphs] Failed to finalize QNN graph.
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, Conv3D_U16S8S32_PerChannel) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_Conv3D_U16S8S32_PerChannel) {
#endif
std::vector<int64_t> input_shape = {1, 2, 4, 4, 4};
std::vector<int64_t> weight_shape = {3, 2, 2, 2, 2};
std::vector<int64_t> bias_shape = {3};
@ -1432,11 +1420,7 @@ TEST_F(QnnHTPBackendTests, ConvTransposeU16S8S32_PerChannel) {
// Disable it for 2.21, re-enable it for 2.22
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, ConvTranspose3D_U16S8S32_PerChannel) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_ConvTranspose3D_U16S8S32_PerChannel) {
#endif
std::vector<int64_t> input_shape = {1, 2, 4, 4, 4};
std::vector<int64_t> weight_shape = {2, 3, 2, 2, 2};
std::vector<int64_t> bias_shape = {3};
@ -1502,11 +1486,7 @@ TEST_F(QnnHTPBackendTests, ConvDepthwiseU16S8S32_PerChannel) {
// QnnDsp <I> QnnGraph_finalize done. status 0x3ea
// onnxruntime::qnn::QnnModel::FinalizeGraphs] Failed to finalize QNN graph.
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, Conv3D_U16S8S32_PerChannel2) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_Conv3D_U16S8S32_PerChannel2) {
#endif
std::vector<int64_t> input_shape = {1, 2, 4, 4, 4};
std::vector<int64_t> weight_shape = {2, 1, 2, 2, 2};
std::vector<int64_t> bias_shape = {2};
@ -1860,11 +1840,7 @@ TEST_F(QnnHTPBackendTests, ConvTransposeU8U8S32_DynamicWeight_NoBias) {
// Exception thrown at 0x00007FFF9E0128B0 (QnnHtpPrepare.dll) in onnxruntime_test_all.exe:
// 0xC0000005: Access violation reading location 0x7079745F656C706D.
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, ConvTranspose3D_U8U8S32_DynamicWeight_NoBias) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_ConvTranspose3D_U8U8S32_DynamicWeight_NoBias) {
#endif
RunHTPConvOpTest<uint8_t, uint8_t>("ConvTranspose",
TestInputDef<float>({1, 3, 32, 32, 32}, false, -10.0f, 10.0f), // Input
TestInputDef<float>({3, 1, 4, 4, 4}, false, -10.0f, 10.0f), // Weights

View file

@ -151,11 +151,7 @@ TEST_F(QnnHTPBackendTests, GatherOp_IndicesDynamicInt32_Axis0) {
//
// Static int32 indices with axis = 1
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, GatherOp_IndicesStaticInt32_Axis1) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_GatherOp_IndicesStaticInt32_Axis1) {
#endif
RunQDQGatherOpTest<uint8_t, int32_t>(TestInputDef<float>({3, 3}, false, {1.0f, 1.2f, 1.9f, 2.3f, 3.4f, 3.9f, 4.5f, 5.7f, 5.9f}),
TestInputDef<int32_t>({1, 2}, true, {0, 2}),
{utils::MakeAttribute("axis", static_cast<int64_t>(1))},

View file

@ -339,10 +339,11 @@ TEST_F(QnnHTPBackendTests, Gemm_Broadcast_Bias_DynamicA_StaticB_StaticC) {
// QNN QDQ val: 0 (err 120.73912048339844)
// CPU QDQ val: 120.73889923095703 (err 0.00022125244140625)
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, Gemm_Dynamic_A_Static_B_Dynamic_Bias_U16) {
#else
#ifdef __linux__
// Failed on Linux with 2.31
TEST_F(QnnHTPBackendTests, DISABLED_Gemm_Dynamic_A_Static_B_Dynamic_Bias_U16) {
#else
TEST_F(QnnHTPBackendTests, Gemm_Dynamic_A_Static_B_Dynamic_Bias_U16) {
#endif
std::vector<float> input_a_data = GetFloatDataInRange(-10.0f, 10.0f, 6);
std::vector<float> input_b_data = GetFloatDataInRange(-5.0f, 5.0f, 24);
@ -377,11 +378,7 @@ TEST_F(QnnHTPBackendTests, Gemm_Dynamic_A_Static_B_Dynamic_Bias_U16Act_U8Weight)
// QNN QDQ val: 77.012794494628906 (err 43.726325988769531)
// CPU QDQ val: 119.85115814208984 (err 0.88796234130859375)
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, Gemm_Dynamic_A_B_Static_Bias) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_Gemm_Dynamic_A_B_Static_Bias) {
#endif
std::vector<float> input_a_data = GetFloatDataInRange(-10.0f, 10.0f, 6);
std::vector<float> input_b_data = GetFloatDataInRange(-5.0f, 5.0f, 24);
std::vector<float> input_c_data = GetFloatDataInRange(-1.0f, 1.0f, 4);

View file

@ -338,11 +338,7 @@ TEST_F(QnnCPUBackendTests, ReduceL2Opset13) {
//
// Failed QNN Opvalidation because of 5D input. It runs OK if bypass the op validation
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, ReduceSumOpset11_5D_FP16) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_ReduceSumOpset11_5D_FP16) {
#endif
float fp32_abs_err = 3e-2f;
bool enable_fp16 = true;
RunReduceTest<float>("ReduceSum",

View file

@ -670,11 +670,7 @@ TEST_F(QnnHTPBackendTests, UnaryOp_Ceil) {
// CPU EP qdq model output: [-12.0, -6.99, -1.99, 3.0, 8.0, 11.99]
// QNN EP qdq model output: [-11.0 (WRONG), -7.0, -2.0, 2.99, 8.0, 11.99]
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, UnaryOp_Ceil_U16) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_UnaryOp_Ceil_U16) {
#endif
const std::vector<float> input_data = GetFloatDataInRange(-12.0f, 12.0f, 6);
RunQDQOpTest<uint16_t>("Ceil",
{TestInputDef<float>({1, 2, 3}, false, input_data)},
@ -1081,11 +1077,7 @@ TEST_F(QnnHTPBackendTests, GridSample_U16_AlignCorners) {
// QNN QDQ val: 3.2922921180725098 (err 0.069758892059326172)
// CPU QDQ val: 3.3850328922271729 (err 0.022981882095336914)
// Issue fixed in 2.30
#if (QNN_API_VERSION_MAJOR == 2) && (QNN_API_VERSION_MINOR >= 23)
TEST_F(QnnHTPBackendTests, GridSample_BorderPadding) {
#else
TEST_F(QnnHTPBackendTests, DISABLED_GridSample_BorderPadding) {
#endif
RunQDQOpTest<uint8_t>("GridSample",
{TestInputDef<float>({1, 1, 3, 2}, false, -10.0f, 10.0f),
TestInputDef<float>({1, 2, 4, 2}, false, -10.0f, 10.0f)},

View file

@ -32,7 +32,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
jobs:
- job: Build_QNN_EP

View file

@ -62,7 +62,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK Version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
resources:
repositories:

View file

@ -33,7 +33,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
jobs:
- job: Build_QNN_EP

View file

@ -59,7 +59,7 @@ parameters:
- name: qnn_sdk_version
type: string
displayName: 'QNN SDK version. Only for QNN packages.'
default: 2.30.0.250109
default: 2.31.0.250130
trigger: none

View file

@ -2,7 +2,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK Version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
- name: build_config
displayName: Build Configuration

View file

@ -59,7 +59,7 @@ parameters:
- name: qnn_sdk_version
type: string
displayName: 'QNN SDK version. Only for QNN packages.'
default: 2.30.0.250109
default: 2.31.0.250130
stages:
- ${{ if eq(parameters.enable_windows_cpu, true) }}:

View file

@ -17,7 +17,7 @@ parameters:
- name: QnnSDKVersion
displayName: QNN SDK Version
type: string
default: '2.30.0.250109'
default: '2.31.0.250130'
jobs:
- job: Final_AAR_Testing_Android

View file

@ -51,7 +51,7 @@ parameters:
- name: QnnSDKVersion
displayName: QNN SDK Version
type: string
default: '2.30.0.250109'
default: '2.31.0.250130'
jobs:
- job: Android_Java_API_AAR_Packaging_${{ parameters.job_name_suffix }}

View file

@ -51,7 +51,7 @@ parameters:
- name: QnnSDKVersion
displayName: QNN SDK Version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
stages:
- template: linux-cpu-packaging-pipeline.yml

View file

@ -1,7 +1,7 @@
parameters:
- name: QnnSDKVersion
type: string
default: '2.30.0.250109'
default: '2.31.0.250130'
steps:
- script: |

View file

@ -1,7 +1,7 @@
parameters:
- name: QnnSDKVersion
type: string
default: '2.30.0.250109'
default: '2.31.0.250130'
steps:
- powershell: |

View file

@ -26,7 +26,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
jobs:
- job: Linux_py_qnn_Wheels_x64

View file

@ -7,7 +7,7 @@ parameters:
- name: QNN_SDK
displayName: QNN SDK Version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
- name: ENV_SETUP_SCRIPT
type: string

View file

@ -7,7 +7,7 @@ parameters:
- name: QNN_SDK
displayName: QNN SDK Version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
- name: ENV_SETUP_SCRIPT
type: string

View file

@ -7,7 +7,7 @@ parameters:
- name: QNN_SDK
displayName: QNN SDK Version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
- name: ENV_SETUP_SCRIPT
type: string

View file

@ -1,5 +1,5 @@
parameters:
QnnSdk: '2.30.0.250109'
QnnSdk: '2.31.0.250130'
build_config: 'RelWithDebInfo'
IsReleaseBuild: false
DoEsrp: false

View file

@ -33,7 +33,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
jobs:
- job: 'BUILD_QNN_EP'

View file

@ -33,7 +33,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK version
type: string
default: 2.30.0.250109
default: 2.31.0.250130
jobs:
- job: 'BUILD_QNN_EP'
@ -102,11 +102,11 @@ jobs:
displayName: 'Run unit tests'
- script: |
.\$(BuildConfig)\onnx_test_runner -j 1 -v -e qnn -i "backend_path|$(QnnSDKRootDir)\lib\x86_64-windows-msvc\QnnCpu.dll" $(Build.SourcesDirectory)\cmake\external\onnx\onnx\backend\test\data\node
.\$(BuildConfig)\onnx_test_runner -j 1 -e qnn -i "backend_path|$(QnnSDKRootDir)\lib\x86_64-windows-msvc\QnnCpu.dll" $(Build.SourcesDirectory)\cmake\external\onnx\onnx\backend\test\data\node
workingDirectory: '$(Build.BinariesDirectory)\$(BuildConfig)'
displayName: 'Run ONNX Tests'
- script: |
.\$(BuildConfig)\onnx_test_runner -j 1 -v -e qnn -i "backend_path|$(QnnSDKRootDir)\lib\x86_64-windows-msvc\QnnCpu.dll" C:\data\float32_models
.\$(BuildConfig)\onnx_test_runner -j 1 -e qnn -i "backend_path|$(QnnSDKRootDir)\lib\x86_64-windows-msvc\QnnCpu.dll" C:\data\float32_models
workingDirectory: '$(Build.BinariesDirectory)\$(BuildConfig)'
displayName: 'Run float32 model tests'