1 /*
2  * Copyright (C) 2011 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_internal.h"
18 
19 #include <pthread.h>
20 
21 #include "common_runtime_test.h"
22 #include "java_vm_ext.h"
23 #include "runtime.h"
24 
25 namespace art {
26 
27 class JavaVmExtTest : public CommonRuntimeTest {
28  protected:
SetUp()29   virtual void SetUp() {
30     CommonRuntimeTest::SetUp();
31 
32     vm_ = Runtime::Current()->GetJavaVM();
33   }
34 
35 
TearDown()36   virtual void TearDown() OVERRIDE {
37     CommonRuntimeTest::TearDown();
38   }
39 
40   JavaVMExt* vm_;
41 };
42 
TEST_F(JavaVmExtTest,JNI_GetDefaultJavaVMInitArgs)43 TEST_F(JavaVmExtTest, JNI_GetDefaultJavaVMInitArgs) {
44   jint err = JNI_GetDefaultJavaVMInitArgs(nullptr);
45   EXPECT_EQ(JNI_ERR, err);
46 }
47 
TEST_F(JavaVmExtTest,JNI_GetCreatedJavaVMs)48 TEST_F(JavaVmExtTest, JNI_GetCreatedJavaVMs) {
49   JavaVM* vms_buf[1];
50   jsize num_vms;
51   jint ok = JNI_GetCreatedJavaVMs(vms_buf, arraysize(vms_buf), &num_vms);
52   EXPECT_EQ(JNI_OK, ok);
53   EXPECT_EQ(1, num_vms);
54   EXPECT_EQ(vms_buf[0], vm_);
55 }
56 
57 static bool gSmallStack = false;
58 static bool gAsDaemon = false;
59 
attach_current_thread_callback(void * arg ATTRIBUTE_UNUSED)60 static void* attach_current_thread_callback(void* arg ATTRIBUTE_UNUSED) {
61   JavaVM* vms_buf[1];
62   jsize num_vms;
63   JNIEnv* env;
64   jint ok = JNI_GetCreatedJavaVMs(vms_buf, arraysize(vms_buf), &num_vms);
65   EXPECT_EQ(JNI_OK, ok);
66   if (ok == JNI_OK) {
67     if (!gAsDaemon) {
68       ok = vms_buf[0]->AttachCurrentThread(&env, nullptr);
69     } else {
70       ok = vms_buf[0]->AttachCurrentThreadAsDaemon(&env, nullptr);
71     }
72     // TODO: Find a way to test with exact SMALL_STACK value, for which we would bail. The pthreads
73     //       spec says that the stack size argument is a lower bound, and bionic currently gives us
74     //       a chunk more on arm64.
75     if (!gSmallStack) {
76       EXPECT_EQ(JNI_OK, ok);
77     }
78     if (ok == JNI_OK) {
79       ok = vms_buf[0]->DetachCurrentThread();
80       EXPECT_EQ(JNI_OK, ok);
81     }
82   }
83   return nullptr;
84 }
85 
TEST_F(JavaVmExtTest,AttachCurrentThread)86 TEST_F(JavaVmExtTest, AttachCurrentThread) {
87   pthread_t pthread;
88   const char* reason = __PRETTY_FUNCTION__;
89   gSmallStack = false;
90   gAsDaemon = false;
91   CHECK_PTHREAD_CALL(pthread_create, (&pthread, nullptr, attach_current_thread_callback,
92       nullptr), reason);
93   void* ret_val;
94   CHECK_PTHREAD_CALL(pthread_join, (pthread, &ret_val), reason);
95   EXPECT_EQ(ret_val, nullptr);
96 }
97 
TEST_F(JavaVmExtTest,AttachCurrentThreadAsDaemon)98 TEST_F(JavaVmExtTest, AttachCurrentThreadAsDaemon) {
99   pthread_t pthread;
100   const char* reason = __PRETTY_FUNCTION__;
101   gSmallStack = false;
102   gAsDaemon = true;
103   CHECK_PTHREAD_CALL(pthread_create, (&pthread, nullptr, attach_current_thread_callback,
104       nullptr), reason);
105   void* ret_val;
106   CHECK_PTHREAD_CALL(pthread_join, (pthread, &ret_val), reason);
107   EXPECT_EQ(ret_val, nullptr);
108 }
109 
TEST_F(JavaVmExtTest,AttachCurrentThread_SmallStack)110 TEST_F(JavaVmExtTest, AttachCurrentThread_SmallStack) {
111   pthread_t pthread;
112   pthread_attr_t attr;
113   const char* reason = __PRETTY_FUNCTION__;
114   gSmallStack = true;
115   gAsDaemon = false;
116   CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
117   CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, PTHREAD_STACK_MIN), reason);
118   CHECK_PTHREAD_CALL(pthread_create, (&pthread, &attr, attach_current_thread_callback,
119       nullptr), reason);
120   CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
121   void* ret_val;
122   CHECK_PTHREAD_CALL(pthread_join, (pthread, &ret_val), reason);
123   EXPECT_EQ(ret_val, nullptr);
124 }
125 
TEST_F(JavaVmExtTest,DetachCurrentThread)126 TEST_F(JavaVmExtTest, DetachCurrentThread) {
127   JNIEnv* env;
128   jint ok = vm_->AttachCurrentThread(&env, nullptr);
129   ASSERT_EQ(JNI_OK, ok);
130   ok = vm_->DetachCurrentThread();
131   EXPECT_EQ(JNI_OK, ok);
132 
133   jint err = vm_->DetachCurrentThread();
134   EXPECT_EQ(JNI_ERR, err);
135 }
136 
137 }  // namespace art
138