1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_LIBNATIVELOADER_NATIVE_LOADER_TEST_H_
18 #define ART_LIBNATIVELOADER_NATIVE_LOADER_TEST_H_
19 
20 #include <string.h>
21 
22 #include <memory>
23 
24 #include "gmock/gmock.h"
25 #include "jni.h"
26 
27 namespace android {
28 namespace nativeloader {
29 
30 class MockJni {
31  public:
~MockJni()32   virtual ~MockJni() {}
33   MOCK_METHOD1(JniObject_getParent, const char*(const char*));
34 };
35 
36 static std::unique_ptr<MockJni> jni_mock;
37 
38 // A very simple JNI mock.
39 // jstring is a pointer to utf8 char array. We don't need utf16 char here.
40 // jobject, jclass, and jmethodID are also a pointer to utf8 char array
41 // Only a few JNI methods that are actually used in libnativeloader are mocked.
CreateJNINativeInterface()42 JNINativeInterface* CreateJNINativeInterface() {
43   JNINativeInterface* inf = new JNINativeInterface();
44   memset(inf, 0, sizeof(JNINativeInterface));
45 
46   inf->GetStringUTFChars = [](JNIEnv*, jstring s, jboolean*) -> const char* {
47     return reinterpret_cast<const char*>(s);
48   };
49 
50   inf->ReleaseStringUTFChars = [](JNIEnv*, jstring, const char*) -> void { return; };
51 
52   inf->NewStringUTF = [](JNIEnv*, const char* bytes) -> jstring {
53     return reinterpret_cast<jstring>(const_cast<char*>(bytes));
54   };
55 
56   inf->FindClass = [](JNIEnv*, const char* name) -> jclass {
57     return reinterpret_cast<jclass>(const_cast<char*>(name));
58   };
59 
60   inf->CallObjectMethodV = [](JNIEnv*, jobject obj, jmethodID mid, va_list) -> jobject {
61     if (strcmp("getParent", reinterpret_cast<const char*>(mid)) == 0) {
62       // JniObject_getParent can be a valid jobject or nullptr if there is
63       // no parent classloader.
64       const char* ret = jni_mock->JniObject_getParent(reinterpret_cast<const char*>(obj));
65       return reinterpret_cast<jobject>(const_cast<char*>(ret));
66     }
67     return nullptr;
68   };
69 
70   inf->GetMethodID = [](JNIEnv*, jclass, const char* name, const char*) -> jmethodID {
71     return reinterpret_cast<jmethodID>(const_cast<char*>(name));
72   };
73 
74   inf->NewWeakGlobalRef = [](JNIEnv*, jobject obj) -> jobject { return obj; };
75 
76   inf->IsSameObject = [](JNIEnv*, jobject a, jobject b) -> jboolean {
77     return strcmp(reinterpret_cast<const char*>(a), reinterpret_cast<const char*>(b)) == 0;
78   };
79 
80   return inf;
81 }
82 
83 }  // namespace nativeloader
84 }  // namespace android
85 
86 #endif  // ART_LIBNATIVELOADER_NATIVE_LOADER_TEST_H_
87