File indexing completed on 2025-02-02 05:02:41
0001 /* 0002 SPDX-FileCopyrightText: 2020-2022 Volker Krause <vkrause@kde.org> 0003 SPDX-License-Identifier: LGPL-2.0-or-later 0004 */ 0005 0006 #ifndef KANDROIDEXTRAS_MOCK_JNIOBJECT_H 0007 #define KANDROIDEXTRAS_MOCK_JNIOBJECT_H 0008 0009 #include "kandroidextras_export.h" 0010 #include "jni.h" 0011 0012 #include "kandroidextras/jnisignature.h" 0013 #include "kandroidextras/jnitypes.h" 0014 0015 #include <QExplicitlySharedDataPointer> 0016 #include <QStringList> 0017 #include <QVariant> 0018 0019 class MockJniObjectBasePrivate; 0020 0021 namespace KAndroidExtras { 0022 namespace Internal { 0023 template <typename T> 0024 constexpr inline const char* argTypeToString() 0025 { 0026 return KAndroidExtras::Jni::signature<T>(); 0027 } 0028 template <> 0029 constexpr inline const char* argTypeToString<jobject>() 0030 { 0031 return "o"; 0032 } 0033 0034 class KANDROIDEXTRAS_EXPORT MockJniObjectBase { 0035 public: 0036 MockJniObjectBase(); 0037 MockJniObjectBase(const MockJniObjectBase&); 0038 ~MockJniObjectBase(); 0039 MockJniObjectBase& operator=(const MockJniObjectBase&); 0040 0041 MockJniObjectBase(const char *className); 0042 0043 inline MockJniObjectBase(const char *className, const char *signature) 0044 : MockJniObjectBase() 0045 { 0046 addToProtocol(QLatin1StringView("ctor: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(signature)); 0047 } 0048 template <typename ...Args> 0049 inline MockJniObjectBase(const char *className, const char *signature, Args...) 0050 : MockJniObjectBase() 0051 { 0052 addToProtocol(QLatin1StringView("ctor: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(signature) 0053 + QLatin1StringView(" (") + (...+QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')')); 0054 } 0055 0056 MockJniObjectBase(jobject object); 0057 0058 bool isValid() const { return true; } 0059 0060 static QStringList m_staticProtocol; 0061 0062 QStringList protocol() const; 0063 void addToProtocol(const QString &line) const; 0064 0065 protected: 0066 QVariant property(const QByteArray &name) const; 0067 void setProperty(const QByteArray &name, const QVariant &value); 0068 QVariant value() const; 0069 void setValue(const QVariant &value); 0070 void setData(jobject object); 0071 0072 void setProtocol(const QStringList &protocol); 0073 QExplicitlySharedDataPointer<MockJniObjectBasePrivate> d; 0074 }; 0075 0076 0077 template <typename JniObjectT> 0078 class MockJniObject : public MockJniObjectBase { 0079 public: 0080 using MockJniObjectBase::MockJniObjectBase; 0081 static inline JniObjectT fromString(const QString &s) 0082 { 0083 JniObjectT o; 0084 o.setValue(s); 0085 return o; 0086 } 0087 static inline JniObjectT fromLocalRef(jobject o) 0088 { 0089 JniObjectT obj; 0090 obj.addToProtocol(QLatin1StringView("ctor: ") + QString::number((qulonglong)o)); 0091 return obj; 0092 } 0093 inline QString toString() const 0094 { 0095 return value().userType() == QMetaType::QString ? value().toString() : protocol().join(QLatin1Char('\n')); 0096 } 0097 0098 inline jobject object() const { return d.data(); } 0099 template <typename T> 0100 inline T object() const { return {}; } 0101 0102 template <typename T, typename ...Args> 0103 inline T callMethod(const char *methodName, const char *signature, Args...) const 0104 { 0105 const QString s = QLatin1StringView("callMethod: ") + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" (") 0106 + (...+QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')'); 0107 addToProtocol(s); 0108 if constexpr (!std::is_same_v<T, void>) { 0109 return {}; 0110 } 0111 } 0112 template <typename T> 0113 inline T callMethod(const char *methodName, const char *signature) const 0114 { 0115 const QString s = QLatin1StringView("callMethod: ") + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" ()"); 0116 addToProtocol(s); 0117 if constexpr (!std::is_same_v<T, void>) { 0118 return {}; 0119 } 0120 } 0121 0122 template <typename ...Args> 0123 inline JniObjectT callObjectMethod(const char *methodName, const char *signature, Args...) const 0124 { 0125 const QString s = QLatin1StringView("callObjectMethod: ") + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" (") 0126 + (...+QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')'); 0127 addToProtocol(s); 0128 0129 JniObjectT obj; 0130 obj.setProtocol(protocol()); 0131 return obj; 0132 } 0133 inline JniObjectT callObjectMethod(const char *methodName, const char *signature) const 0134 { 0135 addToProtocol(QLatin1StringView("callObjectMethod: ") + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" ()")); 0136 0137 JniObjectT obj; 0138 obj.setProtocol(protocol()); 0139 return obj; 0140 } 0141 0142 template <typename T> 0143 inline T getField(const char *fieldName) const 0144 { 0145 addToProtocol(QLatin1StringView("getField: ") + QLatin1StringView(fieldName) + QLatin1Char(' ') + QLatin1StringView(KAndroidExtras::Jni::signature<T>())); 0146 return property(fieldName).template value<T>(); 0147 } 0148 0149 inline JniObjectT getObjectField(const char *fieldName, const char *signature) const 0150 { 0151 addToProtocol(QLatin1StringView("getObjectField: ") + QLatin1StringView(fieldName) + QLatin1Char(' ') + QLatin1StringView(signature)); 0152 return property(fieldName).template value<JniObjectT>(); 0153 } 0154 0155 template <typename T> 0156 inline void setField(const char *fieldName, const char *signature, T value) 0157 { 0158 Q_UNUSED(value); 0159 addToProtocol(QLatin1StringView("setField: ") + QLatin1StringView(fieldName) + QLatin1Char(' ') + QLatin1StringView(signature)); 0160 if constexpr (std::is_same_v<jobject, T>) { 0161 setObjectProperty(fieldName, value); 0162 } else { 0163 setProperty(fieldName, QVariant::fromValue(value)); 0164 } 0165 } 0166 template <typename T> 0167 inline void setField(const char *fieldName, T value) 0168 { 0169 setField(fieldName, KAndroidExtras::Jni::signature<T>(), value); 0170 } 0171 0172 template <typename T, typename ...Args> 0173 static inline T callStaticMethod(const char *className, const char *methodName, const char *signature, Args...) 0174 { 0175 const QString s = QLatin1StringView("callStaticMethod: ") + QLatin1StringView(className) + QLatin1Char(' ') 0176 + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" (") 0177 + (...+QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')'); 0178 m_staticProtocol.push_back(s); 0179 if constexpr (!std::is_same_v<T, void>) { 0180 return {}; 0181 } 0182 } 0183 template <typename T> 0184 static inline T callStaticMethod(const char *className, const char *methodName, const char *signature) 0185 { 0186 const QString s = QLatin1StringView("callStaticMethod: ") + QLatin1StringView(className) + QLatin1Char(' ') 0187 + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" ()"); 0188 m_staticProtocol.push_back(s); 0189 if constexpr (!std::is_same_v<T, void>) { 0190 return {}; 0191 } 0192 } 0193 0194 template <typename ...Args> 0195 static inline JniObjectT callStaticObjectMethod(const char *className, const char *methodName, const char *signature, Args...) 0196 { 0197 const QString s = QLatin1StringView("callStaticObjectMethod: ") + QLatin1StringView(className) + QLatin1Char(' ') 0198 + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" (") 0199 + (...+QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')'); 0200 JniObjectT obj; 0201 obj.addToProtocol(s); 0202 return obj; 0203 } 0204 0205 static inline JniObjectT callStaticObjectMethod(const char *className, const char *methodName, const char *signature) 0206 { 0207 JniObjectT obj; 0208 obj.addToProtocol(QLatin1StringView("callStaticObjectMethod: ") + QLatin1StringView(className) + QLatin1Char(' ') 0209 + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" ()")); 0210 return obj; 0211 } 0212 0213 static inline JniObjectT getStaticObjectField(const char *className, const char *fieldName, const char *signature) 0214 { 0215 m_staticProtocol.push_back(QLatin1StringView("getStaticObjectField: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(fieldName) + QLatin1Char(' ') + QLatin1StringView(signature)); 0216 return {}; 0217 } 0218 0219 template <typename T> 0220 static inline JniObjectT getStaticObjectField(const char *className, const char *fieldName) 0221 { 0222 m_staticProtocol.push_back(QLatin1StringView("getStaticObjectField<>: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(fieldName)); 0223 return {}; 0224 } 0225 0226 template <typename T> 0227 static inline T getStaticField(const char *className, const char *fieldName) 0228 { 0229 m_staticProtocol.push_back(QLatin1StringView("getStaticField<>: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(fieldName) + QLatin1Char(' ') + QLatin1StringView(KAndroidExtras::Jni::signature<T>())); 0230 return {}; 0231 } 0232 0233 inline void setObjectProperty(const QByteArray &name, jobject value) 0234 { 0235 JniObjectT o; 0236 o.setData(value); 0237 setProperty(name, QVariant::fromValue(o)); 0238 } 0239 }; 0240 0241 } 0242 } 0243 0244 #endif