558a931409
Change-Id: I552086445a7e07792f9da85afa5edf23b6c450d5 Reviewed-on: https://dart-review.googlesource.com/44402 Reviewed-by: Siva Annamalai <asiva@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
195 lines
7.7 KiB
C++
195 lines
7.7 KiB
C++
// 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/resolver.h"
|
|
#include "platform/assert.h"
|
|
#include "vm/class_finalizer.h"
|
|
#include "vm/compiler/assembler/assembler.h"
|
|
#include "vm/compiler/jit/compiler.h"
|
|
#include "vm/dart_entry.h"
|
|
#include "vm/object.h"
|
|
#include "vm/symbols.h"
|
|
#include "vm/unit_test.h"
|
|
|
|
namespace dart {
|
|
|
|
// Setup function for invocation.
|
|
static void SetupFunction(const char* test_library_name,
|
|
const char* test_class_name,
|
|
const char* test_static_function_name,
|
|
bool is_static) {
|
|
Thread* thread = Thread::Current();
|
|
Zone* zone = thread->zone();
|
|
|
|
// Setup a dart class and function.
|
|
char script_chars[1024];
|
|
Utils::SNPrint(script_chars, sizeof(script_chars),
|
|
"class Base {\n"
|
|
" dynCall() { return 3; }\n"
|
|
" static statCall() { return 4; }\n"
|
|
"\n"
|
|
"}\n"
|
|
"class %s extends Base {\n"
|
|
" %s %s(String s, int i) { return i; }\n"
|
|
"}\n",
|
|
test_class_name, is_static ? "static" : "",
|
|
test_static_function_name);
|
|
|
|
String& url = String::Handle(
|
|
zone, is_static ? String::New("dart-test:DartStaticResolve")
|
|
: String::New("dart-test:DartDynamicResolve"));
|
|
String& source = String::Handle(zone, String::New(script_chars));
|
|
Script& script =
|
|
Script::Handle(zone, Script::New(url, source, RawScript::kScriptTag));
|
|
const String& lib_name = String::Handle(zone, String::New(test_library_name));
|
|
Library& lib = Library::Handle(zone, Library::New(lib_name));
|
|
lib.Register(thread);
|
|
EXPECT(CompilerTest::TestCompileScript(lib, script));
|
|
EXPECT(ClassFinalizer::ProcessPendingClasses());
|
|
}
|
|
|
|
// Setup a static function for invocation.
|
|
static void SetupStaticFunction(const char* test_library_name,
|
|
const char* test_class_name,
|
|
const char* test_static_function_name) {
|
|
// Setup a static dart class and function.
|
|
SetupFunction(test_library_name, test_class_name, test_static_function_name,
|
|
true);
|
|
}
|
|
|
|
// Setup an instance function for invocation.
|
|
static void SetupInstanceFunction(const char* test_library_name,
|
|
const char* test_class_name,
|
|
const char* test_function_name) {
|
|
// Setup a static dart class and function.
|
|
SetupFunction(test_library_name, test_class_name, test_function_name, false);
|
|
}
|
|
|
|
TEST_CASE(DartStaticResolve) {
|
|
const char* test_library_name = "ResolverApp";
|
|
const char* test_class_name = "A";
|
|
const char* test_static_function_name = "static_foo";
|
|
const int kTestValue = 42;
|
|
|
|
// Setup a static function which can be invoked.
|
|
SetupStaticFunction(test_library_name, test_class_name,
|
|
test_static_function_name);
|
|
|
|
const String& library_name = String::Handle(String::New(test_library_name));
|
|
const Library& library =
|
|
Library::Handle(Library::LookupLibrary(thread, library_name));
|
|
const String& class_name = String::Handle(String::New(test_class_name));
|
|
const String& static_function_name =
|
|
String::Handle(String::New(test_static_function_name));
|
|
|
|
// Now try to resolve and invoke the static function in this class.
|
|
{
|
|
const int kTypeArgsLen = 0;
|
|
const int kNumArguments = 2;
|
|
const Function& function = Function::Handle(Resolver::ResolveStatic(
|
|
library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
|
|
Object::empty_array()));
|
|
EXPECT(!function.IsNull()); // No ambiguity error expected.
|
|
const Array& args = Array::Handle(Array::New(kNumArguments));
|
|
const String& arg0 = String::Handle(String::New("junk"));
|
|
args.SetAt(0, arg0);
|
|
const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
|
|
args.SetAt(1, arg1);
|
|
const Smi& retval = Smi::Handle(
|
|
reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
|
|
EXPECT_EQ(kTestValue, retval.Value());
|
|
}
|
|
|
|
// Now try to resolve a static function with invalid argument count.
|
|
{
|
|
const int kTypeArgsLen = 0;
|
|
const int kNumArguments = 1;
|
|
const Function& bad_function = Function::Handle(Resolver::ResolveStatic(
|
|
library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
|
|
Object::empty_array()));
|
|
EXPECT(bad_function.IsNull()); // No ambiguity error expected.
|
|
}
|
|
|
|
// Hierarchy walking.
|
|
{
|
|
const String& super_static_function_name =
|
|
String::Handle(String::New("statCall"));
|
|
const String& super_class_name = String::Handle(String::New("Base"));
|
|
const int kTypeArgsLen = 0;
|
|
const int kNumArguments = 0;
|
|
const Function& super_function = Function::Handle(Resolver::ResolveStatic(
|
|
library, super_class_name, super_static_function_name, kTypeArgsLen,
|
|
kNumArguments, Object::empty_array()));
|
|
EXPECT(!super_function.IsNull()); // No ambiguity error expected.
|
|
}
|
|
}
|
|
|
|
TEST_CASE(DartDynamicResolve) {
|
|
const char* test_library_name = "ResolverApp";
|
|
const char* test_class_name = "A";
|
|
const char* test_function_name = "foo";
|
|
const int kTestValue = 42;
|
|
|
|
// Setup a function which can be invoked.
|
|
SetupInstanceFunction(test_library_name, test_class_name, test_function_name);
|
|
|
|
// Now create an instance object of the class and try to
|
|
// resolve a function in it.
|
|
const String& lib_name = String::Handle(String::New(test_library_name));
|
|
const Library& lib =
|
|
Library::Handle(Library::LookupLibrary(thread, lib_name));
|
|
ASSERT(!lib.IsNull());
|
|
const Class& cls = Class::Handle(
|
|
lib.LookupClass(String::Handle(Symbols::New(thread, test_class_name))));
|
|
EXPECT(!cls.IsNull()); // No ambiguity error expected.
|
|
|
|
Instance& receiver = Instance::Handle(Instance::New(cls));
|
|
const String& function_name = String::Handle(String::New(test_function_name));
|
|
|
|
// Now try to resolve and invoke the instance function in this class.
|
|
{
|
|
const int kTypeArgsLen = 0;
|
|
const int kNumArguments = 3;
|
|
ArgumentsDescriptor args_desc(
|
|
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
|
const Function& function = Function::Handle(
|
|
Resolver::ResolveDynamic(receiver, function_name, args_desc));
|
|
EXPECT(!function.IsNull());
|
|
const Array& args = Array::Handle(Array::New(kNumArguments));
|
|
args.SetAt(0, receiver);
|
|
const String& arg0 = String::Handle(String::New("junk"));
|
|
args.SetAt(1, arg0);
|
|
const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
|
|
args.SetAt(2, arg1);
|
|
const Smi& retval = Smi::Handle(
|
|
reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
|
|
EXPECT_EQ(kTestValue, retval.Value());
|
|
}
|
|
|
|
// Now try to resolve an instance function with invalid argument count.
|
|
{
|
|
const int kTypeArgsLen = 0;
|
|
const int kNumArguments = 1;
|
|
ArgumentsDescriptor args_desc(
|
|
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
|
const Function& bad_function = Function::Handle(
|
|
Resolver::ResolveDynamic(receiver, function_name, args_desc));
|
|
EXPECT(bad_function.IsNull());
|
|
}
|
|
|
|
// Hierarchy walking.
|
|
{
|
|
const int kTypeArgsLen = 0;
|
|
const int kNumArguments = 1;
|
|
ArgumentsDescriptor args_desc(
|
|
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
|
const String& super_function_name = String::Handle(String::New("dynCall"));
|
|
const Function& super_function = Function::Handle(
|
|
Resolver::ResolveDynamic(receiver, super_function_name, args_desc));
|
|
EXPECT(!super_function.IsNull());
|
|
}
|
|
}
|
|
|
|
} // namespace dart
|