xref: /aosp_15_r20/libnativehelper/tests/libnativehelper_test.cpp (revision 0797b24ee566c78eb48500180cb4bf71f81c8aab)
1 /*
2  * Copyright (C) 2024 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 #include <jni.h>
18 
19 #include <memory>
20 
21 #include "android-base/logging.h"
22 #include "gtest/gtest.h"
23 #include "nativehelper/scoped_local_ref.h"
24 #include "nativehelper/scoped_utf_chars.h"
25 #include "nativehelper/utils.h"
26 #include "nativetesthelper_jni/utils.h"
27 
28 class LibnativehelperTest : public ::testing::Test {
29    protected:
SetUp()30     virtual void SetUp() override {
31         int result = GetJavaVM()->GetEnv(reinterpret_cast<void**>(&mEnv), JNI_VERSION_1_6);
32         CHECK_EQ(JNI_OK, result);
33         CHECK_NE(nullptr, mEnv);
34     }
35 
TearDown()36     virtual void TearDown() override { mEnv = nullptr; }
37 
38     JNIEnv* mEnv;
39 };
40 
TEST_F(LibnativehelperTest,GetUtfOrReturn)41 TEST_F(LibnativehelperTest, GetUtfOrReturn) {
42     ScopedLocalRef<jstring> j_str(mEnv, mEnv->NewStringUTF("foo"));
43     std::unique_ptr<ScopedUtfChars> result;
44 
45     jint ret = [&](JNIEnv* env) -> jint {
46         ScopedUtfChars str = GET_UTF_OR_RETURN(env, j_str.get());
47         result.reset(new ScopedUtfChars(std::move(str)));
48         return 1;
49     }(mEnv);
50 
51     EXPECT_EQ(result->c_str(), std::string_view("foo"));
52     EXPECT_FALSE(mEnv->ExceptionCheck());
53     EXPECT_EQ(ret, 1);
54 }
55 
TEST_F(LibnativehelperTest,GetUtfOrReturnVoid)56 TEST_F(LibnativehelperTest, GetUtfOrReturnVoid) {
57     ScopedLocalRef<jstring> j_str(mEnv, mEnv->NewStringUTF("foo"));
58     std::unique_ptr<ScopedUtfChars> result;
59 
60     [&](JNIEnv* env) -> void {
61         ScopedUtfChars str = GET_UTF_OR_RETURN_VOID(env, j_str.get());
62         result.reset(new ScopedUtfChars(std::move(str)));
63     }(mEnv);
64 
65     EXPECT_EQ(result->c_str(), std::string_view("foo"));
66     EXPECT_FALSE(mEnv->ExceptionCheck());
67 }
68 
TEST_F(LibnativehelperTest,GetUtfOrReturnFailed)69 TEST_F(LibnativehelperTest, GetUtfOrReturnFailed) {
70     jint ret = [&](JNIEnv* env) -> jint {
71         ScopedUtfChars str = GET_UTF_OR_RETURN(env, nullptr);
72         return 1;
73     }(mEnv);
74 
75     EXPECT_TRUE(mEnv->ExceptionCheck());
76     EXPECT_EQ(ret, 0);
77 
78     mEnv->ExceptionClear();
79 }
80 
TEST_F(LibnativehelperTest,GetUtfOrReturnVoidFailed)81 TEST_F(LibnativehelperTest, GetUtfOrReturnVoidFailed) {
82     bool execution_completed = false;
83 
84     [&](JNIEnv* env) -> void {
85         ScopedUtfChars str = GET_UTF_OR_RETURN_VOID(env, nullptr);
86         execution_completed = true;
87     }(mEnv);
88 
89     EXPECT_TRUE(mEnv->ExceptionCheck());
90     EXPECT_FALSE(execution_completed);
91 
92     mEnv->ExceptionClear();
93 }
94 
TEST_F(LibnativehelperTest,CreateUtfOrReturn)95 TEST_F(LibnativehelperTest, CreateUtfOrReturn) {
96     std::unique_ptr<ScopedLocalRef<jstring>> result;
97 
98     jint ret = [&](JNIEnv* env) -> jint {
99         ScopedLocalRef<jstring> j_str = CREATE_UTF_OR_RETURN(env, "foo");
100         result.reset(new ScopedLocalRef<jstring>(std::move(j_str)));
101         return 1;
102     }(mEnv);
103 
104     ScopedUtfChars str(mEnv, result->get());
105     EXPECT_EQ(str.c_str(), std::string_view("foo"));
106     EXPECT_FALSE(mEnv->ExceptionCheck());
107     EXPECT_EQ(ret, 1);
108 }
109 
110 class MyString : public std::string {
111    public:
MyString(const char * c_str)112     explicit MyString(const char* c_str) : std::string(c_str) {}
113 
114     // Force clear the string to catch use-after-free issues.
~MyString()115     ~MyString() { clear(); }
116 };
117 
118 // `expr` creates a temporary object and evaluates to it.
TEST_F(LibnativehelperTest,CreateUtfOrReturnExprEvaluatesToTemporary)119 TEST_F(LibnativehelperTest, CreateUtfOrReturnExprEvaluatesToTemporary) {
120     std::unique_ptr<ScopedLocalRef<jstring>> result;
121 
122     jint ret = [&](JNIEnv* env) -> jint {
123         ScopedLocalRef<jstring> j_str = CREATE_UTF_OR_RETURN(env, MyString("foo"));
124         result.reset(new ScopedLocalRef<jstring>(std::move(j_str)));
125         return 1;
126     }(mEnv);
127 
128     ScopedUtfChars str(mEnv, result->get());
129     EXPECT_EQ(str.c_str(), std::string_view("foo"));
130     EXPECT_FALSE(mEnv->ExceptionCheck());
131     EXPECT_EQ(ret, 1);
132 }
133 
134 // `expr` creates a temporary object and evaluates to something else backed by it.
TEST_F(LibnativehelperTest,CreateUtfOrReturnExprEvaluatesToValueBackedByTemporary)135 TEST_F(LibnativehelperTest, CreateUtfOrReturnExprEvaluatesToValueBackedByTemporary) {
136     std::unique_ptr<ScopedLocalRef<jstring>> result;
137 
138     jint ret = [&](JNIEnv* env) -> jint {
139         ScopedLocalRef<jstring> j_str = CREATE_UTF_OR_RETURN(env, MyString("foo").c_str());
140         result.reset(new ScopedLocalRef<jstring>(std::move(j_str)));
141         return 1;
142     }(mEnv);
143 
144     ScopedUtfChars str(mEnv, result->get());
145     EXPECT_EQ(str.c_str(), std::string_view("foo"));
146     EXPECT_FALSE(mEnv->ExceptionCheck());
147     EXPECT_EQ(ret, 1);
148 }
149 
TEST_F(LibnativehelperTest,CreateUtfOrReturnVoid)150 TEST_F(LibnativehelperTest, CreateUtfOrReturnVoid) {
151     std::unique_ptr<ScopedLocalRef<jstring>> result;
152 
153     [&](JNIEnv* env) -> void {
154         ScopedLocalRef<jstring> j_str = CREATE_UTF_OR_RETURN_VOID(env, "foo");
155         result.reset(new ScopedLocalRef<jstring>(std::move(j_str)));
156     }(mEnv);
157 
158     ScopedUtfChars str(mEnv, result->get());
159     EXPECT_EQ(str.c_str(), std::string_view("foo"));
160     EXPECT_FALSE(mEnv->ExceptionCheck());
161 }
162 
TEST_F(LibnativehelperTest,CreateUtfOrReturnFailed)163 TEST_F(LibnativehelperTest, CreateUtfOrReturnFailed) {
164     JNINativeInterface interface;
165     interface.NewStringUTF = [](JNIEnv*, const char*) -> jstring { return nullptr; };
166     JNIEnv fake_env;
167     fake_env.functions = &interface;
168 
169     jint ret = [&](JNIEnv* env) -> jint {
170         ScopedLocalRef<jstring> j_str = CREATE_UTF_OR_RETURN(env, "foo");
171         return 1;
172     }(&fake_env);
173 
174     EXPECT_EQ(ret, 0);
175 }
176 
TEST_F(LibnativehelperTest,CreateUtfOrReturnVoidFailed)177 TEST_F(LibnativehelperTest, CreateUtfOrReturnVoidFailed) {
178     JNINativeInterface interface;
179     interface.NewStringUTF = [](JNIEnv*, const char*) -> jstring { return nullptr; };
180     JNIEnv fake_env;
181     fake_env.functions = &interface;
182 
183     bool execution_completed = false;
184 
185     [&](JNIEnv* env) -> void {
186         ScopedLocalRef<jstring> j_str = CREATE_UTF_OR_RETURN_VOID(env, "foo");
187         execution_completed = true;
188     }(&fake_env);
189 
190     EXPECT_FALSE(execution_completed);
191 }
192