// 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 "platform/assert.h" #include "vm/class_finalizer.h" #include "vm/class_table.h" #include "vm/dart_entry.h" #include "vm/globals.h" #include "vm/symbols.h" #include "vm/unit_test.h" namespace dart { TEST_CASE(ClassHierarchyAnalysis) { const char* kScriptChars = "class A {" " foo() { }" " bar() { }" "}\n" "class B extends A {" "}\n" "class C extends B {" " foo() { }" "}\n" "class D extends A {" " foo() { }" " bar() { }" "}\n"; TestCase::LoadTestScript(kScriptChars, NULL); EXPECT(ClassFinalizer::FinalizePendingClasses()); const String& name = String::Handle(String::New(TestCase::url())); const Library& lib = Library::Handle(Library::LookupLibrary(name)); EXPECT(!lib.IsNull()); const Class& class_a = Class::Handle( lib.LookupClass(String::Handle(Symbols::New("A")))); EXPECT(!class_a.IsNull()); const intptr_t class_a_id = class_a.id(); const Class& class_b = Class::Handle( lib.LookupClass(String::Handle(Symbols::New("B")))); EXPECT(!class_b.IsNull()); const intptr_t class_b_id = class_b.id(); const Class& class_c = Class::Handle( lib.LookupClass(String::Handle(Symbols::New("C")))); EXPECT(!class_c.IsNull()); const intptr_t class_c_id = class_c.id(); const Class& class_d = Class::Handle( lib.LookupClass(String::Handle(Symbols::New("D")))); EXPECT(!class_d.IsNull()); const intptr_t class_d_id = class_d.id(); const String& function_foo_name = String::Handle(String::New("foo")); const String& function_bar_name = String::Handle(String::New("bar")); const Function& class_a_foo = Function::Handle(class_a.LookupDynamicFunction(function_foo_name)); EXPECT(!class_a_foo.IsNull()); const Function& class_a_bar = Function::Handle(class_a.LookupDynamicFunction(function_bar_name)); EXPECT(!class_a_bar.IsNull()); const Function& class_c_foo = Function::Handle(class_c.LookupDynamicFunction(function_foo_name)); EXPECT(!class_c_foo.IsNull()); const Function& class_d_foo = Function::Handle(class_d.LookupDynamicFunction(function_foo_name)); EXPECT(!class_d_foo.IsNull()); const Function& class_d_bar = Function::Handle(class_d.LookupDynamicFunction(function_bar_name)); EXPECT(!class_d_bar.IsNull()); ClassTable* class_table = Isolate::Current()->class_table(); EXPECT(class_table != NULL); ZoneGrowableArray* a_subclass_ids = class_table->GetSubclassIdsOf(class_a_id); EXPECT_EQ(3, a_subclass_ids->length()); EXPECT_EQ(class_b_id, (*a_subclass_ids)[0]); EXPECT_EQ(class_c_id, (*a_subclass_ids)[1]); EXPECT_EQ(class_d_id, (*a_subclass_ids)[2]); ZoneGrowableArray* b_subclass_ids = class_table->GetSubclassIdsOf(class_b_id); EXPECT_EQ(1, b_subclass_ids->length()); EXPECT_EQ(class_c_id, (*b_subclass_ids)[0]); ZoneGrowableArray* c_subclass_ids = class_table->GetSubclassIdsOf(class_c_id); EXPECT_EQ(0, c_subclass_ids->length()); ZoneGrowableArray* d_subclass_ids = class_table->GetSubclassIdsOf(class_d_id); EXPECT_EQ(0, d_subclass_ids->length()); ZoneGrowableArray* foos = class_table->GetNamedInstanceFunctionsOf(*a_subclass_ids, function_foo_name); EXPECT_EQ(2, foos->length()); EXPECT_EQ(class_c_foo.raw(), (*foos)[0]->raw()); EXPECT_EQ(class_d_foo.raw(), (*foos)[1]->raw()); ZoneGrowableArray* class_a_foo_overrides = class_table->GetOverridesOf(class_a_foo); EXPECT_EQ(2, class_a_foo_overrides->length()); EXPECT_EQ(class_c_foo.raw(), (*class_a_foo_overrides)[0]->raw()); EXPECT_EQ(class_d_foo.raw(), (*class_a_foo_overrides)[1]->raw()); ZoneGrowableArray* bars = class_table->GetNamedInstanceFunctionsOf(*a_subclass_ids, function_bar_name); EXPECT_EQ(1, bars->length()); EXPECT_EQ(class_d_bar.raw(), (*bars)[0]->raw()); ZoneGrowableArray* class_a_bar_overrides = class_table->GetOverridesOf(class_a_bar); EXPECT_EQ(1, class_a_bar_overrides->length()); EXPECT_EQ(class_d_bar.raw(), (*class_a_bar_overrides)[0]->raw()); EXPECT(class_table->HasSubclasses(class_a_id)); EXPECT(class_table->HasSubclasses(class_b_id)); EXPECT(!class_table->HasSubclasses(class_c_id)); EXPECT(!class_table->HasSubclasses(class_d_id)); } } // namespace dart