handle_scope_test.cc revision e8a3c576301fd531d5f73a65fc8b84a63619d580
1/*
2 * Copyright (C) 2014 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 "base/enums.h"
18#include "common_runtime_test.h"
19#include "gtest/gtest.h"
20#include "handle_scope-inl.h"
21#include "scoped_thread_state_change-inl.h"
22#include "thread.h"
23
24namespace art {
25
26class HandleScopeTest : public CommonRuntimeTest {};
27
28// Test the offsets computed for members of HandleScope. Because of cross-compiling
29// it is impossible the use OFFSETOF_MEMBER, so we do some reasonable computations ourselves. This
30// test checks whether we do the right thing.
31TEST_F(HandleScopeTest, Offsets) {
32  ScopedObjectAccess soa(Thread::Current());
33  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
34  // As the members of HandleScope are private, we cannot use OFFSETOF_MEMBER
35  // here. So do the inverse: set some data, and access it through pointers created from the offsets.
36  StackHandleScope<0x1> hs0(soa.Self());
37  static const size_t kNumReferences = 0x9ABC;
38  StackHandleScope<kNumReferences> test_table(soa.Self());
39  ObjPtr<mirror::Class> c = class_linker->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
40  test_table.SetReference(0, c.Ptr());
41
42  uint8_t* table_base_ptr = reinterpret_cast<uint8_t*>(&test_table);
43
44  {
45    BaseHandleScope** link_ptr = reinterpret_cast<BaseHandleScope**>(table_base_ptr +
46        HandleScope::LinkOffset(kRuntimePointerSize));
47    EXPECT_EQ(*link_ptr, &hs0);
48  }
49
50  {
51    uint32_t* num_ptr = reinterpret_cast<uint32_t*>(table_base_ptr +
52        HandleScope::NumberOfReferencesOffset(kRuntimePointerSize));
53    EXPECT_EQ(*num_ptr, static_cast<size_t>(kNumReferences));
54  }
55
56  {
57    auto* ref_ptr = reinterpret_cast<StackReference<mirror::Object>*>(table_base_ptr +
58        HandleScope::ReferencesOffset(kRuntimePointerSize));
59    EXPECT_OBJ_PTR_EQ(ref_ptr->AsMirrorPtr(), c);
60  }
61}
62
63class CollectVisitor {
64 public:
65  void VisitRootIfNonNull(StackReference<mirror::Object>* ref) {
66    if (!ref->IsNull()) {
67      visited.insert(ref);
68    }
69    ++total_visited;
70  }
71
72  std::set<StackReference<mirror::Object>*> visited;
73  size_t total_visited = 0;  // including null.
74};
75
76// Test functionality of variable sized handle scopes.
77TEST_F(HandleScopeTest, VariableSized) {
78  ScopedObjectAccess soa(Thread::Current());
79  VariableSizedHandleScope hs(soa.Self());
80  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
81  Handle<mirror::Class> c =
82      hs.NewHandle(class_linker->FindSystemClass(soa.Self(), "Ljava/lang/Object;"));
83  // Test nested scopes.
84  StackHandleScope<1> inner(soa.Self());
85  inner.NewHandle(c->AllocObject(soa.Self()));
86  // Add a bunch of handles and make sure callbacks work.
87  static const size_t kNumHandles = 100;
88  std::vector<Handle<mirror::Object>> handles;
89  for (size_t i = 0; i < kNumHandles; ++i) {
90    BaseHandleScope* base = &hs;
91    ObjPtr<mirror::Object> o = c->AllocObject(soa.Self());
92    handles.push_back(hs.NewHandle(o));
93    EXPECT_OBJ_PTR_EQ(o, handles.back().Get());
94    EXPECT_TRUE(hs.Contains(handles.back().GetReference()));
95    EXPECT_TRUE(base->Contains(handles.back().GetReference()));
96    EXPECT_EQ(hs.NumberOfReferences(), base->NumberOfReferences());
97  }
98  CollectVisitor visitor;
99  BaseHandleScope* base = &hs;
100  base->VisitRoots(visitor);
101  EXPECT_LE(visitor.visited.size(), base->NumberOfReferences());
102  EXPECT_EQ(visitor.total_visited, base->NumberOfReferences());
103  for (StackReference<mirror::Object>* ref : visitor.visited) {
104    EXPECT_TRUE(base->Contains(ref));
105  }
106}
107
108}  // namespace art
109