This is an automated email from the ASF dual-hosted git repository.

hemant pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 7ac04658a9 HDDS-9174. Native library loader fails when system property 
"native.lib.tmp.dir" is not set (#5190)
7ac04658a9 is described below

commit 7ac04658a9c8379155068529424a055018dc268e
Author: Swaminathan Balachandran <[email protected]>
AuthorDate: Tue Sep 5 22:54:25 2023 -0700

    HDDS-9174. Native library loader fails when system property 
"native.lib.tmp.dir" is not set (#5190)
---
 hadoop-hdds/rocks-native/pom.xml                   |  5 ++
 .../hadoop/hdds/utils/NativeLibraryLoader.java     | 29 +++++--
 .../hadoop/hdds/utils/TestNativeLibraryLoader.java | 91 ++++++++++++++++++++++
 pom.xml                                            |  6 ++
 4 files changed, 126 insertions(+), 5 deletions(-)

diff --git a/hadoop-hdds/rocks-native/pom.xml b/hadoop-hdds/rocks-native/pom.xml
index 14fec20de3..6866890d81 100644
--- a/hadoop-hdds/rocks-native/pom.xml
+++ b/hadoop-hdds/rocks-native/pom.xml
@@ -57,6 +57,11 @@
             <artifactId>mockito-junit-jupiter</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     <properties>
         <maven.compiler.source>8</maven.compiler.source>
diff --git 
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryLoader.java
 
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryLoader.java
index 2ab264a6f6..10df236f88 100644
--- 
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryLoader.java
+++ 
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryLoader.java
@@ -18,6 +18,7 @@
 
 package org.apache.hadoop.hdds.utils;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.apache.hadoop.ozone.util.ShutdownHookManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -28,6 +29,7 @@ import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -78,7 +80,8 @@ public class NativeLibraryLoader {
     return OS.startsWith("linux");
   }
 
-  private static String getLibOsSuffix() {
+  @VisibleForTesting
+  static String getLibOsSuffix() {
     if (isMac()) {
       return ".dylib";
     } else if (isWindows()) {
@@ -126,20 +129,36 @@ public class NativeLibraryLoader {
     return isLibraryLoaded(libraryName);
   }
 
+  // Added function to make this testable.
+  @VisibleForTesting
+  static String getSystemProperty(String property) {
+    return System.getProperty(property);
+  }
+
+  // Added function to make this testable
+  @VisibleForTesting
+  static InputStream getResourceStream(String libraryFileName) {
+    return NativeLibraryLoader.class.getClassLoader()
+        .getResourceAsStream(libraryFileName);
+  }
+
   private Optional<File> copyResourceFromJarToTemp(final String libraryName)
       throws IOException {
     final String libraryFileName = getJniLibraryFileName(libraryName);
     InputStream is = null;
     try {
-      is = getClass().getClassLoader().getResourceAsStream(libraryFileName);
+      is = getResourceStream(libraryFileName);
       if (is == null) {
         return Optional.empty();
       }
 
+      final String nativeLibDir =
+          Objects.nonNull(getSystemProperty(NATIVE_LIB_TMP_DIR)) ?
+              getSystemProperty(NATIVE_LIB_TMP_DIR) : "";
+      final File dir = new File(nativeLibDir).getAbsoluteFile();
+
       // create a temporary file to copy the library to
-      final File temp = File.createTempFile(libraryName, getLibOsSuffix(),
-          new File(Optional.ofNullable(System.getProperty(NATIVE_LIB_TMP_DIR))
-              .orElse("")));
+      final File temp = File.createTempFile(libraryName, getLibOsSuffix(), 
dir);
       if (!temp.exists()) {
         return Optional.empty();
       } else {
diff --git 
a/hadoop-hdds/rocks-native/src/test/java/org/apache/hadoop/hdds/utils/TestNativeLibraryLoader.java
 
b/hadoop-hdds/rocks-native/src/test/java/org/apache/hadoop/hdds/utils/TestNativeLibraryLoader.java
new file mode 100644
index 0000000000..472954f2bd
--- /dev/null
+++ 
b/hadoop-hdds/rocks-native/src/test/java/org/apache/hadoop/hdds/utils/TestNativeLibraryLoader.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdds.utils;
+
+
+import org.apache.ozone.test.tag.Native;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static 
org.apache.hadoop.hdds.utils.NativeConstants.ROCKS_TOOLS_NATIVE_LIBRARY_NAME;
+import static 
org.apache.hadoop.hdds.utils.NativeLibraryLoader.NATIVE_LIB_TMP_DIR;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.same;
+
+/**
+ * Test class for NativeLibraryLoader.
+ */
+public class TestNativeLibraryLoader {
+
+  private static Stream<String> nativeLibraryDirectoryLocations()
+      throws IOException {
+    return Stream.of("", File.createTempFile("prefix", "suffix")
+        .getParentFile().getAbsolutePath(), null);
+  }
+
+  @Native(ROCKS_TOOLS_NATIVE_LIBRARY_NAME)
+  @ParameterizedTest
+  @MethodSource("nativeLibraryDirectoryLocations")
+  public void testNativeLibraryLoader(
+      String nativeLibraryDirectoryLocation) {
+    Map<String, Boolean> libraryLoadedMap = new HashMap<>();
+    NativeLibraryLoader loader = new NativeLibraryLoader(libraryLoadedMap);
+    try (MockedStatic<NativeLibraryLoader> mockedNativeLibraryLoader =
+             Mockito.mockStatic(NativeLibraryLoader.class,
+                 Mockito.CALLS_REAL_METHODS)) {
+      mockedNativeLibraryLoader.when(() ->
+              NativeLibraryLoader.getSystemProperty(same(NATIVE_LIB_TMP_DIR)))
+          .thenReturn(nativeLibraryDirectoryLocation);
+      mockedNativeLibraryLoader.when(() -> NativeLibraryLoader.getInstance())
+          .thenReturn(loader);
+      Assertions.assertTrue(NativeLibraryLoader.getInstance()
+          .loadLibrary(ROCKS_TOOLS_NATIVE_LIBRARY_NAME));
+      Assertions.assertTrue(NativeLibraryLoader
+          .isLibraryLoaded(ROCKS_TOOLS_NATIVE_LIBRARY_NAME));
+      // Mocking to force copy random bytes to create a lib file to
+      // nativeLibraryDirectoryLocation. But load library will fail.
+      mockedNativeLibraryLoader.when(() ->
+          NativeLibraryLoader.getResourceStream(anyString()))
+          .thenReturn(new ByteArrayInputStream(new byte[]{0, 1, 2, 3}));
+      String dummyLibraryName = "dummy_lib";
+      NativeLibraryLoader.getInstance().loadLibrary(dummyLibraryName);
+      NativeLibraryLoader.isLibraryLoaded(dummyLibraryName);
+      // Checking if the resource with random was copied to a temp file.
+      File[] libPath =
+          new File(nativeLibraryDirectoryLocation == null ? "" :
+              nativeLibraryDirectoryLocation)
+          .getAbsoluteFile().listFiles((dir, name) ->
+              name.startsWith(dummyLibraryName) &&
+                  name.endsWith(NativeLibraryLoader.getLibOsSuffix()));
+      Assertions.assertNotNull(libPath);
+      Assertions.assertEquals(1, libPath.length);
+      Assertions.assertTrue(libPath[0].delete());
+    }
+
+  }
+}
diff --git a/pom.xml b/pom.xml
index 717dacd8d6..241db48476 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1571,6 +1571,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xs
         <artifactId>jgrapht-ext</artifactId>
         <version>${jgrapht.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.mockito</groupId>
+        <artifactId>mockito-inline</artifactId>
+        <version>${mockito2.version}</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to