-
Notifications
You must be signed in to change notification settings - Fork 30
Check that the loaded native library is compatible [ECR-3148]: #882
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
Check that the loaded native library is compatible [ECR-3148]: #882
Conversation
Check that the loaded native library is compatible, i.e., has the same version as the Java library. This check is useful in _service integration tests_ that can update their dependency on 'exonum-java-binding-core' but not the application (that contains the native library), or vice versa. Requires native code to enable this check: ECR-3172
} | ||
} | ||
|
||
// todo: Shall we extract it as a Supplier<String>, and System.load() as Consumer<String> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can possibly parameterize this class with this couple of functions (hence the constructor):
private static final LibraryLoader INSTANCE =
new LibraryLoader(System::loadLibrary, LibraryLoader::nativeGetLibraryVersion,
JAVA_BINDING_VERSION);
Is this complication worth it? Also, it will still have dependencies on the system properties and environment, unless we also abstract them and parameterize 🙃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about such refactoring for tests because it contains only one equals
statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙆♂️ , let's keep it simple(r) then.
private static final String JAVA_LIBRARY_PATH_PROPERTY = "java.library.path"; | ||
private static final String DYNAMIC_LIBRARIES_ENV_VAR_WINDOWS = "PATH"; | ||
private static final String DYNAMIC_LIBRARIES_ENV_VAR_UNIX = "LD_LIBRARY_PATH"; | ||
// TODO: Shall this class read the properties instead? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could make Maven auto-generate the properties file with the version, but … not sure we need that at this moment (with some code here reading those properties).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we then update the version string here on each release?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes — update this string each release or make Maven write and this code read the build properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible/better to generate source file with constants before building the "static" source code? (move it to compilation phase instead of reading properties at runtime)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's trivial to pick up maven properties in runtime. So I believe it brings more benefits than drawbacks 🦊
Also, looks like we can configure RUSTFLAGS in maven and remove tests_profile
? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's trivial to pick up maven properties in runtime. So I believe it brings more benefits than drawbacks fox_face
Yes, it is not difficult at all, but it seems like an overkill at this point: this class will gain a responsibility to read (once) a certain file with properties + the build configuration needs to be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, looks like we can configure RUSTFLAGS in maven and remove tests_profile
How? It invokes rustup and find do determine some various paths to add to RUSTFLAGS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>define-property</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<exportAntProperties>true</exportAntProperties>
<tasks>
<exec executable="git" outputproperty="testproperty">
<arg value="--version"/>
</exec>
</tasks>
</configuration>
</execution>
<execution>
<id>show-property</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Displaying value of 'testproperty':</echo>
<echo>[testproperty] ${testproperty}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
It'll print in the log:
[echo] Displaying value of 'testproperty':
[echo] [testproperty] git version 2.20.1 (Apple Git-117)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks interesting, maybe we can offload that to an Ant script instead of a bash script for ease of use (no source tests_profile) and support of any platform (Windows). Please file an issue if consider that promising.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* A loader of the native shared library with Exonum framework bindings. | ||
* A loader of the native shared library with Exonum framework bindings. It loads the native | ||
* library and also verifies that it is compatible with the Java classes. The native library | ||
* is compatible iff it has exactly the same version as this Java library. The revision |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: iff -> if
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It isn't: "if and only if"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @param libraryVersion the version of this library to verify that the native library | ||
* is compatible with it. The compatibility is d | ||
*/ | ||
LibraryLoader(String libraryVersion) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does it package private, not private? I see no tests.
* Creates a new library loader. | ||
* | ||
* @param libraryVersion the version of this library to verify that the native library | ||
* is compatible with it. The compatibility is d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d? 🙃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably "determined by comparing …" :-D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code review gives you great opportunity to discover lots of new words like "iff", "d" 🙃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@skletsun OMG YOLO
private static final String JAVA_LIBRARY_PATH_PROPERTY = "java.library.path"; | ||
private static final String DYNAMIC_LIBRARIES_ENV_VAR_WINDOWS = "PATH"; | ||
private static final String DYNAMIC_LIBRARIES_ENV_VAR_UNIX = "LD_LIBRARY_PATH"; | ||
// TODO: Shall this class read the properties instead? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we then update the version string here on each release?
|
||
private static final Logger logger = LogManager.getLogger(LibraryLoader.class); | ||
|
||
private static final LibraryLoader INSTANCE = new LibraryLoader(JAVA_BINDING_VERSION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about to implement the singleton with lazy loading? It doesn't bring a big overhead but anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it will never be actually "lazy" loaded, if I understand correctly — a class is loaded when its first static symbol is accessed (with some exception for compile-time constants, I believe), and the only publicly accessible symbol is load
.
https://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4.1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, you are right. My doubt was that it'll be loaded in case no integration tests defined.
} | ||
|
||
private static void loadOnce() { | ||
synchronized void loadOnce() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private?
} | ||
} | ||
|
||
// todo: Shall we extract it as a Supplier<String>, and System.load() as Consumer<String> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about such refactoring for tests because it contains only one equals
statement.
Overview
Check that the loaded native library is compatible, i.e.,
has the same version as the Java library. This check is useful in
service integration tests that can update their dependency
on 'exonum-java-binding-core' but not the application (that
contains the native library), or vice versa.
Requires native code to enable this check: ECR-3172
See: https://jira.bf.local/browse/ECR-3148
Definition of Done