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 <sstream>
18 
19 #include "common_runtime_test.h"
20 #include "reference_queue.h"
21 #include "handle_scope-inl.h"
22 #include "mirror/class-inl.h"
23 #include "scoped_thread_state_change-inl.h"
24 
25 namespace art {
26 namespace gc {
27 
28 class ReferenceQueueTest : public CommonRuntimeTest {};
29 
TEST_F(ReferenceQueueTest,EnqueueDequeue)30 TEST_F(ReferenceQueueTest, EnqueueDequeue) {
31   Thread* self = Thread::Current();
32   ScopedObjectAccess soa(self);
33   StackHandleScope<20> hs(self);
34   Mutex lock("Reference queue lock");
35   ReferenceQueue queue(&lock);
36   ASSERT_TRUE(queue.IsEmpty());
37   ASSERT_EQ(queue.GetLength(), 0U);
38   auto ref_class = hs.NewHandle(
39       Runtime::Current()->GetClassLinker()->FindClass(self, "Ljava/lang/ref/WeakReference;",
40                                                       ScopedNullHandle<mirror::ClassLoader>()));
41   ASSERT_TRUE(ref_class != nullptr);
42   auto ref1(hs.NewHandle(ref_class->AllocObject(self)->AsReference()));
43   ASSERT_TRUE(ref1 != nullptr);
44   auto ref2(hs.NewHandle(ref_class->AllocObject(self)->AsReference()));
45   ASSERT_TRUE(ref2 != nullptr);
46   queue.EnqueueReference(ref1.Get());
47   ASSERT_TRUE(!queue.IsEmpty());
48   ASSERT_EQ(queue.GetLength(), 1U);
49   queue.EnqueueReference(ref2.Get());
50   ASSERT_TRUE(!queue.IsEmpty());
51   ASSERT_EQ(queue.GetLength(), 2U);
52 
53   std::set<mirror::Reference*> refs = {ref1.Get(), ref2.Get()};
54   std::set<mirror::Reference*> dequeued;
55   dequeued.insert(queue.DequeuePendingReference().Ptr());
56   ASSERT_TRUE(!queue.IsEmpty());
57   ASSERT_EQ(queue.GetLength(), 1U);
58   dequeued.insert(queue.DequeuePendingReference().Ptr());
59   ASSERT_EQ(queue.GetLength(), 0U);
60   ASSERT_TRUE(queue.IsEmpty());
61   ASSERT_EQ(refs, dequeued);
62 }
63 
TEST_F(ReferenceQueueTest,Dump)64 TEST_F(ReferenceQueueTest, Dump) {
65   Thread* self = Thread::Current();
66   ScopedObjectAccess soa(self);
67   StackHandleScope<20> hs(self);
68   Mutex lock("Reference queue lock");
69   ReferenceQueue queue(&lock);
70   std::ostringstream oss;
71   queue.Dump(oss);
72   LOG(INFO) << oss.str();
73   auto weak_ref_class = hs.NewHandle(
74       Runtime::Current()->GetClassLinker()->FindClass(self, "Ljava/lang/ref/WeakReference;",
75                                                       ScopedNullHandle<mirror::ClassLoader>()));
76   ASSERT_TRUE(weak_ref_class != nullptr);
77   auto finalizer_ref_class = hs.NewHandle(
78       Runtime::Current()->GetClassLinker()->FindClass(self, "Ljava/lang/ref/FinalizerReference;",
79                                                       ScopedNullHandle<mirror::ClassLoader>()));
80   ASSERT_TRUE(finalizer_ref_class != nullptr);
81   auto ref1(hs.NewHandle(weak_ref_class->AllocObject(self)->AsReference()));
82   ASSERT_TRUE(ref1 != nullptr);
83   auto ref2(hs.NewHandle(finalizer_ref_class->AllocObject(self)->AsReference()));
84   ASSERT_TRUE(ref2 != nullptr);
85 
86   queue.EnqueueReference(ref1.Get());
87   oss.str("");
88   queue.Dump(oss);
89   LOG(INFO) << oss.str();
90 
91   queue.EnqueueReference(ref2.Get());
92   oss.str("");
93   queue.Dump(oss);
94   LOG(INFO) << oss.str();
95 }
96 
97 }  // namespace gc
98 }  // namespace art
99