1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/handles.h"
6#include "platform/assert.h"
7#include "vm/dart_api_state.h"
8#include "vm/flags.h"
9#include "vm/heap/heap.h"
10#include "vm/object.h"
11#include "vm/unit_test.h"
12#include "vm/zone.h"
13
14namespace dart {
15
16// Unit test for Zone handle allocation.
17ISOLATE_UNIT_TEST_CASE(AllocateZoneHandle) {
18#if defined(DEBUG)
19 FLAG_trace_handles = true;
20#endif
21 // The previously run stub code generation may have created zone handles.
22 int initial_count = VMHandles::ZoneHandleCount();
23 static const int kNumHandles = 65;
24 // Create some zone handles.
25 for (int i = 0; i < kNumHandles; i++) {
26 const Smi& handle = Smi::ZoneHandle(Smi::New(i));
27 EXPECT(handle.IsSmi());
28 EXPECT_EQ(i, handle.Value());
29 }
30 EXPECT_EQ(kNumHandles + initial_count, VMHandles::ZoneHandleCount());
31 // Create some more zone handles.
32 for (int i = kNumHandles; i < (2 * kNumHandles); i++) {
33 const Smi& handle = Smi::ZoneHandle(Smi::New(i));
34 EXPECT(handle.IsSmi());
35 EXPECT_EQ(i, handle.Value());
36 }
37 EXPECT_EQ((2 * kNumHandles) + initial_count, VMHandles::ZoneHandleCount());
38}
39
40// Unit test for Scope handle allocation.
41ISOLATE_UNIT_TEST_CASE(AllocateScopeHandle) {
42#if defined(DEBUG)
43 FLAG_trace_handles = true;
44#endif
45 int32_t handle_count = VMHandles::ScopedHandleCount();
46 static const int kNumHandles = 65;
47 // Create some scoped handles.
48 {
49 Thread* thread = Thread::Current();
50 HANDLESCOPE(thread);
51 for (int i = 0; i < kNumHandles; i++) {
52 const Smi& handle = Smi::Handle(Smi::New(i));
53 EXPECT(handle.IsSmi());
54 EXPECT_EQ(i, handle.Value());
55 }
56 EXPECT_EQ((handle_count + kNumHandles), VMHandles::ScopedHandleCount());
57 // Create lots of scoped handles in a loop with a nested scope.
58 for (int loop = 0; loop < 1000; loop++) {
59 HANDLESCOPE(thread);
60 for (int i = 0; i < 2; i++) {
61 const Smi& handle = Smi::Handle(Smi::New(i + loop));
62 EXPECT(handle.IsSmi());
63 EXPECT_EQ(i + loop, handle.Value());
64 }
65 EXPECT_EQ((handle_count + kNumHandles + 2),
66 VMHandles::ScopedHandleCount());
67 }
68 EXPECT_EQ((handle_count + kNumHandles), VMHandles::ScopedHandleCount());
69 for (int i = 0; i < kNumHandles; i++) {
70 const Smi& handle = Smi::Handle(Smi::New(i));
71 EXPECT(handle.IsSmi());
72 EXPECT_EQ(i, handle.Value());
73 }
74 EXPECT_EQ((handle_count + (2 * kNumHandles)),
75 VMHandles::ScopedHandleCount());
76 }
77 EXPECT_EQ(handle_count, VMHandles::ScopedHandleCount());
78}
79
80static void NoopCallback(void* isolate_callback_data,
81 Dart_WeakPersistentHandle handle,
82 void* peer) {}
83
84// Unit test for handle validity checks.
85TEST_CASE(CheckHandleValidity) {
86#if defined(DEBUG)
87 FLAG_trace_handles = true;
88#endif
89 Dart_Handle handle = NULL;
90 // Check validity using zone handles.
91 {
92 TransitionNativeToVM transition(thread);
93 StackZone sz(thread);
94 handle = reinterpret_cast<Dart_Handle>(&Smi::ZoneHandle(Smi::New(1)));
95 {
96 TransitionVMToNative to_native(thread);
97 EXPECT_VALID(handle);
98 }
99 }
100 EXPECT(!Api::IsValid(handle));
101
102 // Check validity using scoped handles.
103 {
104 Dart_EnterScope();
105 {
106 TransitionNativeToVM transition(thread);
107 HANDLESCOPE(thread);
108 handle = reinterpret_cast<Dart_Handle>(&Smi::Handle(Smi::New(1)));
109 {
110 TransitionVMToNative to_native(thread);
111 EXPECT_VALID(handle);
112 }
113 }
114 Dart_ExitScope();
115 }
116 EXPECT(!Api::IsValid(handle));
117
118 // Check validity using persistent handle.
119 Dart_Handle scoped_handle;
120 {
121 TransitionNativeToVM transition(thread);
122 scoped_handle = Api::NewHandle(thread, Smi::New(1));
123 }
124 Dart_PersistentHandle persistent_handle =
125 Dart_NewPersistentHandle(scoped_handle);
126 EXPECT_VALID(persistent_handle);
127
128 Dart_DeletePersistentHandle(persistent_handle);
129 EXPECT(!Api::IsValid(persistent_handle));
130
131 // Check validity using weak persistent handle.
132 handle = reinterpret_cast<Dart_Handle>(Dart_NewWeakPersistentHandle(
133 Dart_NewStringFromCString("foo"), NULL, 0, NoopCallback));
134
135 EXPECT_NOTNULL(handle);
136 EXPECT_VALID(handle);
137
138 Dart_DeleteWeakPersistentHandle(
139 reinterpret_cast<Dart_WeakPersistentHandle>(handle));
140 EXPECT(!Api::IsValid(handle));
141}
142
143} // namespace dart
144