123 lines
3.7 KiB
C++
123 lines
3.7 KiB
C++
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#include "base/android/scoped_java_ref.h"
|
||
|
|
||
|
#include "base/android/jni_android.h"
|
||
|
#include "base/android/jni_string.h"
|
||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||
|
|
||
|
namespace base {
|
||
|
namespace android {
|
||
|
|
||
|
namespace {
|
||
|
int g_local_refs = 0;
|
||
|
int g_global_refs = 0;
|
||
|
|
||
|
const JNINativeInterface* g_previous_functions;
|
||
|
|
||
|
jobject NewGlobalRef(JNIEnv* env, jobject obj) {
|
||
|
++g_global_refs;
|
||
|
return g_previous_functions->NewGlobalRef(env, obj);
|
||
|
}
|
||
|
|
||
|
void DeleteGlobalRef(JNIEnv* env, jobject obj) {
|
||
|
--g_global_refs;
|
||
|
return g_previous_functions->DeleteGlobalRef(env, obj);
|
||
|
}
|
||
|
|
||
|
jobject NewLocalRef(JNIEnv* env, jobject obj) {
|
||
|
++g_local_refs;
|
||
|
return g_previous_functions->NewLocalRef(env, obj);
|
||
|
}
|
||
|
|
||
|
void DeleteLocalRef(JNIEnv* env, jobject obj) {
|
||
|
--g_local_refs;
|
||
|
return g_previous_functions->DeleteLocalRef(env, obj);
|
||
|
}
|
||
|
} // namespace
|
||
|
|
||
|
class ScopedJavaRefTest : public testing::Test {
|
||
|
protected:
|
||
|
virtual void SetUp() {
|
||
|
g_local_refs = 0;
|
||
|
g_global_refs = 0;
|
||
|
JNIEnv* env = AttachCurrentThread();
|
||
|
g_previous_functions = env->functions;
|
||
|
hooked_functions = *g_previous_functions;
|
||
|
env->functions = &hooked_functions;
|
||
|
// We inject our own functions in JNINativeInterface so we can keep track
|
||
|
// of the reference counting ourselves.
|
||
|
hooked_functions.NewGlobalRef = &NewGlobalRef;
|
||
|
hooked_functions.DeleteGlobalRef = &DeleteGlobalRef;
|
||
|
hooked_functions.NewLocalRef = &NewLocalRef;
|
||
|
hooked_functions.DeleteLocalRef = &DeleteLocalRef;
|
||
|
}
|
||
|
|
||
|
virtual void TearDown() {
|
||
|
JNIEnv* env = AttachCurrentThread();
|
||
|
env->functions = g_previous_functions;
|
||
|
}
|
||
|
// From JellyBean release, the instance of this struct provided in JNIEnv is
|
||
|
// read-only, so we deep copy it to allow individual functions to be hooked.
|
||
|
JNINativeInterface hooked_functions;
|
||
|
};
|
||
|
|
||
|
// The main purpose of this is testing the various conversions compile.
|
||
|
TEST_F(ScopedJavaRefTest, Conversions) {
|
||
|
JNIEnv* env = AttachCurrentThread();
|
||
|
ScopedJavaLocalRef<jstring> str = ConvertUTF8ToJavaString(env, "string");
|
||
|
ScopedJavaGlobalRef<jstring> global(str);
|
||
|
{
|
||
|
ScopedJavaGlobalRef<jobject> global_obj(str);
|
||
|
ScopedJavaLocalRef<jobject> local_obj(global);
|
||
|
const JavaRef<jobject>& obj_ref1(str);
|
||
|
const JavaRef<jobject>& obj_ref2(global);
|
||
|
EXPECT_TRUE(env->IsSameObject(obj_ref1.obj(), obj_ref2.obj()));
|
||
|
EXPECT_TRUE(env->IsSameObject(global_obj.obj(), obj_ref2.obj()));
|
||
|
}
|
||
|
global.Reset(str);
|
||
|
const JavaRef<jstring>& str_ref = str;
|
||
|
EXPECT_EQ("string", ConvertJavaStringToUTF8(str_ref));
|
||
|
str.Reset();
|
||
|
}
|
||
|
|
||
|
TEST_F(ScopedJavaRefTest, RefCounts) {
|
||
|
JNIEnv* env = AttachCurrentThread();
|
||
|
ScopedJavaLocalRef<jstring> str;
|
||
|
// The ConvertJavaStringToUTF8 below creates a new string that would normally
|
||
|
// return a local ref. We simulate that by starting the g_local_refs count at
|
||
|
// 1.
|
||
|
g_local_refs = 1;
|
||
|
str.Reset(ConvertUTF8ToJavaString(env, "string"));
|
||
|
EXPECT_EQ(1, g_local_refs);
|
||
|
EXPECT_EQ(0, g_global_refs);
|
||
|
{
|
||
|
ScopedJavaGlobalRef<jstring> global_str(str);
|
||
|
ScopedJavaGlobalRef<jobject> global_obj(global_str);
|
||
|
EXPECT_EQ(1, g_local_refs);
|
||
|
EXPECT_EQ(2, g_global_refs);
|
||
|
|
||
|
ScopedJavaLocalRef<jstring> str2(env, str.Release());
|
||
|
EXPECT_EQ(1, g_local_refs);
|
||
|
{
|
||
|
ScopedJavaLocalRef<jstring> str3(str2);
|
||
|
EXPECT_EQ(2, g_local_refs);
|
||
|
}
|
||
|
EXPECT_EQ(1, g_local_refs);
|
||
|
str2.Reset();
|
||
|
EXPECT_EQ(0, g_local_refs);
|
||
|
global_str.Reset();
|
||
|
EXPECT_EQ(1, g_global_refs);
|
||
|
ScopedJavaGlobalRef<jobject> global_obj2(global_obj);
|
||
|
EXPECT_EQ(2, g_global_refs);
|
||
|
}
|
||
|
|
||
|
EXPECT_EQ(0, g_local_refs);
|
||
|
EXPECT_EQ(0, g_global_refs);
|
||
|
}
|
||
|
|
||
|
} // namespace android
|
||
|
} // namespace base
|