Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Java.Interop-Tests] Initial dotnet test support #801

Merged
merged 1 commit into from
Feb 18, 2021

Conversation

jonpryor
Copy link
Member

@jonpryor jonpryor commented Feb 14, 2021

Context: dotnet/android#5592

With introductory support for Java.Interop.dll on .NET Core via
commit 2a299eb, what about running the unit tests within
Java.Interop-Tests.dll on .NET Core?

Update src/java-interop so that the java-interop native library
is copied to $(OutputPath) of referencing projects. This allows
e.g. libjava-interop.dylib to be implicitly copied into the
appropriate output dir, e.g. bin/TestDebug-netcoreapp3.1.
Further update src/java-interop so that $(IntermediateOutputPath)
correctly differs between net472 and netcoreapp3.1 builds, and
generate jni.c into $(IntermediateOutputPath). This ensures that
e.g. bin/Debug/libjava-interop.dylib reliably uses Mono on net472,
instead of occasionally/accidentally being the netstandard version.

Update tests/Java.Interop-Tests and tests/TestJVM/TestJVM.csproj
to multitarget between net472 and netcoreapp3.1.

Update Java.Runtime.Environment.csproj to reference
java-interop.csproj, which causes all projects which reference
Java.Runtime.Environment.csproj to get the java-interop native
library copied to the appropriate $(OutputPath).

Update JreRuntime to use "dummy" JniRuntime.JniValueManager and
JniRuntime.JniObjectReferenceManager subclasses when not running
under Mono. This avoids an ArgumentException when creating the
Java.InteropTests.JavaVMFixture instance used by the unit tests.

Update tests/TestJVM to reference
Xamarin.Android.Tools.AndroidSdk.csproj, allowing the TestJVM type
to use JdkInfo to find a JVM to use. This allows us to avoid a
requirement to set the JI_JVM_PATH environment variable in order to
create TestJVM instances.

Update src/Java.Interop so that generic delegate types are not
marshaled via P/Invoke. .NET Core doesn't support this.

Update JniEnvironment.Types.FindClass() to call
info.Runtime.GetExceptionForThrowable() as soon as possible after
calling JNIEnv::ExceptionClear(), instead of potentially after
calling ClassLoader.loadClass(). The problem is Java-side stack-
frames: if info.Runtime.GetExceptionForThrowable() is delayed, then
the exception created by info.Runtime.GetExceptionForThrowable()
only contains the Java message text, but no stack trace, and no
"cause" information. This meant that when generic delegate types
were still being used, dotnet test failures would show:

    java.lang.NoClassDefFoundError: Could not initialize class com.xamarin.interop.CallVirtualFromConstructorDerive

with no additional information about why it failed.
(It failed because P/Invoke was trying to marshal a generic delegate,
so the ManagedPeer static constructor threw an exception, which
was "within" a static{ManagedPeer.registerNativeMembers(…)} Java
block, and thus the Java type initializer failed, so nothing worked.)

Update **/*.java to remove Version, Culture, and PublicKeyToken
information from the assembly qualified name, for two reasons:

  1. The default Version value appears to differ between
    net472 (0.0.0.0) and netcoreapp3.1 (1.0.0.0).

  2. Wrt MobSf Scan Security issue android#5592, certain "security products"
    believe that the Version number is an IP address, and emit a
    warning about "IP Address disclosure".

Since we don't strong-name any of these assemblies (unit tests!)
or the expected execution environment is a "self-contained app"
in which you can't have multiple versions of the same assembly
(Xamarin.Android), remove the Version, Culture, and PublicKeyToken
information from these Java Callable Wrappers.

@jonpryor jonpryor force-pushed the jonp-ji-tests-on-dotnet branch from 748d156 to 0f81620 Compare February 17, 2021 15:13
@jonpryor
Copy link
Member Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonpryor jonpryor force-pushed the jonp-ji-tests-on-dotnet branch from 0f81620 to 827c627 Compare February 17, 2021 15:19
Context: dotnet/android#5592

With introductory support for `Java.Interop.dll` on .NET Core via
commit 2a299eb, what about running the unit tests within
`Java.Interop-Tests.dll` on .NET Core?

Update `src/java-interop` so that the `java-interop` native library
is copied to `$(OutputPath)` of referencing projects.  This allows
e.g. `libjava-interop.dylib` to be implicitly copied into the
appropriate output dir, e.g. `bin/TestDebug-netcoreapp3.1`.
Further update `src/java-interop` so that `$(IntermediateOutputPath)`
correctly differs between net472 and netcoreapp3.1 builds, and
generate `jni.c` into `$(IntermediateOutputPath)`.  This ensures that
e.g. `bin/Debug/libjava-interop.dylib` reliably uses Mono on net472,
instead of occasionally/accidentally being the netstandard version.

Update `tests/Java.Interop-Tests` and `tests/TestJVM/TestJVM.csproj`
to multitarget between net472 and netcoreapp3.1.

Update `Java.Runtime.Environment.csproj` to reference
`java-interop.csproj`, which causes all projects which reference
`Java.Runtime.Environment.csproj` to get the `java-interop` native
library copied to the appropriate `$(OutputPath)`.

Update `JreRuntime` to use "dummy" `JniRuntime.JniValueManager` and
`JniRuntime.JniObjectReferenceManager` subclasses when *not* running
under Mono.  This avoids an `ArgumentException` when creating the
`Java.InteropTests.JavaVMFixture` instance used by the unit tests.

Update `tests/TestJVM` to reference
`Xamarin.Android.Tools.AndroidSdk.csproj`, allowing the `TestJVM` type
to use `JdkInfo` to find a JVM to use.  This allows us to avoid a
requirement to set the `JI_JVM_PATH` environment variable in order to
create `TestJVM` instances.

Update `src/Java.Interop` so that generic delegate types are not
marshaled via P/Invoke.  .NET Core doesn't support this.

Update `JniEnvironment.Types.FindClass()` to call
`info.Runtime.GetExceptionForThrowable()` as soon as possible after
calling `JNIEnv::ExceptionClear()`, instead of potentially after
calling `ClassLoader.loadClass()`.  The problem is Java-side stack-
frames: if `info.Runtime.GetExceptionForThrowable()` is delayed, then
the exception created by `info.Runtime.GetExceptionForThrowable()`
only contains the Java message text, but no stack trace, and no
"cause" information.  This meant that when generic delegate types
were still being used, `dotnet test` failures would show:

	java.lang.NoClassDefFoundError: Could not initialize class com.xamarin.interop.CallVirtualFromConstructorDerive

with *no* additional information about *why* it failed.
(It failed because P/Invoke was trying to marshal a generic delegate,
so the `ManagedPeer` static constructor threw an exception, which
was "within" a `static{ManagedPeer.registerNativeMembers(…)}` Java
block, and thus the Java type initializer failed, so nothing worked.)

Update `**/*.java` to remove Version, Culture, and PublicKeyToken
information from the assembly qualified name, for two reasons:

 1. The default Version value appears to differ between
    net472 (0.0.0.0) and netcoreapp3.1 (1.0.0.0).

 2. Wrt dotnet/android#5592, certain "security products"
    believe that the Version number is an *IP address*, and emit a
    warning about "IP Address disclosure".

Since we don't strong-name any of these assemblies (unit tests!)
*or* the expected execution environment is a "self-contained app"
in which you can't have multiple versions of the same assembly
(Xamarin.Android), remove the Version, Culture, and PublicKeyToken
information from these Java Callable Wrappers.
@jonpryor jonpryor force-pushed the jonp-ji-tests-on-dotnet branch from 827c627 to 4b8b232 Compare February 17, 2021 23:39
@jonpryor jonpryor changed the title [Java.Interop-Tests] .NET Core support [Java.Interop-Tests] Initial dotnet test support Feb 17, 2021
@jonpryor jonpryor requested a review from jpobst February 17, 2021 23:40
@jonpryor jonpryor marked this pull request as ready for review February 17, 2021 23:40
@jonpryor
Copy link
Member Author

Note that this is initial; it is not "complete":

% dotnet test bin/TestDebug-netcoreapp3.1/Java.Interop-Tests.dll
Failed!  - Failed:    16, Passed:   325, Skipped:     1, Total:   342, Duration: 310 ms - /Users/jon/Documents/Developer/src/xamarin/Java.Interop/bin/TestDebug-netcoreapp3.1/Java.Interop-Tests.dll (netcoreapp3.1)

16 tests pass, mostly because the DummyValueManager doesn't do anything, so all tests which requires it fail.

@jonpryor jonpryor merged commit 89a5a22 into dotnet:main Feb 18, 2021
@jpobst jpobst added this to the 11.3 (16.10 / 8.10) milestone Mar 1, 2021
@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants