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

GraalVM Native Image support #403

Open
Tracked by #417
beckermarc opened this issue Aug 4, 2023 · 4 comments
Open
Tracked by #417

GraalVM Native Image support #403

beckermarc opened this issue Aug 4, 2023 · 4 comments

Comments

@beckermarc
Copy link

GraalVM Native Image support and tooling also allows to run tests in Native Image style (e.g. see docs of Spring Boot Native Image support).

As Hamcrest is a popular matcher library and Spring Boot includes Hamcrest for example in it's spring-boot-starter-test it is very likely that Hamcrest is also used in tests executed inside a GraalVM Native Image.

There are some areas where Hamcrest is relying on Java reflection most prominently through ReflectiveTypeFinder, which is used in various matcher implementations. Some of these reflection usages - but not all - can be known upfront in the library. GraalVM requires reflection usage to be registered in reflect-config.json files (see GraalVM docs here and here).

A good starting point that should suit many usecases already are reflection hints for the usages of ReflectiveTypeFinder.
Therefore my suggestion is to place the following reflect-config.json file, placed under hamcrest/src/main/resources/META-INF/native-image/org.hamcrest/hamcrest/

[
  {
    "condition": {
      "typeReachable": "org.hamcrest.TypeSafeMatcher"
    },
    "name": "org.hamcrest.TypeSafeMatcher",
    "queryAllDeclaredMethods": true
  },
  {
    "condition": {
      "typeReachable": "org.hamcrest.TypeSafeDiagnosingMatcher"
    },
    "name": "org.hamcrest.TypeSafeDiagnosingMatcher",
    "queryAllDeclaredMethods": true
  },
  {
    "condition": {
      "typeReachable": "org.hamcrest.FeatureMatcher"
    },
    "name": "org.hamcrest.FeatureMatcher",
    "queryAllDeclaredMethods": true
  }
]

As it is preferred to add GraalVM Native Image support to the libraries directly I wanted to ask, if there is willingness to add this configuration to Hamcrest? If not, an alternative solution would be to add the reflection hints to the community maintained GraalVM Reachability Metadata.

@tumbarumba
Copy link
Member

Thanks for looking into this @beckermarc. I'm looking at creating some new Hamcrest releases in the near future. This looks like doesn't have any backwards compatibilty issues.

I'm not a GraalVM user. Is there a sensible way to test this is working correctly?

@beckermarc
Copy link
Author

Thanks for picking this up.

Is there a sensible way to test this is working correctly?

Yes, although it requires some steps:

  1. Install GraalVM (for example via SDKman!): https://www.graalvm.org/downloads/
  2. Initialize a simple Spring Boot app with Native Image: https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.3.0&packaging=jar&jvmVersion=17&groupId=com.example&artifactId=demo&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.demo&dependencies=native
  3. Add a line to the pregenerated test class with a matcher that requires reflection, for example: MatcherAssert.assertThat("foobar", Matchers.containsString("foo"));
  4. Run mvn -PnativeTest test -> should fail with Cannot determine correct type for matchesSafely() method.
  5. Add the reflect-config.json file suggested by me above to Hamcrest as described above and switch the project to that Hamcrest SNAPSHOT version.
  6. Run mvn -PnativeTest test -> should succeed now

@tumbarumba
Copy link
Member

tumbarumba commented Jun 4, 2024

Thanks @beckermarc. This project is a complete mess right now, suffering from years of neglect. I think a priority is to get the CI infrastructure working again. When I'm doing that, I'll see if there's some way we can pull in a graalvm image to run the tests on. It might be a bit tricky, but I'm sure there's a way. I don't have a massive amount of free time, but I'm planning on plugging away at this project for the forseeable future. I won't get back to this straight away, but I'll get there eventually :-)

@tumbarumba tumbarumba mentioned this issue Aug 3, 2024
13 tasks
@linghengqian
Copy link

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.startsWith;

    @Test
    void failNativeTest(){
        assertThat("172.30.110.7@-@178924", startsWith("172.30.110.7@-@"));
    }

    @Test
    void successNativeTest(){
        assertThat("172.30.110.7@-@178924".startsWith("172.30.110.7@-@"), is(true));
    }
  • As a temporary measure, apache/shardingsphere-elasticjob semi-automatically generates and hosts the GraalVM Reachability Metadata which is part of org.hamcrest:hamcrest:2.2.
[
{
  "condition":{"typeReachable":"org.hamcrest.internal.ReflectiveTypeFinder"},
  "name":"org.hamcrest.core.StringStartsWith",
  "queryAllDeclaredMethods":true
},
{
  "condition":{"typeReachable":"org.hamcrest.internal.ReflectiveTypeFinder"},
  "name":"org.hamcrest.core.SubstringMatcher",
  "queryAllDeclaredMethods":true
}
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants