| // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | #include "vm/handles.h" | 
 | #include "platform/assert.h" | 
 | #include "vm/dart_api_state.h" | 
 | #include "vm/flags.h" | 
 | #include "vm/heap/heap.h" | 
 | #include "vm/object.h" | 
 | #include "vm/unit_test.h" | 
 | #include "vm/zone.h" | 
 |  | 
 | namespace dart { | 
 |  | 
 | // Unit test for Zone handle allocation. | 
 | ISOLATE_UNIT_TEST_CASE(AllocateZoneHandle) { | 
 | #if defined(DEBUG) | 
 |   FLAG_trace_handles = true; | 
 | #endif | 
 |   // The previously run stub code generation may have created zone handles. | 
 |   int initial_count = VMHandles::ZoneHandleCount(); | 
 |   static const int kNumHandles = 65; | 
 |   // Create some zone handles. | 
 |   for (int i = 0; i < kNumHandles; i++) { | 
 |     const Smi& handle = Smi::ZoneHandle(Smi::New(i)); | 
 |     EXPECT(handle.IsSmi()); | 
 |     EXPECT_EQ(i, handle.Value()); | 
 |   } | 
 |   EXPECT_EQ(kNumHandles + initial_count, VMHandles::ZoneHandleCount()); | 
 |   // Create some more zone handles. | 
 |   for (int i = kNumHandles; i < (2 * kNumHandles); i++) { | 
 |     const Smi& handle = Smi::ZoneHandle(Smi::New(i)); | 
 |     EXPECT(handle.IsSmi()); | 
 |     EXPECT_EQ(i, handle.Value()); | 
 |   } | 
 |   EXPECT_EQ((2 * kNumHandles) + initial_count, VMHandles::ZoneHandleCount()); | 
 | } | 
 |  | 
 | // Unit test for Scope handle allocation. | 
 | ISOLATE_UNIT_TEST_CASE(AllocateScopeHandle) { | 
 | #if defined(DEBUG) | 
 |   FLAG_trace_handles = true; | 
 | #endif | 
 |   int32_t handle_count = VMHandles::ScopedHandleCount(); | 
 |   static const int kNumHandles = 65; | 
 |   // Create some scoped handles. | 
 |   { | 
 |     Thread* thread = Thread::Current(); | 
 |     HANDLESCOPE(thread); | 
 |     for (int i = 0; i < kNumHandles; i++) { | 
 |       const Smi& handle = Smi::Handle(Smi::New(i)); | 
 |       EXPECT(handle.IsSmi()); | 
 |       EXPECT_EQ(i, handle.Value()); | 
 |     } | 
 |     EXPECT_EQ((handle_count + kNumHandles), VMHandles::ScopedHandleCount()); | 
 |     // Create lots of scoped handles in a loop with a nested scope. | 
 |     for (int loop = 0; loop < 1000; loop++) { | 
 |       HANDLESCOPE(thread); | 
 |       for (int i = 0; i < 2; i++) { | 
 |         const Smi& handle = Smi::Handle(Smi::New(i + loop)); | 
 |         EXPECT(handle.IsSmi()); | 
 |         EXPECT_EQ(i + loop, handle.Value()); | 
 |       } | 
 |       EXPECT_EQ((handle_count + kNumHandles + 2), | 
 |                 VMHandles::ScopedHandleCount()); | 
 |     } | 
 |     EXPECT_EQ((handle_count + kNumHandles), VMHandles::ScopedHandleCount()); | 
 |     for (int i = 0; i < kNumHandles; i++) { | 
 |       const Smi& handle = Smi::Handle(Smi::New(i)); | 
 |       EXPECT(handle.IsSmi()); | 
 |       EXPECT_EQ(i, handle.Value()); | 
 |     } | 
 |     EXPECT_EQ((handle_count + (2 * kNumHandles)), | 
 |               VMHandles::ScopedHandleCount()); | 
 |   } | 
 |   EXPECT_EQ(handle_count, VMHandles::ScopedHandleCount()); | 
 | } | 
 |  | 
 | static void NoopCallback(void* isolate_callback_data, void* peer) {} | 
 |  | 
 | // Unit test for handle validity checks. | 
 | TEST_CASE(CheckHandleValidity) { | 
 | #if defined(DEBUG) | 
 |   FLAG_trace_handles = true; | 
 | #endif | 
 |   Dart_Handle handle = NULL; | 
 |   // Check validity using zone handles. | 
 |   { | 
 |     TransitionNativeToVM transition(thread); | 
 |     StackZone sz(thread); | 
 |     handle = reinterpret_cast<Dart_Handle>(&Smi::ZoneHandle(Smi::New(1))); | 
 |     { | 
 |       TransitionVMToNative to_native(thread); | 
 |       EXPECT_VALID(handle); | 
 |     } | 
 |   } | 
 |   EXPECT(!Api::IsValid(handle)); | 
 |  | 
 |   // Check validity using scoped handles. | 
 |   { | 
 |     Dart_EnterScope(); | 
 |     { | 
 |       TransitionNativeToVM transition(thread); | 
 |       HANDLESCOPE(thread); | 
 |       handle = reinterpret_cast<Dart_Handle>(&Smi::Handle(Smi::New(1))); | 
 |       { | 
 |         TransitionVMToNative to_native(thread); | 
 |         EXPECT_VALID(handle); | 
 |       } | 
 |     } | 
 |     Dart_ExitScope(); | 
 |   } | 
 |   EXPECT(!Api::IsValid(handle)); | 
 |  | 
 |   // Check validity using persistent handle. | 
 |   Dart_Handle scoped_handle; | 
 |   { | 
 |     TransitionNativeToVM transition(thread); | 
 |     scoped_handle = Api::NewHandle(thread, Smi::New(1)); | 
 |   } | 
 |   Dart_PersistentHandle persistent_handle = | 
 |       Dart_NewPersistentHandle(scoped_handle); | 
 |   EXPECT_VALID(persistent_handle); | 
 |  | 
 |   Dart_DeletePersistentHandle(persistent_handle); | 
 |   EXPECT(!Api::IsValid(persistent_handle)); | 
 |  | 
 |   // Check validity using weak persistent handle. | 
 |   handle = reinterpret_cast<Dart_Handle>(Dart_NewWeakPersistentHandle( | 
 |       Dart_NewStringFromCString("foo"), NULL, 0, NoopCallback)); | 
 |  | 
 |   EXPECT_NOTNULL(handle); | 
 |   EXPECT_VALID(handle); | 
 |  | 
 |   Dart_DeleteWeakPersistentHandle( | 
 |       reinterpret_cast<Dart_WeakPersistentHandle>(handle)); | 
 |   EXPECT(!Api::IsValid(handle)); | 
 | } | 
 |  | 
 | }  // namespace dart |