Browse Source

Add dedicated JniClass to wrap C like JNI functionality

Patrick-Christopher Mattulat 1 year ago
parent
commit
d31fcb781c

+ 77 - 25
CMakeLists.txt

@@ -194,6 +194,12 @@ set(SOURCE_FILES_CORE
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/LibraryVersion.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/Version.cpp)
 
+set(SOURCE_FILES_CORE_JNI
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/interface/IJniApi.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/jni/JniApi.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/jni/JniClass.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/jni/JniClassParameter.cpp)
+
 set(SOURCE_FILES_ENCODING
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/encoding/Base64.cpp)
 
@@ -318,6 +324,12 @@ if (${LS_STD_BUILD_WITH_TESTS})
             ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/core/ClassWrapper.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/core/MathOddValidator.cpp)
 
+    set(UNIT_TEST_FILES_CORE_JNI
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/jni/JniApiTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/jni/JniClassParameterTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/jni/JniClassTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/core/jni/MockJniApi.cpp)
+
     set(UNIT_TEST_FILES_ENCODING
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/encoding/Base64Test.cpp)
 
@@ -424,8 +436,13 @@ endif ()
 ##########################################################
 
 if (${LS_STD_BUILD_WITH_TESTS})
-    message("${MODULE_NAME_CORE}: Building unit tests...")
-    add_executable(${MODULE_NAME_CORE}-unit-test ${UNIT_TEST_FILES_CORE})
+    if (${LS_STD_BUILD_WITH_JNI})
+        message("${MODULE_NAME_CORE}: Building unit tests with JNI support...")
+        add_executable(${MODULE_NAME_CORE}-unit-test ${UNIT_TEST_FILES_CORE} ${UNIT_TEST_FILES_CORE_JNI})
+    else ()
+        message("${MODULE_NAME_CORE}: Building unit tests...")
+        add_executable(${MODULE_NAME_CORE}-unit-test ${UNIT_TEST_FILES_CORE})
+    endif ()
 endif ()
 
 ##########################################################
@@ -471,16 +488,30 @@ endif ()
 ##########################################################
 
 if (${LS_STD_BUILD_WITH_TESTS})
-    message("${PROJECT_NAME}: Building unit tests...")
-    add_executable(${PROJECT_NAME}-unit-test
-            ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/TestHelper.cpp
-            ${UNIT_TEST_FILES_BOXING}
-            ${UNIT_TEST_FILES_CORE}
-            ${UNIT_TEST_FILES_ENCODING}
-            ${UNIT_TEST_FILES_EVENT}
-            ${UNIT_TEST_FILES_IO}
-            ${UNIT_TEST_FILES_SERIALIZATION}
-            ${UNIT_TEST_FILES_TIME})
+    if (${LS_STD_BUILD_WITH_JNI})
+        message("${PROJECT_NAME}: Building unit tests with JNI support...")
+        add_executable(${PROJECT_NAME}-unit-test
+                ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/TestHelper.cpp
+                ${UNIT_TEST_FILES_BOXING}
+                ${UNIT_TEST_FILES_CORE}
+                ${UNIT_TEST_FILES_CORE_JNI}
+                ${UNIT_TEST_FILES_ENCODING}
+                ${UNIT_TEST_FILES_EVENT}
+                ${UNIT_TEST_FILES_IO}
+                ${UNIT_TEST_FILES_SERIALIZATION}
+                ${UNIT_TEST_FILES_TIME})
+    else ()
+        message("${PROJECT_NAME}: Building unit tests...")
+        add_executable(${PROJECT_NAME}-unit-test
+                ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/TestHelper.cpp
+                ${UNIT_TEST_FILES_BOXING}
+                ${UNIT_TEST_FILES_CORE}
+                ${UNIT_TEST_FILES_ENCODING}
+                ${UNIT_TEST_FILES_EVENT}
+                ${UNIT_TEST_FILES_IO}
+                ${UNIT_TEST_FILES_SERIALIZATION}
+                ${UNIT_TEST_FILES_TIME})
+    endif ()
 endif ()
 
 ####################################################################################################################
@@ -524,17 +555,32 @@ endif ()
 ####################################################################################################################
 
 if (${LS_STD_BUILD_WITH_TESTS})
-    message("${PROJECT_NAME}: Building all tests...")
-    add_executable(${PROJECT_NAME}-test
-            ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/TestHelper.cpp
-            ${UNIT_TEST_FILES_BOXING}
-            ${UNIT_TEST_FILES_CORE}
-            ${UNIT_TEST_FILES_ENCODING}
-            ${UNIT_TEST_FILES_EVENT}
-            ${UNIT_TEST_FILES_IO}
-            ${INTEGRATION_TEST_FILES_IO}
-            ${UNIT_TEST_FILES_SERIALIZATION}
-            ${UNIT_TEST_FILES_TIME})
+    if (${LS_STD_BUILD_WITH_JNI})
+        message("${PROJECT_NAME}: Building all tests...")
+        add_executable(${PROJECT_NAME}-test
+                ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/TestHelper.cpp
+                ${UNIT_TEST_FILES_BOXING}
+                ${UNIT_TEST_FILES_CORE}
+                ${UNIT_TEST_FILES_CORE_JNI}
+                ${UNIT_TEST_FILES_ENCODING}
+                ${UNIT_TEST_FILES_EVENT}
+                ${UNIT_TEST_FILES_IO}
+                ${INTEGRATION_TEST_FILES_IO}
+                ${UNIT_TEST_FILES_SERIALIZATION}
+                ${UNIT_TEST_FILES_TIME})
+    else ()
+        message("${PROJECT_NAME}: Building all tests with JNI support...")
+        add_executable(${PROJECT_NAME}-test
+                ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/TestHelper.cpp
+                ${UNIT_TEST_FILES_BOXING}
+                ${UNIT_TEST_FILES_CORE}
+                ${UNIT_TEST_FILES_ENCODING}
+                ${UNIT_TEST_FILES_EVENT}
+                ${UNIT_TEST_FILES_IO}
+                ${INTEGRATION_TEST_FILES_IO}
+                ${UNIT_TEST_FILES_SERIALIZATION}
+                ${UNIT_TEST_FILES_TIME})
+    endif ()
 endif ()
 
 ####################################################################################################################
@@ -574,8 +620,14 @@ if (${LS_STD_BUILD_STATIC})
 endif ()
 
 if (${LS_STD_BUILD_SHARED})
-    add_library("${MODULE_NAME_CORE}" SHARED ${SOURCE_FILES_CORE})
-    set_target_properties("${MODULE_NAME_CORE}" PROPERTIES DEBUG_POSTFIX "-d")
+    if (${LS_STD_BUILD_WITH_JNI})
+        message("${MODULE_NAME_CORE}: building with JNI...")
+        add_library("${MODULE_NAME_CORE}" SHARED ${SOURCE_FILES_CORE} ${SOURCE_FILES_CORE_JNI})
+        set_target_properties("${MODULE_NAME_CORE}" PROPERTIES DEBUG_POSTFIX "-d")
+    else ()
+        add_library("${MODULE_NAME_CORE}" SHARED ${SOURCE_FILES_CORE})
+        set_target_properties("${MODULE_NAME_CORE}" PROPERTIES DEBUG_POSTFIX "-d")
+    endif ()
 endif ()
 
 ##########################################################

+ 30 - 0
include/ls-std/core/interface/IJniApi.hpp

@@ -0,0 +1,30 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#ifndef LS_STD_I_JNI_API_HPP
+#define LS_STD_I_JNI_API_HPP
+
+#include <jni.h>
+#include <ls-std/os/dynamic-goal.hpp>
+#include <string>
+
+namespace ls::std::core::interface_type
+{
+  class LS_STD_DYNAMIC_GOAL IJniApi
+  {
+    public:
+
+      IJniApi();
+      virtual ~IJniApi();
+
+      virtual jclass findClass(const ::std::string &_classPath) = 0;
+  };
+}
+
+#endif

+ 33 - 0
include/ls-std/core/jni/JniApi.hpp

@@ -0,0 +1,33 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#ifndef LS_STD_JNI_API_HPP
+#define LS_STD_JNI_API_HPP
+
+#include <ls-std/core/interface/IJniApi.hpp>
+#include <ls-std/os/dynamic-goal.hpp>
+
+namespace ls::std::core
+{
+  class LS_STD_DYNAMIC_GOAL JniApi : public ls::std::core::interface_type::IJniApi
+  {
+    public:
+
+      explicit JniApi(JNIEnv *_environment);
+      ~JniApi() noexcept override;
+
+      jclass findClass(const ::std::string &_classPath) override;
+
+    private:
+
+      JNIEnv *environment{};
+  };
+}
+
+#endif

+ 41 - 0
include/ls-std/core/jni/JniClass.hpp

@@ -0,0 +1,41 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#ifndef LS_STD_JNI_CLASS_HPP
+#define LS_STD_JNI_CLASS_HPP
+
+#include "JniClassParameter.hpp"
+#include <jni.h>
+#include <ls-std/core/interface/IJniApi.hpp>
+#include <ls-std/os/dynamic-goal.hpp>
+#include <memory>
+#include <string>
+
+namespace ls::std::core
+{
+  class LS_STD_DYNAMIC_GOAL JniClass
+  {
+    public:
+
+      explicit JniClass(const ::std::shared_ptr<ls::std::core::JniClassParameter> &_parameter, const ::std::string &_path);
+      virtual ~JniClass();
+
+      bool load(); // nodiscard is optional here
+
+    private:
+
+      jclass javaClass{};
+      ::std::shared_ptr<ls::std::core::JniClassParameter> parameter{};
+      ::std::string path{};
+
+      void _createJniApi();
+  };
+}
+
+#endif

+ 40 - 0
include/ls-std/core/jni/JniClassParameter.hpp

@@ -0,0 +1,40 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#ifndef LS_STD_JNI_CLASS_PARAMETER_HPP
+#define LS_STD_JNI_CLASS_PARAMETER_HPP
+
+#include <jni.h>
+#include <ls-std/core/interface/IJniApi.hpp>
+#include <ls-std/os/dynamic-goal.hpp>
+#include <memory>
+#include <string>
+
+namespace ls::std::core
+{
+  class LS_STD_DYNAMIC_GOAL JniClassParameter
+  {
+    public:
+
+      JniClassParameter();
+      ~JniClassParameter();
+
+      [[nodiscard]] JNIEnv *getJavaEnvironment();
+      [[nodiscard]] ::std::shared_ptr<ls::std::core::interface_type::IJniApi> getJniApi();
+      void setJavaEnvironment(JNIEnv *_environment);
+      void setJniApi(const ::std::shared_ptr<ls::std::core::interface_type::IJniApi> &_jniApi);
+
+    private:
+
+      JNIEnv *environment{};
+      ::std::shared_ptr<ls::std::core::interface_type::IJniApi> jniApi{};
+  };
+}
+
+#endif

+ 17 - 0
include/ls-std/ls-std-core-jni.hpp

@@ -0,0 +1,17 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#ifndef LS_STD_LS_STD_CORE_JNI_HPP
+#define LS_STD_LS_STD_CORE_JNI_HPP
+
+#include <ls-std/core/jni/JniApi.hpp>
+#include <ls-std/core/jni/JniClass.hpp>
+#include <ls-std/core/jni/JniClassParameter.hpp>
+
+#endif

+ 16 - 0
source/ls-std/core/interface/IJniApi.cpp

@@ -0,0 +1,16 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#include <ls-std/core/interface/IJniApi.hpp>
+
+using ls::std::core::interface_type::IJniApi;
+
+IJniApi::IJniApi() = default;
+
+IJniApi::~IJniApi() = default;

+ 28 - 0
source/ls-std/core/jni/JniApi.cpp

@@ -0,0 +1,28 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#include <ls-std/core/evaluator/NullPointerArgumentEvaluator.hpp>
+#include <ls-std/core/jni/JniApi.hpp>
+
+using ls::std::core::JniApi;
+using ls::std::core::NullPointerArgumentEvaluator;
+using std::string;
+
+JniApi::JniApi(JNIEnv *_environment)
+{
+  NullPointerArgumentEvaluator{_environment}.evaluate();
+  this->environment = _environment;
+}
+
+JniApi::~JniApi() noexcept = default;
+
+jclass JniApi::findClass(const string &_classPath)
+{
+  return this->environment->FindClass(_classPath.c_str());
+}

+ 48 - 0
source/ls-std/core/jni/JniClass.cpp

@@ -0,0 +1,48 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#include <ls-std/core/ConditionalFunctionExecutor.hpp>
+#include <ls-std/core/evaluator/EmptyStringArgumentEvaluator.hpp>
+#include <ls-std/core/evaluator/NullPointerArgumentEvaluator.hpp>
+#include <ls-std/core/jni/JniApi.hpp>
+#include <ls-std/core/jni/JniClass.hpp>
+#include <memory>
+
+using ls::std::core::ConditionalFunctionExecutor;
+using ls::std::core::EmptyStringArgumentEvaluator;
+using ls::std::core::JniApi;
+using ls::std::core::JniClass;
+using ls::std::core::JniClassParameter;
+using ls::std::core::NullPointerArgumentEvaluator;
+using std::make_shared;
+using std::shared_ptr;
+using std::string;
+
+JniClass::JniClass(const shared_ptr<JniClassParameter> &_parameter, const string &_path)
+{
+  NullPointerArgumentEvaluator{_parameter}.evaluate();
+  EmptyStringArgumentEvaluator{_path}.evaluate();
+  NullPointerArgumentEvaluator{_parameter->getJavaEnvironment()}.evaluate();
+  this->parameter = _parameter;
+  this->path = _path;
+  ConditionalFunctionExecutor{_parameter->getJniApi() == nullptr}.execute([this]() { _createJniApi(); });
+}
+
+JniClass::~JniClass() = default;
+
+bool JniClass::load()
+{
+  this->javaClass = this->parameter->getJniApi()->findClass(this->path);
+  return this->javaClass != nullptr;
+}
+
+void JniClass::_createJniApi()
+{
+  this->parameter->setJniApi(make_shared<JniApi>(this->parameter->getJavaEnvironment()));
+}

+ 39 - 0
source/ls-std/core/jni/JniClassParameter.cpp

@@ -0,0 +1,39 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#include <ls-std/core/jni/JniClassParameter.hpp>
+
+using ls::std::core::JniClassParameter;
+using ls::std::core::interface_type::IJniApi;
+using std::shared_ptr;
+using std::string;
+
+JniClassParameter::JniClassParameter() = default;
+
+JniClassParameter::~JniClassParameter() = default;
+
+JNIEnv *JniClassParameter::getJavaEnvironment()
+{
+  return this->environment;
+}
+
+shared_ptr<IJniApi> JniClassParameter::getJniApi()
+{
+  return this->jniApi;
+}
+
+void JniClassParameter::setJavaEnvironment(JNIEnv *_environment)
+{
+  this->environment = _environment;
+}
+
+void JniClassParameter::setJniApi(const shared_ptr<IJniApi> &_jniApi)
+{
+  this->jniApi = _jniApi;
+}

+ 43 - 0
test/cases/core/jni/JniApiTest.cpp

@@ -0,0 +1,43 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#include <gtest/gtest.h>
+#include <ls-std/ls-std-core-jni.hpp>
+#include <ls-std/ls-std-core.hpp>
+
+using ls::std::core::IllegalArgumentException;
+using ls::std::core::JniApi;
+using testing::Test;
+
+namespace
+{
+  class JniApiTest : public Test
+  {
+    public:
+
+      JniApiTest() = default;
+      ~JniApiTest() override = default;
+  };
+
+  TEST_F(JniApiTest, constructor)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            JniApi jniApi{nullptr};
+          }
+          catch (const IllegalArgumentException &_exception)
+          {
+            throw;
+          }
+        },
+        IllegalArgumentException);
+  }
+}

+ 62 - 0
test/cases/core/jni/JniClassParameterTest.cpp

@@ -0,0 +1,62 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#include <gtest/gtest.h>
+#include <ls-std-core-jni-test.hpp>
+#include <ls-std/ls-std-core-jni.hpp>
+#include <memory>
+
+using ls::std::core::JniApi;
+using ls::std::core::JniClassParameter;
+using ls::std::core::interface_type::IJniApi;
+using std::make_shared;
+using std::shared_ptr;
+using test::core::jni::MockJniApi;
+using testing::Test;
+
+namespace
+{
+  class JniClassParameterTest : public Test
+  {
+    public:
+
+      JniClassParameterTest() = default;
+      ~JniClassParameterTest() override = default;
+  };
+
+  TEST_F(JniClassParameterTest, getJavaEnvironment)
+  {
+    JniClassParameter parameter{};
+    ASSERT_TRUE(parameter.getJavaEnvironment() == nullptr);
+  }
+
+  TEST_F(JniClassParameterTest, getJniApi)
+  {
+    JniClassParameter parameter{};
+    ASSERT_TRUE(parameter.getJniApi() == nullptr);
+  }
+
+  TEST_F(JniClassParameterTest, setJniApi)
+  {
+    JniClassParameter parameter{};
+    shared_ptr<IJniApi> jniApi = make_shared<MockJniApi>();
+    parameter.setJniApi(jniApi);
+
+    ASSERT_TRUE(parameter.getJniApi() == jniApi);
+  }
+
+  TEST_F(JniClassParameterTest, setJavaEnvironment)
+  {
+    JniClassParameter parameter{};
+    shared_ptr<JNIEnv> environment = make_shared<JNIEnv>();
+    parameter.setJavaEnvironment(environment.get());
+
+    ASSERT_TRUE(parameter.getJavaEnvironment() == environment.get());
+  }
+}

+ 101 - 0
test/cases/core/jni/JniClassTest.cpp

@@ -0,0 +1,101 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <ls-std-core-jni-test.hpp>
+#include <ls-std/ls-std-core-jni.hpp>
+#include <ls-std/ls-std-core.hpp>
+#include <memory>
+
+using ls::std::core::IllegalArgumentException;
+using ls::std::core::JniClass;
+using ls::std::core::JniClassParameter;
+using std::make_shared;
+using std::shared_ptr;
+using std::string;
+using test::core::jni::MockJniApi;
+using testing::AtLeast;
+using testing::Return;
+using testing::Test;
+
+namespace
+{
+  class JniClassTest : public Test
+  {
+    public:
+
+      JniClassTest() = default;
+      ~JniClassTest() override = default;
+  };
+
+  TEST_F(JniClassTest, constructor_no_parameter_reference)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            JniClass javaClass(nullptr, "java.utils.String");
+          }
+          catch (const IllegalArgumentException &_exception)
+          {
+            throw;
+          }
+        },
+        IllegalArgumentException);
+  }
+
+  TEST_F(JniClassTest, constructor_empty_path)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            JniClass javaClass(make_shared<JniClassParameter>(), "");
+          }
+          catch (const IllegalArgumentException &_exception)
+          {
+            throw;
+          }
+        },
+        IllegalArgumentException);
+  }
+
+  TEST_F(JniClassTest, constructor_no_java_environment_reference)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            JniClass javaClass(make_shared<JniClassParameter>(), "java.utils.String");
+          }
+          catch (const IllegalArgumentException &_exception)
+          {
+            throw;
+          }
+        },
+        IllegalArgumentException);
+  }
+
+  TEST_F(JniClassTest, load)
+  {
+    shared_ptr<JniClassParameter> parameter = make_shared<JniClassParameter>();
+    shared_ptr<MockJniApi> mockJniApi = make_shared<MockJniApi>();
+    parameter->setJniApi(mockJniApi);
+    shared_ptr<JNIEnv> environment = make_shared<JNIEnv>();
+    parameter->setJavaEnvironment(environment.get());
+    string classPath = "java.utils.String";
+    JniClass javaClass{parameter, classPath};
+
+    EXPECT_CALL(*mockJniApi, findClass(classPath)).Times(AtLeast(1));
+    ON_CALL(*mockJniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get()));
+
+    ASSERT_TRUE(javaClass.load());
+  }
+}

+ 16 - 0
test/classes/core/jni/MockJniApi.cpp

@@ -0,0 +1,16 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#include "MockJniApi.hpp"
+
+using test::core::jni::MockJniApi;
+
+MockJniApi::MockJniApi() = default;
+
+MockJniApi::~MockJniApi() noexcept = default;

+ 29 - 0
test/classes/core/jni/MockJniApi.hpp

@@ -0,0 +1,29 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#ifndef LS_STD_MOCK_JNI_API_HPP
+#define LS_STD_MOCK_JNI_API_HPP
+
+#include <gmock/gmock.h>
+#include <ls-std/core/interface/IJniApi.hpp>
+
+namespace test::core::jni
+{
+  class MockJniApi : public ls::std::core::interface_type::IJniApi
+  {
+    public:
+
+      MockJniApi();
+      ~MockJniApi() noexcept override;
+
+      MOCK_METHOD(jclass, findClass, (const ::std::string &_classPath), (override));
+  };
+}
+
+#endif

+ 15 - 0
test/ls-std-core-jni-test.hpp

@@ -0,0 +1,15 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-07
+* Changed:         2023-04-07
+*
+* */
+
+#ifndef LS_STD_LS_STD_CORE_JNI_TEST_HPP
+#define LS_STD_LS_STD_CORE_JNI_TEST_HPP
+
+#include <classes/core/jni/MockJniApi.hpp>
+
+#endif