// 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, Dart_WeakPersistentHandle handle, 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(&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(&Smi::Handle(Smi::New(1))); { TransitionVMToNative to_native(thread); EXPECT_VALID(handle); } } Dart_ExitScope(); } EXPECT(!Api::IsValid(handle)); // Check validity using persistent handle. Isolate* isolate = Isolate::Current(); 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_NewWeakPersistentHandle( Dart_NewStringFromCString("foo"), NULL, 0, NoopCallback)); EXPECT_NOTNULL(handle); EXPECT_VALID(handle); Dart_DeleteWeakPersistentHandle( reinterpret_cast(isolate), reinterpret_cast(handle)); EXPECT(!Api::IsValid(handle)); } } // namespace dart