Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e6abde0
Reapply "[Mobile] Add BrowserStack Android MAUI Test (#23383)" (#23474)
carzh Jan 28, 2025
0dd42e9
maui csproj that builds into apk successfully
carzh Jan 29, 2025
4011a10
attempt to fix nuget pipeline failure
carzh Jan 29, 2025
0783bb1
target only ort for building c# bindings
carzh Jan 30, 2025
5a5fe4b
removed test projects from sln and updated pipeline yml
carzh Jan 31, 2025
70e3a23
format
carzh Jan 31, 2025
773cbb6
Revert "format"
carzh Jan 31, 2025
657c60d
format again..
carzh Jan 31, 2025
7a51dd5
fixed format again
carzh Jan 31, 2025
ec57836
Merge remote-tracking branch 'msft/main' into carzh/browserstack-andr…
carzh Jan 31, 2025
573e284
removed modifications from sln and commented out the ios and maccatyl…
carzh Feb 3, 2025
15d86f5
added more detailed comment
carzh Feb 4, 2025
2c17720
added test_android yml + added it to nuget pipeline
carzh Feb 4, 2025
fba5416
fixed indent
carzh Feb 4, 2025
a6c9823
Merge remote-tracking branch 'msft/main' into carzh/nuget-test-androi…
carzh Feb 6, 2025
1815b96
fixed curly bracket / ascii processing issue
carzh Feb 7, 2025
e6cd1e8
disable aot compilation for inference sample to see if that resolves …
carzh Feb 7, 2025
d15c053
Merge remote-tracking branch 'msft/main' into carzh/nuget-test-androi…
carzh Feb 21, 2025
a77f4f1
added updated asserts
carzh Feb 21, 2025
7e69c93
made InferenceTest diffs more clear hopefully + removed double feedba…
carzh Feb 22, 2025
24f5b3f
applied formatting suggestions + added second assert method that will…
carzh Feb 25, 2025
90411e9
updated the assertion check for the expected exception message. Added…
carzh Feb 25, 2025
f2e7854
added comment about ep checks, fixed typos, removed aotcompilation
carzh Mar 10, 2025
af28ea3
removed references to the preprocessor directives in the feedback mes…
carzh Mar 10, 2025
a5c7182
added coreml test back in and updated feedback message
carzh Mar 14, 2025
d222d90
updated comment explaining appending ep tests to session options
carzh Mar 19, 2025
26b965e
amended comment
carzh Mar 19, 2025
c70ac90
amended comment
carzh Mar 19, 2025
e7afd4b
Update csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTes…
carzh Mar 20, 2025
1dbd060
Merge remote-tracking branch 'msft/main' into carzh/nuget-test-androi…
carzh Mar 21, 2025
644d01c
resolve '
carzh Mar 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@

<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\InferenceTest.cs" />
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\EqualityComparers.cs" />
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\AssertUtils.cs" />
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\OnnxMl.cs" />
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.Common\OnnxData.cs" />
<Compile Include="..\Microsoft.ML.OnnxRuntime.Tests.NetCoreApp\InferenceTest.netcore.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public void Dispose()
{
String failureMessage = TestContext.CurrentContext.Result.Message;
String jsonToSendFailure =
String.Format("browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": " +
"{\"status\":\"failed\", \"reason\": {0}}}",
String.Format("browserstack_executor: {{\"action\": \"setSessionStatus\", \"arguments\": " +
"{{\"status\":\"failed\", \"reason\": {0}}}}}",
JsonConvert.ToString(failureMessage));

((IJavaScriptExecutor)driver).ExecuteScript(jsonToSendFailure);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public async Task ClickRunAllTest()
await Task.Delay(500);
}

var (numPassed, numFailed) = GetPassFailCount();
(int numPassed, int numFailed) = GetPassFailCount();

if (numFailed == 0)
{
Expand Down
81 changes: 81 additions & 0 deletions csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssertUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Microsoft.ML.OnnxRuntime.Tests
{
internal static class AssertUtils
{

/// <summary>
/// Check if the action throws the expected exception. If it doesn't, the method passes. If it does, check for
/// the exception type and the expected exception message. More detailed Assert method to be used for unit tests
/// written with XUnit.
/// </summary>
/// <typeparam name="T">Type of exception expected to be thrown.</typeparam>
/// <param name="action">Action to be executed or tested.</param>
/// <param name="feedbackMessage">Feedback message if an unexpected exception happens.</param>
/// <param name="expectedExceptionMessage">Expected exception message. If null, the exception message is not
// checked.</param>
public static void IfThrowsCheckException<T>(Action action, string feedbackMessage, string expectedExceptionMessage = null) where T : Exception
{
try
{
action();
}
catch (T ex)
{
if (expectedExceptionMessage == null)
{
return;
}
else
{
Assert.True(ex.Message.Contains(expectedExceptionMessage),
$"{feedbackMessage}\nExpected exception message to contain '{expectedExceptionMessage}', but got '{ex.Message}'");
}
}
catch (Exception ex)
{
Assert.Fail($"{feedbackMessage}\nExpected {typeof(T).Name} but got {ex.GetType().Name}. ");
}
}


/// <summary>
/// Check if the action throws the expected exception. If it doesn't, the method fails with the feedbackMessage.
/// If it does, check for the exception type and the expected exception message. More detailed Assert method to be
/// used for unit tests written with XUnit.
/// </summary>
/// <typeparam name="T">Type of exception expected to be thrown.</typeparam>
/// <param name="action">Action to be executed or tested. It is expected that the action will throw.</param>
/// <param name="feedbackMessage">Feedback message if an unexpected exception happens.</param>
/// <param name="expectedExceptionMessage">Expected exception message. If null, the exception message is not
// checked.</param>
public static void AssertThrowsCheckException<T>(Action action, string feedbackMessage, string expectedExceptionMessage = null) where T : Exception
{
try
{
action();
Assert.Fail($"{feedbackMessage}\nExpected {typeof(T).Name} but no exception was thrown.");
}
catch (T ex)
{
if (expectedExceptionMessage == null)
{
return;
}
else
{
Assert.True(ex.Message.Contains(expectedExceptionMessage),
$"{feedbackMessage}\nExpected exception message to contain '{expectedExceptionMessage}', but got '{ex.Message}'");
}
}
catch (Exception ex)
{
Assert.Fail($"{feedbackMessage}\nExpected {typeof(T).Name} but got {ex.GetType().Name}. ");
}
}
}
}
72 changes: 42 additions & 30 deletions csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,35 @@ public void TestSessionOptions()
opt.GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_EXTENDED;
Assert.Equal(GraphOptimizationLevel.ORT_ENABLE_EXTENDED, opt.GraphOptimizationLevel);

Assert.Throws<OnnxRuntimeException>(() => { opt.GraphOptimizationLevel = (GraphOptimizationLevel)10; });
AssertUtils.AssertThrowsCheckException<OnnxRuntimeException>(
() => { opt.GraphOptimizationLevel = (GraphOptimizationLevel)10; },
"Set an invalid Graph Optimization Level.");

opt.AddSessionConfigEntry("key", "value");

var ex = Assert.Throws<OnnxRuntimeException>(() => { opt.AddSessionConfigEntry("", "invalid key"); });
Assert.Contains("[ErrorCode:InvalidArgument] Config key is empty", ex.Message);
AssertUtils.AssertThrowsCheckException<OnnxRuntimeException>(
() => { opt.AddSessionConfigEntry("", "invalid key"); },
"Added an invalid config entry.",
"[ErrorCode:InvalidArgument] Config key is empty");

// SessionOptions.RegisterOrtExtensions can be manually tested by referencing the
// Microsoft.ML.OnnxRuntime.Extensions nuget package. After that is done, this should not throw.
ex = Assert.Throws<OnnxRuntimeException>(() => { opt.RegisterOrtExtensions(); });
Assert.Contains("Microsoft.ML.OnnxRuntime.Extensions NuGet package must be referenced", ex.Message);

AssertUtils.AssertThrowsCheckException<OnnxRuntimeException>(
() => { opt.RegisterOrtExtensions(); },
"RegisterOrtExtensions should throw if the Extensions package is not referenced",
"Microsoft.ML.OnnxRuntime.Extensions NuGet package must be referenced");

// The below tests what happens when various execution providers are added
// to the session options.

// We can only check what EPs the package was built with for the
// Microsoft.ML.OnnxRuntime.Managed package because the managed package defines
// the C# preprocessor symbols (such as USE_CUDA) for the EPs that it was built with.

// The Microsoft.ML.OnnxRuntime package will use the appropriate platform bindings
// (ie the native Android bindings) where the C# preprocessor symbols
// identifying the EPs included in the build may not be available, so we use
// IfThrowsCheckException instead of using ifdefs.
#if USE_CUDA
opt.AppendExecutionProvider_CUDA(0);
#endif
Expand Down Expand Up @@ -157,30 +174,25 @@ public void TestSessionOptions()
#if USE_TENSORRT
opt.AppendExecutionProvider_Tensorrt(0);
#endif
#if USE_XNNPACK
opt.AppendExecutionProvider("XNNPACK");
#else
ex = Assert.Throws<OnnxRuntimeException>(() => { opt.AppendExecutionProvider("XNNPACK"); });
Assert.Contains("XNNPACK execution provider is not supported in this build", ex.Message);
#endif
#if USE_SNPE
opt.AppendExecutionProvider("SNPE");
#else
ex = Assert.Throws<OnnxRuntimeException>(() => { opt.AppendExecutionProvider("SNPE"); });
Assert.Contains("SNPE execution provider is not supported in this build", ex.Message);
#endif
#if USE_QNN
opt.AppendExecutionProvider("QNN");
#else
ex = Assert.Throws<OnnxRuntimeException>(() => { opt.AppendExecutionProvider("QNN"); });
Assert.Contains("QNN execution provider is not supported in this build", ex.Message);
#endif
#if USE_COREML
opt.AppendExecutionProvider("CoreML");
#else
ex = Assert.Throws<OnnxRuntimeException>(() => { opt.AppendExecutionProvider("CoreML"); });
Assert.Contains("CoreML execution provider is not supported in this build", ex.Message);
#endif
AssertUtils.IfThrowsCheckException<OnnxRuntimeException>(
() => { opt.AppendExecutionProvider("CoreML"); },
"Appending CoreML EP should have succeeded or thrown an OnnRuntimeException with the expected message. ",
"CoreML execution provider is not supported in this build");

AssertUtils.IfThrowsCheckException<OnnxRuntimeException>(
() => { opt.AppendExecutionProvider("XNNPACK"); },
"Appending XNNPACK EP should have succeeded or thrown an OnnRuntimeException with the expected message. ",
"XNNPACK execution provider is not supported in this build");

AssertUtils.IfThrowsCheckException<OnnxRuntimeException>(
() => { opt.AppendExecutionProvider("SNPE"); },
"Appending SNPE EP should have succeeded or thrown an OnnRuntimeException with the expected message. ",
"SNPE execution provider is not supported in this build");

AssertUtils.IfThrowsCheckException<OnnxRuntimeException>(
() => { opt.AppendExecutionProvider("QNN"); },
"Appending QNN EP should have succeeded or thrown an OnnRuntimeException with the expected message. ",
"QNN execution provider is not supported in this build");

opt.AppendExecutionProvider_CPU(1);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
parameters:
AgentPool : 'Win-CPU'
ArtifactSuffix: ''
SpecificArtifact: false
BuildId: ''

stages:
- stage: NuGet_Test_Android
jobs:
- job: NuGet_Test_Android
workspace:
clean: all
pool: "${{ parameters.AgentPool }}"

variables:
- name: OnnxRuntimeBuildDirectory
value: '$(Build.BinariesDirectory)'

steps:
- task: NuGetToolInstaller@0
displayName: Use Nuget 6.10.x
inputs:
versionSpec: 6.10.x

- template: ../../templates/flex-downloadPipelineArtifact.yml
parameters:
StepName: 'Download Pipeline Artifact'
ArtifactName: drop-signed-nuget-${{ parameters.ArtifactSuffix }}
TargetPath: '$(Build.BinariesDirectory)\nuget-artifact'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}

- template: get-nuget-package-version-as-variable.yml
parameters:
packageFolder: '$(Build.BinariesDirectory)\nuget-artifact'

- task: PowerShell@2
displayName: Install MAUI workloads
inputs:
targetType: 'inline'
script: |
dotnet workload install maui maui-android android
workingDirectory: '$(Build.SourcesDirectory)\csharp'

- task: PowerShell@2
displayName: Publish Android MAUI APK
inputs:
targetType: 'inline'
script: |
dotnet nuget add source $(Build.BinariesDirectory)\nuget-artifact --name local-nuget
dotnet publish -c Release --property:UsePrebuiltNativePackage=true --property:CurrentOnnxRuntimeVersion=$(NuGetPackageVersionNumber) -f net8.0-android
workingDirectory: '$(Build.SourcesDirectory)\csharp\test\Microsoft.ML.OnnxRuntime.Tests.MAUI'

- task: PowerShell@2
displayName: Run BrowserStack test
inputs:
targetType: 'inline'
script: |
dotnet test
workingDirectory: '$(Build.SourcesDirectory)\csharp\test\Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android'
env:
BROWSERSTACK_USERNAME: $(browserstack_username)
BROWSERSTACK_ACCESS_KEY: $(browserstack_access_key)
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ jobs:
pool: 'onnxruntime-Ubuntu2204-AMD-CPU'
workspace:
clean: all
pool:
vmImage: 'macOS-14'
variables:
runCodesignValidationInjection: false
ANDROID_AVD_HOME: $(Agent.TempDirectory)
Expand Down Expand Up @@ -114,4 +112,3 @@ jobs:
- template: component-governance-component-detection-steps.yml
parameters :
condition : 'succeeded'

7 changes: 7 additions & 0 deletions tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,13 @@ stages:
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}

- template: ../nuget/templates/test_android.yml
parameters:
AgentPool : 'onnxruntime-Win-CPU-2022'
ArtifactSuffix: 'CPU'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}

- template: ../nuget/templates/test_linux.yml
parameters:
AgentPool : onnxruntime-Ubuntu2204-AMD-CPU
Expand Down
Loading