/* * Author: Patrick-Christopher Mattulat * Company: Lynar Studios * E-Mail: webmaster@lynarstudios.com * Created: 2023-04-07 * Changed: 2023-04-11 * * */ #include #include #include #include #include #include using ls::std::core::IllegalArgumentException; using ls::std::core::NullPointerException; using ls::std::core::experimental::JniClass; using ls::std::core::experimental::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; JniClass createJniClass(const string &_classPath) { shared_ptr parameter = make_shared(); this->jniApi = make_shared(); parameter->setJniApi(this->jniApi); shared_ptr environment = make_shared(); parameter->setJavaEnvironment(environment.get()); return JniClass{parameter, _classPath}; } shared_ptr jniApi{}; }; TEST_F(JniClassTest, constructor_no_parameter_reference) { EXPECT_THROW( { try { JniClass javaClass(nullptr, "java.utils.String"); } catch (const IllegalArgumentException &_exception) { string expected = _exception.getName() + " thrown - no provided reference to JNI class parameter!"; string actual = _exception.what(); ASSERT_STREQ(expected.c_str(), actual.c_str()); throw; } }, IllegalArgumentException); } TEST_F(JniClassTest, constructor_empty_path) { EXPECT_THROW( { try { JniClass javaClass(make_shared(), ""); } catch (const IllegalArgumentException &_exception) { string expected = _exception.getName() + " thrown - path to associated Java class is empty!"; string actual = _exception.what(); ASSERT_STREQ(expected.c_str(), actual.c_str()); throw; } }, IllegalArgumentException); } TEST_F(JniClassTest, constructor_no_java_environment_reference) { EXPECT_THROW( { try { JniClass javaClass(make_shared(), "java.utils.String"); } catch (const IllegalArgumentException &_exception) { string expected = _exception.getName() + " thrown - Java environment is not being provided!"; string actual = _exception.what(); ASSERT_STREQ(expected.c_str(), actual.c_str()); throw; } }, IllegalArgumentException); } TEST_F(JniClassTest, callMethod_boolean_return_value) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "isBlue"; string methodSignature = "()Z"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); EXPECT_CALL(*this->jniApi, callBooleanMethod(testing::_, methodId)).Times(AtLeast(1)); ON_CALL(*this->jniApi, callBooleanMethod(testing::_, methodId)).WillByDefault(Return(true)); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); ASSERT_TRUE(javaClass.callMethod(methodIdentifier).getBooleanValue()); } TEST_F(JniClassTest, callMethod_byte_return_value) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "getDay"; string methodSignature = "()B"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); EXPECT_CALL(*this->jniApi, callByteMethod(testing::_, methodId)).Times(AtLeast(1)); ON_CALL(*this->jniApi, callByteMethod(testing::_, methodId)).WillByDefault(Return(22)); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); ASSERT_EQ(22, javaClass.callMethod(methodIdentifier).getByteValue()); } TEST_F(JniClassTest, callMethod_char_return_value) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "getLetter"; string methodSignature = "()C"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); EXPECT_CALL(*this->jniApi, callCharMethod(testing::_, methodId)).Times(AtLeast(1)); ON_CALL(*this->jniApi, callCharMethod(testing::_, methodId)).WillByDefault(Return('P')); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); ASSERT_EQ('P', javaClass.callMethod(methodIdentifier).getCharValue()); } TEST_F(JniClassTest, callMethod_double_return_value) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "getPi"; string methodSignature = "()D"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); EXPECT_CALL(*this->jniApi, callDoubleMethod(testing::_, methodId)).Times(AtLeast(1)); ON_CALL(*this->jniApi, callDoubleMethod(testing::_, methodId)).WillByDefault(Return(3.14159265l)); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); ASSERT_DOUBLE_EQ(3.14159265l, javaClass.callMethod(methodIdentifier).getDoubleValue()); } TEST_F(JniClassTest, callMethod_float_return_value) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "getPi"; string methodSignature = "()F"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); EXPECT_CALL(*this->jniApi, callFloatMethod(testing::_, methodId)).Times(AtLeast(1)); ON_CALL(*this->jniApi, callFloatMethod(testing::_, methodId)).WillByDefault(Return(3.14159f)); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); ASSERT_FLOAT_EQ(3.14159f, javaClass.callMethod(methodIdentifier).getFloatValue()); } TEST_F(JniClassTest, callMethod_integer_return_value) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "getYear"; string methodSignature = "()I"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); EXPECT_CALL(*this->jniApi, callIntMethod(testing::_, methodId)).Times(AtLeast(1)); ON_CALL(*this->jniApi, callIntMethod(testing::_, methodId)).WillByDefault(Return(1989)); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); ASSERT_EQ(1989, javaClass.callMethod(methodIdentifier).getIntegerValue()); } TEST_F(JniClassTest, callMethod_long_return_value) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "getAmountOfMoney"; string methodSignature = "()J"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); EXPECT_CALL(*this->jniApi, callLongMethod(testing::_, methodId)).Times(AtLeast(1)); ON_CALL(*this->jniApi, callLongMethod(testing::_, methodId)).WillByDefault(Return(18837828981)); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); ASSERT_EQ(18837828981, javaClass.callMethod(methodIdentifier).getLongValue()); } TEST_F(JniClassTest, callMethod_short_return_value) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "getDay"; string methodSignature = "()S"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); EXPECT_CALL(*this->jniApi, callShortMethod(testing::_, methodId)).Times(AtLeast(1)); ON_CALL(*this->jniApi, callShortMethod(testing::_, methodId)).WillByDefault(Return(55)); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); ASSERT_EQ(55, javaClass.callMethod(methodIdentifier).getShortValue()); } TEST_F(JniClassTest, hasMethod) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); ASSERT_FALSE(javaClass.hasMethod("getDay")); } TEST_F(JniClassTest, load) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); ASSERT_TRUE(javaClass.load()); } TEST_F(JniClassTest, loadMethod) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "getDay"; string methodSignature = "()B"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); } TEST_F(JniClassTest, loadMethod_repeat) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1)); ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get())); string methodIdentifier = "getDay"; string methodSignature = "()B"; EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1)); jmethodID methodId = (jmethodID) make_shared().get(); ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId)); ASSERT_TRUE(javaClass.load()); ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature)); ASSERT_FALSE(javaClass.loadMethod(methodIdentifier, methodSignature)); } TEST_F(JniClassTest, loadMethod_without_previous_class_load) { string classPath = "java.utils.String"; JniClass javaClass = this->createJniClass(classPath); string methodIdentifier = "getDay"; string methodSignature = "()B"; EXPECT_THROW( { try { javaClass.loadMethod(methodIdentifier, methodSignature); } catch (const NullPointerException &_exception) { string expected = _exception.getName() + " thrown - no Java class reference available for loading class method!"; string actual = _exception.what(); ASSERT_STREQ(expected.c_str(), actual.c_str()); throw; } }, NullPointerException); } }